웹 애니메이션 2/3 ㅡ keyframe animation 방식

웹에서 애니메이션을 제공하는 방식 중 두번째는 Keyframe 개념으로 접근하는 것입니다. 이는 전체 애니메이션을 100%라고 할때 각 단계마다 애니메이션될 속성값을 지정해 주는 방식으로써 그 중간 화면은 자동으로 계산해 줍니다. 아래의 화면은 Key frame Animation 방식을 사용한 애니메이션에 대한 화면입니다.

[xyz-ihs snippet=”keyframe-Animation”]

위의 화면에 대한 예를 통해 키프레임 애니메이션을 정리해 보겠습니다.

가장 먼저 움직이는 노란 사각형에 대한 div에 대한 코드입니다.

이 div의 클래스는 box인데, 아직 크기와 색상과 같은 스타일이 지정되지 않은 상태이므로 이 box 클래스에 해당 스타일을 아래처럼 지정합니다.

    .box {
        width: 100px;
        height: 100px;
        background: #ffd800;
        box-shadow: 0 10px 20px rgba(0,0,0,0.5);

        animation-name: movingBox;
        animation-duration: 2300ms;
        animation-iteration-count: infinite;
        animation-direction: alternate;
    }

2~5번가지의 코드가 div의 크기와 색상 그리고 그림자에 대한 스타일 지정입니다. 7~10번 코드는 키프레임 애니메이션에 대한 스타일입니다. 7번 코드는 구체적인 키프레임에 대한 아이디값이고, 8번은 애니메이션이 진행되는 시간을 2.3초로 지정했으며, 9번은 무한반복, 10번은 무한반복시 반복방향을 지정하는 코드입니다. 이제 7번에서 지정한 키프레임에 대한 아이디인 movingBox에 대한 정의는 다음과 같습니다.

@keyframes movingBox {
    0% {
        transform: translate(0, 0);
        opacity: 0.3;
    }

    25% {
        opacity: 0.9;
    }

    50% {
        transform: translate(400px, 0);
        opacity: 0.2;
    }

    100% {
        transform: translate(100px, 0);
        opacity: 0.8;
    }
}

코드를 살펴보면, 초기단계(0%)와 1/4지점(25%) 그리고 중간지점(50%) 및 끝지점(100%)의 상태에서의 위치와 투명도를 지정함으로써, 각 단계의 중간결과를 자동으로 계산하여 애니메이션이 이루어지도록 하고 있습니다.

웹 애니메이션 1/3 ㅡ Transition 방식

이글은 웹에서 화면에 표시된 객체에 대한 애니메이션을 적용하는 방식 중 Transition 방식에 대한 정리입니다. 현대의 UI에 애니메이션을 적용한다는 것은 사용자에게 영감을 불어 넣을 수 있다는 점에 매우 철학적이고 세련된 방법이라고 할 수 있습니다.

먼저 아래의 화면에서 ‘터치미!’ 텍스트(div 요소)를 클릭해 보시기 바랍니다.

[xyz-ihs snippet=”Transition”]

클릭할 때마다 좌에서 우로.. 우에서 좌로 이동하는 것을 살펴볼 수 있습니다. 위의 예제에 대한 코스를 살펴 보겠습니다. 먼저 화면에 표시되는 ‘터치미!’에 대한 div 요소입니다.

터치미!

div에 box라는 클래스를 지정하고 있습니다. box 클래스에 대한 정의는 다음과 같습니다.

    .box {
        font-family: '맑은 고딕';
        text-align: center;
        line-height: 100px;

        width: 100px;
        height: 100px;

        background: #FFF;
        box-shadow: 0 10px 20px rgba(0,0,0,0.5);

        transform: translate(0, 0);
        transition: transform 1000ms;
    }

2번~4번 코드는 div의 ‘터치미!’ 텍스트에 대한 폰트와 정렬을 지정하고 있고, 6번~7번은 div의 너비와 높이에 대한 크기를 지정하고 있습니다. 그리고 9~10번 코드는 div의 색상과 그림자를 표시하도록 하고 있습니다. 12번은 최초의 div의 위치를 (0, 0) 좌표로 지정하고 있습니다. 13번 코드가 바로 애니메이션을 위한 transition(전환)을 지정하고 있는데, transform에 대해 1초(1ms) 동안 애니메이션이 이루어지도록 하고 있습니다. 그러나 여기서는 아직 transform에 대해 어떤 전환이 이루어질지에 대한 코드는 없습니다. 이떤 전환이 이루어지는 시점은 이 div를 클릭할 때인데, 다음의 코드가 필요합니다.

var box = document.querySelector('.box');

box.addEventListener('click', function () {
    box.classList.toggle('move');
});

box.addEventListener('transitionend', function () {
    alert('이동 완료');
}, false);

3번 코드에서 div에 대한 클릭 이벤트를 지정하고 있습니다. 즉, div에 move라는 클래스를 토글링하고 있는데요. 토글링은 해당 값이 지정되어 있으면 제거하고, 지정되어 있지 않으면 지정하는 방식입니다. move 클래스는 다음과 같습니다. (참고로 7번 코드는 하나의 애니메이션이 완료되었을 때 호출되는 함수를 지정하고 있음)

    .box.move {
        transform: translate(400px, 0);
    }

보시면 transform 속성에 대해서 x축으로 400px로 변경하고 있습니다.

jQuery를 이용해 DOM의 크기 얻기

아래와 같은 Visual DOM 객체가 있다고 하자. jQuery를 이용해 이 객체의 가로와 세로에 대한 픽셀 크기를 얻는 코드에 대해 정리해 봅니다.

Visual DOM 객체는 눈에 보이는 것, 즉 본래의 모양과 외곽선(Border) 이외에도 Padding과 Margin와 같은 보이지 않지만 활용에서 유용한 속성을 갖는다. 아래의 그림을 보면..

위의 그림은 w3schools.com에서 jQuery 튜토리얼에서 가져온 그림입니다.

그림에서 함수는 jQuery에서 얻는 DOM 객체에 대한 것입니다. 정리를 하면 아래와 같습니다.

  • width(), height() ㅡ Padding, Border, Margin을 제외한 크기
  • innerWidth(), innerHeight() ㅡ Border, Margin을 제외한 크기
  • outerWidth(), outerHeight() ㅡ Margin을 제외한 크기
  • outerWidth(true), outerHeight(true) ㅡ Padding, Border, Margin을 모두 포함한 크기

특히나 위의 width와 height 함수는 크기를 얻는(get) 기능을 하면서도 인자를 받으면 해당 인자의 값만큼 크기를 설정하는(set) 기능도 갖습니다.

이제 이 글의 맨 앞에서 보인 DOM 객체(ID가 div1임)에 대한 스타일을 살펴봄으로써 Border, Padding, Margin의 값을 살펴볼 수 있습니다.

#div1 {
    height: 100px;
    width: 300px;
    padding: 10px;
    margin: 3px;
    border: 2px solid blue;
    background-color: lightblue;
}

ID가 div1인 div를 jQuery로 얻어 그 크기 몇가지를 얻는 코드는 아래와 같습니다.

$(document).ready(function () {
    $("button").click(function () {
        var div = $("#div1");
        var txt = "";

        txt += "Width of div: " + div.width() + "
"; txt += "Height of div: " + div.height() + "
"; txt += "Outer width of div (margin included): " + div.outerWidth(true) + "
"; txt += "Outer height of div (margin included): " + div.outerHeight(true); div.html(txt); }); });

실행하고 이벤트가 설정된 버튼을 클릭하면 아래와 같은 결과를 살펴볼 수 있습니다.

참고로 위의 예제에서 사용한 body 부분의 DOM 구성 코드는 아래와 같습니다.


    
>/div>

HTML5의 requestAnimationFrame 함수

HTML5를 지원하는 웹브라우저 기반의 JavaScript의 window 객체에는 requestAnimationFrame 함수가 정의되어 있습니다. 더 정확히는, 이 함수는 WebGL의 지원과 함께 제공됩니다. 이 함수는 지정된 연산(함수)의 호출을 다른 연산에 방해를 주지 않고 최대한 빨리 호출해 주는 함수입니다. 웹GL에서 이 함수의 용도를 충분히 짐작할 수 있습니다.

네, 아래의 애니메이션은 requestAnimationFrame 함수를 사용한 예제 입니다. 이 예제를 통해 requestAnimFrame 함수에 대해 정리해 보겠습니다.

[xyz-ihs snippet=”requestAnimationFrame2″]

위의 예제에 대한 코드를 살펴보겠습니다. 먼저 애니메이션이 이루어지는 캔버스에 대한 정의 코드입니다.


다음은 requestAnimationFrame 함수가 아직 지원이 되지 않을 경우, 또는 브러우저 마다 서로 다른 이름으로 함수로 제공되는 문제에 대한 해법으로 일괄적으로 requestAnimFrame이라는 함수로 지원되도록 하는 코드입니다.

window.requestAnimFrame = (function(callback) {
    return window.requestAnimationFrame || 
    window.webkitRequestAnimationFrame || 
    window.mozRequestAnimationFrame || 
    window.oRequestAnimationFrame || 
    window.msRequestAnimationFrame ||
    function(callback) { window.setTimeout(callback, 1000 / 60); };
})();

위의 코드를 보면 만약 어떠한 requestAnimationFrame 함수도 지원되지 않을 경우 1000/60밀리초 후에 발생하는 Timer를 사용하고 있습니다.

다음은 캔버스에 사각형을 렌더링하고 애니메이션을 수행하는 코드입니다.

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');

var myRectangle = {
    x: 0,
    y: 75,
    width: 100,
    height: 50,
    borderWidth: 5
};

drawRectangle(myRectangle, context);

setTimeout(function() {
    var startTime = (new Date()).getTime();
        animate(myRectangle, canvas, context, startTime);
    }, 2000);

4번 코드가 캔버스에 렌더링할 사각형의 스펙입니다. 12번 코드를 통해 이 사각형의 스펙대로 렌더링합니다. 그리고 14번 코드에서 2초 후에 animation 함수를 호출하고 있는데요. 바로 이 animation 함수가 실제 requestAnimFrame 함수를 이용하여 애니메이션을 수행하는 함수입니다.

drawRectangle 함수는 다음과 같습니다.

function drawRectangle(rect, context) {
    context.beginPath();
    context.rect(rect.x, rect.y, rect.width, rect.height);
    context.fillStyle = '#8ED6FF';
    context.fill();
    context.lineWidth = rect.borderWidth;
    context.strokeStyle = 'black';
    context.stroke();
}

그리고 animation 함수는 다음과 같습니다.

function animate(rect, canvas, context, startTime) {
    var time = (new Date()).getTime() - startTime;
    var linearSpeed = 100;
    var newX = linearSpeed * time / 1000;

    if(newX < canvas.width - rect.width - rect.borderWidth / 2) {
        rect.x = newX;
    }

    context.clearRect(0, 0, canvas.width, canvas.height);

    drawRectangle(rect, context);

    requestAnimFrame(function() {
        animate(rect, canvas, context, startTime);
    });
}

2~4번 코드는 사각형를 움직이도록 새롭게 설정할 x 좌표값을 계산하여 newX 변수에 할당합니다. 6~8번 코드는 계산한 newX 변수를 사각형의 x 속성에 할당하는 것으로써 만약 사각형이 캔버스 밖으로 벗어나지 않도록 하고 있습니다. 10번 코드는 새로운 위치의 사각형을 그리기에 앞서 화면을 지우는 코드이고 12번 코드는 실제로 화면에 사각형을 그리는 함수의 호출이며, 14~16번이 바로 requestAnimFrame 함수를 통해 animate 함수를 호출해 주는 것입니다. 이처럼 animate 함수의 호출을 requestAnimFrame 함수를 통해 등록해 놓으면 가장 적합하고 빠른 시점에 animate 함수를 호출해주게 됩니다.

jQuery UI를 이용한 대화상자(Dialog) 표시하기

jQuery 라이브러리를 이용한 UI, 즉 jQuery UI에는 기본적인 Button에서부터 Accordion까지 다양한 UI를 제공합니다. 그 중 대화상자(Dialog)에 대해 살펴 보도록 하겠습니다.

흐름은 3가지입니다. 첫째는 Dialog의 기능을 담을 DIV를 선언하고, 두번째는 jQuery와 jQuery UI에 대한 자바스크립트 라이브러리를 추가하고, 세번째는 앞서 선언한 DIV에 대해 dialog() 함수를 호출해 주는 것이 기본적인 내용의 전부입니다.

아래는 jQuery UI를 이용한 다이얼로그에 대한 화면입니다.

위의 화면을 구성하기 위한 전체 코드는 아래와 같습니다.




    
    jQuery UI - DialogBox

    
    
    
    

    


    

Message

앞서 언급한 세가지 흐름에 해당하는 코드는, 첫째인 Dialog의 기능을 담을 DIV를 선언은 20번, 두번째로 jQuery와 jQuery UI에 대한 자바스크립트 라이브러리를 추가는 10번과 11번, 세번째인 앞서 선언한 DIV에 대해 dialog() 함수를 호출해 주는 것은 15번입니다.

jQuery UI는 자바스크립트와 HTML 테그를 이용하여 매우 직관적이고 간단하게 원하는 UI로써의 기능(생명력)을 불어 넣을 수 있는 좋은 라이브러리라고 생각됩니다.