티스토리 뷰

hacking/web

dojo by example(5) - 애니메이션/효과

Ho Eyo He Hum! iolo 2008.08.02 21:28
이번에 알아볼 내용은 애니메이션/효과를 위한 기능이다.

기본 효과
간단한 효과들이지만 dojo base에 포함되어 있어서 dojo.js 파일 하나만 있으면 편하게 쓸 수 있다.
  • dojo.fadeIn(args) : 지정한 노드를 서서히 불투명하게 만든다. args는 여러가지 파라메터를 묶은 해시다. dojo에서는 이런 식의 파라메터를 즐겨쓴다.
  • dojo.fadeOut(args) : 지정한 노드를 서서히 투명하게 만든다.
  • dojo.animateProperty(args) : 지정한 노드의 (CSS) 속성을 연속적으로 변화시킨다. 이 함수만 활용하면 대부분의 효과를 만들 수 있다.
간단한 예를 들어 보면:

dojo.fadeOut(
    node: 'title',
   duration: 1000,
   delay: 250
  }).play();

250ms를 기다린 후, 1000ms(1초)동안 id가 title인 노드를 천천히 표시한다(불투명). fadeOut대신 fadeIn을 사용하면 숨긴다(투명).

dojo.animateProperty({
    node: 'title',
    properties: {
        width:{ start:10, end:500, unit:'px' },
        opacity: { start:0, end:1 },
        backgroundColor: { start: '#ff0000', end: '#00ff00' }.
        fontSize: { start:10, end:20, unit:'pt'},
   },
    duration:500
});

500ms(0.5초) 동안 domNode의 너비를 10px에서 500px로, 투명에서 불투명으로,  배경색을 빨강에서 초록으로, 글꼴 크기를 10pt에서 20pt로... 부드럽게~ 바꾼다. 즉, 위의 dojo.fadeIn/fadeOut()은 dojo.animateProperty()로 쉽게 구현할 수 있다.

좀 더 복잡한(그래봐야 길어 보일 뿐~) 예를 만들어보자:
<html>
<head>
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.1.1/dojo/dojo.xd.js"></script>
<style type="text/css">
#welcome { display:none; position:absolute; top:50px; left:50px; width:300px; height:200px; border:2px solid #cc0000; background-color:#00ff00; color:#0000ff; }
</style>
<script type="text/javascript">
var showWelcome = function() {
  // fadeIn이 효과가 있으려면 먼저 투명하게 만들어둬야 한다.
  dojo.style('welcome', { opacity: '0', display: 'block' });
  dojo.fadeIn({
    node: 'welcome',
    duration: 1000,
    delay: 1000
  }).play();
};

var flyWelcome = function() {
  var bodyBox = dojo.contentBox(dojo.body());
  var welcomeBox = dojo.contentBox('welcome');
  var goArgs = {
    node: 'welcome',
    properties: {
      left: bodyBox.w - welcomeBox.w,
      top: bodyBox.h - welcomeBox.h
    },
    duration: dojo.byId('flyTime').value * 1000, // 밀리초
  };
  var goAnim = dojo.animateProperty(goArgs);
  goAnim.play();
};

var hideWelcome = function() {
  dojo.fadeOut({
    node: 'welcome',
    duration: 1000,
    delay: 100,
    onEnd: function() { dojo.style('welcome', 'display', 'none'); }
  }).play();
  // 애니메이션은 비동기로 일어난다.
  // 여기에 dojo.style('welcome', 'display', 'none');를 넣으면
  // 애니메이션을 시작하자마자 바로 사라져버리므로(display:none),
  // 스르륵 사라지는(투명도를 조절하는) 효과를 볼 수 없게된다.
};

dojo.addOnLoad(showWelcome);
</script>
</head>
<body>
<h1>Hello, World!</h1>
<p>Blah Blah...</p>

<div id="welcome">
<h1>Welcome!</h1>
<p>Blah Blah...</p>
<p>
<button onclick="flyWelcome()">Fly me to the moon</button>
during <input type="text" id="flyTime" value="1" size="5" /> seconds.
</p>
<button onclick="hideWelcome()">Let it be</button>
</div>

</body>
</html>

페이지가 로딩되면 잠시 뒤에 Welcome 창(?)이 스르륵~ 나타난다. 여기서 Let it be를 누르면 창이 스르륵~ 사라지고, Fly me to the moon을 누르면 지정한 시간동안 창이 아래쪽 구석으로 날아간다.
예제 자체는 별거 없지만, 중간에 코멘트 중에 중요한 내용이 있다. 애니메이션은 항상 비동기로 진행된다는 사실을 명심하자. 동기를 맞추려면 그래서 onBegin, onEnd 등의 이벤트를 이용해야 한다.

고급 효과(dojo.fx 패키지)
dojo base에 효과를 자꾸 추가하면 dojo.js 파일의 크기가 너무 커지므로, dojo.fx 라는 별도의 패키지를 만들었다. 따라서 아래의 효과들을 사용하기 전에 dojo.require('dojo.fx');를 실행해야 한다.
  • dojo.fx.chain([애니메이션객체들...]) : 여러 개의 효과을 순서대로 실행하는 복합 효과.
  • dojo.fx.combine([애니메이션객체들...]) : 여러 개의 애니메이션을 동시에 실행하는 복합 효과.
  • dojo.fx.slideTo({ node: 노드, top: 세로좌표, left: 가로좌표 }) : 노드를 지정한 좌표로 이동하는 효과.
  • dojo.fx.wipeIn({ node: 노드 }) : 노드의 높이를 점점 크게하면서 나타나는 효과.
  • dojo.fx.wipeOut({ node: 노드 }) : 노드의 높이를 점점 줄이면서 사라지는 효과.
  • dojo.fx.Toggler(args) : 지정한 효과를 사용해서 노드를 show/hide() 하는 도우미 클래스. 동일한 효과로 show/hide()를 반복할 경우 편리하게 쓸 수 있다.
백문이불일견, 백견이불여일런!
말로 설명하려고 해도 말재주가 부족하니... 소스코드로 때우기로 하자.
<html>
<head>
<script type="text/javascript" djConfig="isDebug:true" src="http://o.aolcdn.com/dojo/1.1.1/dojo/dojo.xd.js"></script>
<style type="text/css">
#overlay { z-index:999; position:absolute; overflow:hidden; top:0; left: 0; right:0; bottom: 0; width:100%; height:100%; background:#000; }
#lightbox { z-index:1000; position:absolute; overflow:hidden; top:0; left:0; background:#fff; }
#lightbox div { border:1px solid #000; padding:20px; }
</style>
<script type="text/javascript">
dojo.require('dojo.fx');

var showLightbox = function() {
  var s1 = dojo.fadeIn({ node:'overlay', end: 0.5 });
  var s2 = dojo.fx.wipeIn({ node:'lightbox' });
  var s3 = dojo.fx.slideTo({ node:'lightbox', top:100, left:0 });
  var s4 = dojo.fx.slideTo({ node:'lightbox', top:200, left:300 });
  fx = dojo.fx.chain([s1, s2, s3, s4]);
  dojo.connect(fx, 'onBegin', function() {
    dojo.style('overlay', 'display', 'block');
    dojo.style('lightbox', 'display', 'block');
    fx.stop();
  });
  fx.play();
};

var hideLightbox = function() {
  var h1 = dojo.fx.slideTo({ node:'lightbox', top:200, left:0 });
  var h2 = dojo.fx.slideTo({ node:'lightbox', top:0, left:0 });
  var h3 = dojo.fx.wipeOut({ node:'lightbox' });
  var h4 = dojo.fadeOut({ node:'overlay' });
  var fx = dojo.fx.combine([h1, h2, h3, h4]);
  dojo.connect(fx, 'onEnd', function() {
    dojo.style('overlay', 'display', 'none');
    dojo.style('lightbox', 'display', 'none');
    fx.stop();
  });
  fx.play();
};

dojo.addOnLoad(function() {
  dojo.style('overlay', 'display', 'none');
  dojo.style('lightbox', 'display', 'none');
});
</script>
</head>
<body>

<p>Click the picture to show in the light box:</p>
<img src="photo.jpg" width="80" onclick="showLightbox()" />

<div id="overlay"></div>

<div id="lightbox">
  <div>
    <img src="photo.jpg" onclick="hideLightbox()" />
  </div>
</div>

</body>
</html>

페이지가 로딩된 다음, 작은 이미지를 클릭하면 뭔가 어수선한 애니메이션이 나오고 창(레이어)에 큰 이미지가 표시된다. 큰 이미지를 클릭하면 역시 어수선한 에니메이션이 나오고 창(레이어)이 닫힌다. 쉽게 얘기해서 어수선한 LightBox 다. 나도 안다... 하나도 안 비슷하다는 거... 그래도 조금만 손을 보면... -.-;;;;
중간에 보면 dojo.fx.combine()dojo.fx.chain()을 쓴 부분이 있는데... 위의 코드를:
dojo.fx.chain([f1, dojo.fx.combine([f2, f3]), f4]); 처럼 바꾸면 f1이 먼저 진행되고, f2와 f3는 동시에 진행되고, 그 다음에 f4가 진행된다. 예를 들려다보니 저렇게 됐지만, 잘 엮으면 멋진 효과를 쉽게~ 만들 수 있다. 정말 잘~ 엮어야 된다. 뭔 소린지는 엮어 보면 안다. -.-;;;
그리고 dojo.addOnLoad()를 사용해서 페이지가 로딩된 직후 overlay와 lightbox노드를 숨기고(display: none)있는데, 이는 보이지 않는 노드에 대해서 높이 계산을 안하는 불여우의 버그(또는 기능)를 피하기 위한 꼼수다.

혹시 prototype을 사용하고 있다면 script.aculo.us를 사용해서 비슷한 효과(더욱 현란한 효과)를 낼 수 있다. prototype과 scrit.aculo.us에 관심이 있는 분들은 인사이트에서 번역 출판한 프로토타입과 스크립타큘러스를 참조하시라(절때! 내가 추천글을 썼다거나 교정을 봤다거나 해서 이러는 건 아니고...-.-;;;; 프로토타입 관련 책 중에서는 원서도 제일 좋고, 번역도 제일 좋다).

오늘은 이 정도로 하고... 다음은 이벤트 시스템~

댓글
댓글쓰기 폼