삼각함수로 구현한 예제를 (SVG I)

앞서 정리한 코드로 (SVG II)

다시 작성하면 다음과 같다.

clock4.html

먼저 CSS 클래스를 3개 작성하였다.

시계 구조(face), 시간(number), 시계 바늘(hands)에 대한

고정된 디자인 값을 가지고 있다 [라인 2 ~ 15].


drawFace에서 두 개의 원(circle)을

createElement로 간단하게 생성하였다.

하나는 시계의 외곽선 [라인 34],

나머지는 시계의 중심을 그리는 원이다 [라인 35].

외곽선은 CSS 클래스를 이용하였고(face)

중심 원은 검은색(#000)으로 채웠다.


시간 표시는 (drawNumbers)

글자를 출력하던 것을 (fillText)

Text 태그를 생성하여 구현한다 [라인 44].

Text 태그에 글자를 넣기 위해

createTextNode를 이용하는 불편함이 있다 [라인 46].


마지막으로

시계 바늘은 선을 그리던 것을 (lineTo)

라인(line) 태그를 생성하였다 [라인 76].


정리하면

Canvas에서는 필요한 도형을 함수를 이용하여 그렸고

SVG에서는 필요한 도형을 태그로 생성했다.

그리고, CSS로 디자인 부분을 분리하였다.


이상의 내용을 타이머를 이용하여

시계처럼 실행하면 문제가 생길 수 있다.

Canvas에서는

타이머가 1초마다 drawClock 함수를 호출하여

시계 구조, 시간, 시계 바늘을

모두 다시 그리기 때문에 중복 되어 실행해도 문제가 없다.


SVG에서는 모두 태그로 생성하게 되는데

1초마다 모든 것을 새로 생성하면

무한대로 계속 생성하기 때문에 여러가지 문제가 생기게 된다.

따라서, 시계 구조, 시간, 시계 바늘을 한 번 생성한 후,

매 초마다 시계 바늘의 위치만 바꾸는 방식으로 구현해야 한다.

var clock = document.getElementById('clock');
var center = parseInt(clock.style.height) / 2;
var radius = center * 0.90;

drawFace(radius);
drawNumbers(radius);

var hourHand = drawHand(0, 0, radius*0.07);
var minuteHand = drawHand(0, 0, radius*0.07);
var secondHand = drawHand(0, 0, radius*0.02);

drawClock();

function drawClock() {
    drawTime(radius);
    setTimeout(drawClock, 1000);
}

~~생략 ~~

function drawTime(radius){
    var now = new Date();
    var hour = now.getHours();
    var minute = now.getMinutes();
    var second = now.getSeconds();
    var pos = radius*0.5;
   
    //hour
    x = pos* Math.cos(Math.PI* ((hour*30)- 90 + 30/60*minute + 30/60/60*second) / 180);
    y = pos* Math.sin(Math.PI* ((hour*30)- 90 + 30/60*minute + 30/60/60*second) / 180);
    setAttributes(hourHand, {"x1": center, "y1": center, "x2": x+center, "y2": y+center});

    //minute
    pos = radius*0.8;
    x = pos * Math.cos(Math.PI* ((minute * 6)- 90 + 6/60*second)/ 180);
    y = pos * Math.sin(Math.PI* ((minute * 6)- 90 + 6/60*second)/ 180);
    setAttributes(minuteHand, {"x1": center, "y1": center, "x2": x+center, "y2": y+center});
   
    // second
    pos = radius*0.9;
    x = pos * Math.cos(Math.PI* ((second * 6)- 90)/ 180);
    y = pos * Math.sin(Math.PI* ((second * 6)- 90)/ 180);
    setAttributes(secondHand, {"x1": center, "y1": center, "x2": x+center, "y2": y+center});
}

~~생략 ~~

function setAttributes(ele, attributes) {
    for (var item in attributes) ele.setAttribute(item, attributes[item]);
}

clock5.html

drawClock 함수에서 생성하던 것을

모두 함수의 밖(앞)으로 빼서 한번만 실행되도록 하고

타이머가 drawClock를 매초마다 실행하게 작성한다.


새로 작성한 setAttributes는

Json의 값(도형들의 속성)을 주어진 개수만큼 반복해서

도형에 속성들을 부여하는 역할을 하는 함수이다.


이 함수를 (setAttributes)

시계 바늘을 생성하던 drawHand 함수 대신 사용했다.

즉, 생성하는 것이(drawHand) 아닌

속성을 바꾸는 것으로 작성한 것(setAttributes)이다.

속성을 바꾸기 위해

시계 바늘을 시, 분, 초로 구별하여 알아야 하기 때문에

생성 후 변수(hourHand, minuteHand, secondHand)로 받아서 사용한다.


 


이번에는 D3로 구현해 본다.

D3는 데이터 시각화 프레임워크로 알려져 있는데

SVG(Scalable Vector Graphic)를 쉽게 사용하도록 해준다.

자세한 내용은 찾아보길 바라고

SVG와 D3의 사용법과 변환에 대한 설명은 여기를 참고 하면 된다.


SVG와 D3의 관계는

자바스크립트와 JQuery의 관계와 유사하다.

한마디로 쉽게 사용하게 해준다는 것이고

실제로 D3 사용법은 JQuery사용법과 비슷하다.


D3와 관련해서 여기서 알아야 할 것은

getElementById 대신에 select를 사용한다 [라인 3].

createElementNS와 appendChild로 생성하던 것을

append로 한번에 생성한다.

setAttribute함수 대신에 attr함수를 사용하고

style 속성이 아닌 style 함수를 사용한다.

attr와 style 함수는 달라진 것이 없는 것 같지만

Json을 이용하여

한번에 많은 속성이나 style을 지정할 수 있다.

(setAttributes 함수 처럼)


그리고 편리한 method chaining이 있다.

이것은 다음 코드에서 보는 것처럼

지정된 노드(태그)에 메소드(함수)를 이어서 사용하는 것이다.


이러한 기능으로 인해

중복 코드 처리를 위해 작성한

createElement, setAttributes 함수가 필요 없다.

clock6.html

먼저 D3를 사용하기 위해 d3.js파일을 포함해야 한다.

간단하게 배포하기 위해

D3 사이트에서 제공하는 파일을 연결했다 [라인 1].


d3.select로 SVG 태그를 찾아서 clock변수에 지정한다 [라인 3].

그리고, 필요한 도형들을 추가(append)로 간단하게 생성한다.

예로, 원(circle)을 추가만으로 생성하고

메소드 체인으로 속성을 지정하였다 [라인 22].

attr("cx", center).attr("cy", center).attr("r", radius).attr("class", "face")

이렇게 생성할 수도 있지만

23라인과 같이

필요한 속성을 Json으로 묶어서 한번에 처리할 수도 있다.

일부러 22와 23라인 코드를 두가지 방식으로 구현하였으니

선호하는 방식을 이용하면 된다.


D3에서는 문자열을 출력하기 위해

TextNode를 생성하지 않고

Text 함수를 호출한다 [라인 32].

Text 생성은 메소드 체인과 Json을 같이 사용하여 간단하게 생성하였다.


마지막으로 시, 분 초 시계 바늘을

매초마다 이동시키는 것도

각 변수 속성을 Json으로 한번에 지정하였다 [라인 47, 53, 59].


이 정도면 D3의 장점과 특징을 간단하게 나마

파악하고 익힐 수 있을 것이다.


지금까지 아날로그 시계를

Canvas에서

기준 축을 이동시켜서 구현하는 방법

삼각 함수로 계산해서 구현하는 방법을 정리하였다.

그리고, 삼각 함수로 구현 것을 SVG와 D3로 구현하였다.


하나의 아날로그 시계를 구현하는데,

Canvas에서는 그림처럼 그렸고

SVG에서는 태그를 생성하였다.

D3에서는 몇가지 함수를 호출 하는 것으로 SVG를 구현하였다.

이상의 코드들을 자세히 본다면

Canvas, SVG, D3처럼 개발하는 도구(프레임워크 또는 개발언어)는 바뀌어도

변하지 않는 것(알고리즘, 수식 등)이 있다는 것을 알 수 있다.

변하지 않는 것을 공부하는 것이 중요할 것이다.


이외에도 자바 스크립트로 DIV를 생성해서 구현할 수도 있다.

자바 스크립트 대신에 JQuery로 구현할 수도 있다.

여기에서는 정리하지 않지만

직접 해보면 실력 향상에 많은 도움이 될 것이다.




자바 스크립트(JavaScript)를 이용하여

간단한 TreeGrid를 제작해 본다.

TreeGrid는 다음 그림(EasyUI TreeGrid)처럼

데이터를 트리와 그리드(List)의 결합 형태로 출력하는

라이브러리를 의미한다.


여기서는 실제로 사용할 수 있는 TreeGrid를 만드는 것이 아니라

간단한 TreeGrid를 단계별로 구현해 보면서

TreeGrid원리와

자바스크립트, Json 사용법 등을 설명하려고 한다.


실제 사용은 TreeGrid jQuery, EasyTree

무료(MIT) 라이브러리 등이 많이 있으니

이것을 그대로 사용하는 것이 좋고,

여기서는 간단하게 TreeGrid를 만들어 보면서

실력을 향상 시키는 것이 목적이다.


예제도 이 라이브러리에서 사용된 일부 코드를 가져와서 구성했으며

본 내용을 다루는 기본을 이해하고

차후 이 라이브러리를 분석해 보면 실력 향상에 도움이 될 것이다.


기본적으로 자바 스크립트, JQuery, JSON의 기본적인 사용법은 알고 있어야 하고,

모르는 경우 찾아보길 바란다.


구성 단계는 다음과 같이 6단계로 세분화하여 정리하였다.

  1. 트리용 데이터(JSON)을 화면에 출력
  2. 데이터(JSON)를 트리형(계층형)으로 보여 주기 위해 들여쓰기
  3. 라이브러리화
  4. 클릭시 자식 노드 숨기기
  5. 클릭시 자식 노드 숨김 / 보이기
  6. 버그 수정

이 단계를 거쳐도 실제적인 TreeGrid를 만들지는 못한다.

TreeGrid를 제작하는 원리를 익히며

자바스크립트(JavaScript)와 JQuery, Json 사용법 등을 익히는 것이 목적이다.


+ Recent posts