들어가며

패럴랙스 스크롤링 웹 사이트의 세계로 들어갈 준비는 되었나요? 패럴랙스 스크롤을 사용한 사이트는 많습니다. 안타깝게도 일부 사이트에 있는 패럴랙스 스크롤링은 사용자들의 주의를 분산시키거나 보여주고자 했던 콘텐츠가 아닌 다른 곳으로 사용자들의 눈을 돌리지만, 제대로만 사용한다면 훨씬 더 빼어난 웹을 만들 수 있습니다. 패럴랙스는 잘만 사용된다면 사용자들이 더 실감 나는 매력적인 방식으로 콘텐츠를 탐색할 수 있도록 도와줍니다.

최근 우리팀은 콘텐츠 일부에 패럴랙스 스크롤 애니메이션을 사용하기 시작했습니다. 우리는 ADT의 역사라는 페이지에서 약간의 아이디어를 얻고, 유명 드라마인 워킹 데드에 대한 인터랙티브 좀비 인포그래픽을 만들어보기로 했습니다. 오늘은 이 프로젝트의 무대 뒤로 여러분을 데려가 굉장히 유용했던 Skrollr.js라는 자바스크립트 플러그인의 사용법을 보여주려고 합니다.

메인 좀비 이미지

간단히 말해서 Skrollr는 HTML과 CSS를 사용해 정교한 스크롤 기반 애니메이션(패럴랙스 혹은 그 밖의 것)을 만드는 플러그인입니다. Skrollr의 수많은 장점은 공식 문서에서 찾아볼 수 있습니다. 이 글에서 우리는 자바스크립트와 스프라이트 몇 개를 사용해 사용자가 스크롤을 앞뒤로 움직임에 따라 반응하는 보행 애니메이션을 간단하게 만들어보겠습니다. 이 글을 끝까지 따라가면, 패럴랙스 환경에서 걷는 캐릭터가 인간에서 좀비로 변하는 것도 볼 수 있습니다.

먼저 몇 가지 소스 파일을 다운로드 받으세요. 워킹 데드 프로젝트에서 사용했던 이미지 몇 장과 자바스크립트 파일, HTML 뼈대가 있을 것입니다. 이제 이 파일들을 가지고 삽질을 시작해보겠습니다.

1단계 - 패럴랙스 백그라운드

HTML5 data- 속성을 추가한 <div> 몇 개를 추가해서 패럴랙스 백그라운드 레이어 두 장을 만들어 보겠습니다. 또한, 스타일시트에 CSS도 약간 추가하고 우리가 작성한 main.js 파일에서 Skrollr의 .init() 함수도 호출할 것입니다. 다음 코드에서 보듯 패럴랙스 레이어는 id="skrollr-body"가 설정된 엘리먼트의 자식 노드여야 합니다. 지금 보기에는 클래스와 ID가 너무 많다 싶을 수 있지만, 나중에 엘리먼트를 조금 더 추가하게 되면 이유가 있었음을 알게 될 것입니다.

HTML:

<div id="skrollr-body">
	<div id="Scene">
		<div id="bg1" class="parallax-layer"
			data-0="left:0px;"
			data-5000="left:-1000px;">
		</div>
		<div id="bg2" class="parallax-layer"
			data-0="left:0px;"
			data-5000="left:-2500px;">
		</div>
	</div>
</div>

우리가 보게될 마술같은 일은 모두 data- 속성 덕분입니다. Skrollr를 호출하면, Skrollr는 #skrollr-body 안에 있는 모든 엘리먼트를 탐색하며 엘리먼트에 설정된 data- 속성을 사용해 적절한 애니메이션을 구현합니다. data- 뒤에 붙은 숫자는 사용자가 스크롤 한 픽셀의 수이며, 속성의 값은 해당 스크롤 위치에 왔을 때 현재의 요소에 설정할 스타일입니다. #bg1를 예로 들면, 사용자가 페이지 상단(data-0)으로부터 페이지 아래로 5,000 픽셀(data-5000)만큼 스크롤하면 #bg1이 왼쪽으로 1000 픽셀만큼 움직이는 애니메이션이 나타날 것입니다. 설정한 값을 보면 Skollr는 대략 사용자 스크롤 5픽셀마다 왼쪽으로 1픽셀씩 #bg1을 옮길 것입니다. 이 애니메이션은 앞으로도 뒤로도 일어나므로 사용자는 어느쪽으로든 스크롤 할 수 있으며 Skrollr이 적절한 애니메이션을 보여줄 것입니다.

#bg2data-* 속성에 설정된 값을 살펴보면 사용자 스크롤 2픽셀마다 #bg2가 1픽셀씩, 다시 말해 #bg1보다 훨씬 빨리 움직이는 것을 알 수 있습니다. 이 덕분에 3D 공간 같은 느낌이 날 것입니다. 그러나 이 코드를 실행하기 전에 이미지를 추가한 후 액자처럼 감싸는 CSS를 추가해야 합니다. 그 후에는 Skrollr의 초기화 함수도 호출해야 하고요.

CSS:

화면은 700px 높이의 프레임에 수직 중간 정렬되게 합니다.

#Scene{
	position: fixed;
	width: 100%;
	height: 700px;
	margin-top: -350px;
	top: 50%;
	}
.parallax-layer{
	position: absolute;
	height: 700px;
	background-repeat: no-repeat;
	}
#bg1{
	background: url(../images/bg-1.jpg);
	width: 3528px;
	}
#bg2{
	background: url(../images/bg-2.png) left bottom;
	/* 이미지가 꽤 크지만... 사용할만한 가치가 있습니다 */
	width: 4368px;
	}


JavaScript:

skrollr.init();

잠시 후에는 여기에 다른 작업을 더 추가할 것이므로 여기까지 작업한 내용을 별도 파일로 저장했습니다. 하지만, 여러분은 굳이 그렇게 하지 않아도 됩니다.

이것 보세요! 패럴랙스가 만들어졌네요!

2단계 - 전경 엘리먼트

다음으로는 전경에 몇 가지 요소를 추가해보겠습니다. 구름, 해, 학교를 추가한 후 캐릭터도 추가할 것입니다. 이 중 학교는 캐릭터가 인간에서 좀비로 변신할 때 잠시 캐릭터를 숨기는 용도로 사용합니다.

먼저 두 번째 구름 레이어를 추가해봅시다. 이 구름 레이어는 #bg2와 같은 속도로 화면을 가로질러 이동할 것이므로, #bg2 안에 구름 레이어를 추가하여 (절대 위치에 기반한) 동일한 애니메이션이 적용되도록 합니다. 이처럼 내부에 있는 div는 부모의 CSS 위치 속성을 그대로 사용하는 경우가 많습니다.

HTML:

<div id="bg2" class="parallax-layer"
	data-0="left:0px;"
	data-5000="left:-2500px;">
	<div id="cloud"></div>
</div>

CSS:

#cloud{
	position:absolute;
	background:url(../images/clouds.png);
	width:2059px;
	height:347px;
	}

이제 학교와 아직 좀비가 되기 전인 캐릭터를 추가해보겠습니다. 학교는 #bg2보다 살짝 더 빠르게 움직이게 할 것입니다. 또한, 학교를 그릴 때 뒤쪽과 앞쪽 레이어를 나누고 그 사이에 좀비 캐릭터를 두어서 마치 캐릭터가 문을 통과해서 지나가는 것처럼 보이게 할 것입니다.

HTML:

<div class="parallax-layer">
	<div id="schoolunder" class="school"
		data-0="left:2000px;"
		data-5000="left:-1500px;">
	</div>
	<div id="zombie"></div>
	<div id="schoolover" class="school"
		data-0="left:2000px;"
		data-5000="left:-1500px;">
	</div>
</div>

CSS:

캐릭터는 화면 왼쪽에서 300px만큼 떨어진 곳에 그대로 있되 배경이 화면 좌우로 움직이도록 하여 마치 예전에 보던 횡 스크롤 게임 느낌이 나도록 했습니다.

#zombie{
	position:absolute;
	background-image:url(../images/zombify.png);
	width:250px;
	height:190px;
	top:340px;
	left:300px;
	}
.school{
	position:absolute;
	width:600px;
	height:523px;
	top:100px;
	}
#schoolunder{
	background:url(../images/school_under.png);
	}
#schoolover{
	background:url(../images/school_over.png);
	}

이제 이 캐릭터는 마치 스케이트를 타듯 미끄러지며 화면을 이동하는 것처럼 보일 텐데, 여기에 보행 애니메이션과 짤막한 좀비 변신 애니메이션을 추가해보겠습니다. 그전에 해 이미지부터 추가하고 넘어가죠. 우리는 5개의 data 속성을 사용하여 해가 뜨고 지는 애니메이션을 표현했습니다. 이 엘리먼트는 #bg1#bg2 사이에 둘 것이므로 하늘 배경보다는 앞에 보이지만 전경 엘리먼트 뒤쪽을 이동하게 될 것입니다.

HTML:

<div id="bg1" class="parallax-layer"
	data-0="left:0px;"
	data-5000="left:-1000px;">
</div>
<div id="sun"
	data-0="top:200px;"
	data-2000="top:25px;"
	data-3000="top:0px;"
	data-4000="top:25px;"
	data-5000="top:50px;">
</div>
<div id="bg2" class="parallax-layer"
	data-0="left:0px;"
	data-5000="left:-2500px;">
</div>

CSS:

#sun {
	position:absolute;
	background:url(../images/sun.png);
	width:194px;
	height:194px;
	left:180px;
	}

우리가 지금까지 한 내용을 확인해보세요. 꽤 괜찮지만, 아직 다듬어야 할 부분이 남아 있습니다.

3단계 - 계속 걷게 하기 (& 좀비로 변신하기)

이제 캐릭터에 생명력을 불어넣을 때입니다. 캐릭터의 보행 및 변신 애니메이션에 필요한 이미지 프레임은 다운로드 받은 .png 스프라이트 파일 안에 있습니다. 처음에는 인간이었다가 나중에 좀비로 변할 것입니다. 이 프레임들을 배경 이미지로 보여주고 사용자의 스크롤에 따라 주기적으로 반복시키는 자바스크립트를 작성해보겠습니다. 스크롤을 어느 쪽으로 하든 동작하게 만들어서 정말 게임 같은 느낌을 내보겠습니다.


좀비화를 표현하는 스프라이트

data-* 속성을 사용하여 Skrollr가 배경 이미지를 애니메이션으로 만들게 할 수도 있지만, 이 방법은 속성을 꽤 많이 작성해야 하므로 직접 함수를 작성하기로 합니다. 직접 작성한 덕분에 약간의 유연함도 얻을 수 있으며 코드의 유지보수도 확실히 더 편해졌습니다. 우리는 skrollr.init()를 호출할 때 우리가 작성한 함수를 인수로 전달할 것입니다. 조금 더 자세히 말하자면 beforerender 리스너 함수로 할당하여 Skrollr가 애니메이션의 각 프레임을 그리기 직전에 자동으로 호출되게 할 것입니다(beforerender를 비롯한 Skrollr의 다른 옵션은 문서를 참고하세요). beforerender에는 curTop이라는 프로퍼티를 가진 객체가 인수로 전달됩니다. curTop은 현재 스크롤이 상단으로부터 얼마나 떨어졌는가를 알려주는, 다시 말해 페이지 상단으로부터 사용자가 스크롤 한 픽셀의 양을 알려주는 숫자입니다. 우리는 이 값을 사용하여 배경 이미지로 사용한 스프라이트를 앞으로 움직일 것인지 뒤로 움직일 것인지 또는 인간을 좀비로 바꿔야 할 때인지 정하겠습니다.

보행 애니메이션부터 작업한 후 인간에서 좀비로 변신하는 과정을 추가하겠습니다.

JavaScript:

var zombie = $('#zombie'),
	pLocs = [0, -250, -500, -750, -1000, -1250, -1500]
	curFrm = 0,
	lastStep=0;

skrollr.init({
	beforerender: function(o){
		// 마지막에 백그라운드 이미지를 움직인 후에
		// 사용자가 50픽셀 아래로 스크롤하면
		// 앞으로 이동해야 하므로 스프라이트에 있는
		// 다음 프레임으로 옮긴다.
		if(o.curTop > lastStep + 50) {
			if (curFrm>=6){ curFrm=-1; }
			zombie.css('background-position', pLocs[curFrm++] + 'px 0px');
			lastStep = o.curTop;
		// 사용자가 50픽셀 위로 스크롤하면
		// 뒤로 이동해야 하므로 이전 프레임으로 옮긴다.
		} else if(o.curTop < lastStep - 50) {
			if (curFrm<=0){ curFrm=7; }
			zombie.css('background-position', pLocs[curFrm--] + 'px 0px');
			lastStep = o.curTop;
		}
	}
});
  • zombie — 캐릭터를 표현하는 div에 대한 참조
  • pLocs — 스프라이트의 각 프레임이 왼쪽 끝으로부터 떨어진 픽셀 위치를 담은 배열
  • curFrm — pLoc에 있는 보행 애니메이션 프레임 중 현재 사용 중인 프레임의 인덱스
  • lastStep — 가장 최근에 배경 이미지를 움직였던 스크롤 위치. 프레임을 앞/뒤 어느 쪽으로 이동할 것인지 계산할 때 사용

멋지네요! 어려운 부분이 끝났습니다. 우리의 좀비는 걷기 시작할 테고요. 이제 남은 단계는 좀비로 변신!밖에 없습니다.

어쩌면 워킹 데드 드라마와 약간 다를지도 모르는데, 이 프로젝트에서는 캐릭터의 좀비 변신이 학교(zombie school)로 표현되었습니다. 덕분에 이 과정은 상대적으로 편했습니다. 인간이 걷는 장면의 프레임과 좀비가 걷는 장면의 프레임은 같은 이미지에 있었고 인간이 걷는 장면 바로 뒤에 좀비가 걷는 장면이 있었으므로 사용자가 캐릭터가 학교를 지나가는 장면이 나오는 곳을 스크롤 할 때 #zombie 레이어 배경 이미지의 위치만 적당히 바꿔주면 됐습니다. 인간이 걷는 장면은 7프레임인데 반해 좀비가 걷는 장면은 4프레임 밖에 안 들어서 애니메이션이 조금 더 유연하게 동작하도록 코드를 살짝 손봐야 했습니다. 수정된 부분은 아래에 굵은 글씨로 표시해두었습니다.

JavaScript:

var zombie = $('#zombie'),
	pLocs = [0, -250, -500, -750, -1000, -1250, -1500],
	curFrm = 0,
	lastStep=0,
	// We need just a couple extra variables
	animationCycle, backPosY;

skrollr.init({
	beforerender: function(o){
		// 사용자가 2800픽셀 이하로 스크롤하면
		// 캐릭터를 그대로 인간인 상태로 두고
		// 그 이상 스크롤하면 좀비로 바꾼다.
		if(o.curTop < 2800) {
			animationCycle=7;
			backPosY= '0px';
		} else {
			animationCycle=4;
			backPosY= '-190px';
		}
		if(o.curTop > lastStep + 50) {
			if (curFrm>=animationCycle-1){ curFrm=-1; }
			zombie.css('background-position', pLocs[++curFrm] + 'px ' + backPosY);
			lastStep=o.curTop;
		} else if(o.curTop < lastStep - 50) {
			if (curFrm<=0){ curFrm=animationCycle; }
			zombie.css('background-position', pLocs[--curFrm] + 'px ' + backPosY);
			lastStep = o.curTop;
		}
	}
});

그럼 이제 끝났습니다. 지금 막 우리는 게임 스타일의 패럴럭스 스크롤링을 만들었습니다. 축하합니다! 만약 더 다듬어진 버전을 보고 싶다면 우리팀이 작성한 워킹 데드 데모를 확인해보세요.

마무리

여기서 한 것은 Skrollr로 할 수 있는 기능의 겉핥기에 지나지 않습니다. 따라서 가능하다면 다른 많은 기능에 대해서도 꼭 읽어볼 것을 추천합니다. 애니메이션에 이징(easing)을 적용하거나 data 속성과 상수를 조합해서 사용하거나(유지보수에 좋습니다) Skrollr 스타일 시트에 프레임을 추가하는 대신 마크업에 전체 키프레임을 넣는 등 흥미로운 기능이 많습니다.

끝으로 잠깐 몇 마디 덧붙이려고 합니다. 가끔 웹 디자이너인 우리들은 매체의 노예처럼 느껴질 때가 있습니다. 웹에는 제약이 많고 크로스 브라우저와 크로스 디바이스 이슈에서 오는 어려움도 많습니다. 최소한 저는 여러 매체에서 디자인과 개발을 하는 한 사람으로서 간혹 매체의 노예처럼 느껴질 때가 있습니다. 하지만 이러한 브라우저 기반 매체에는 매우 독특한 면이 있는 것도 사실입니다. 예를 들어, 스크롤링 덕분에 사용자와 이런 식으로 인터랙션 할 수 있는 기회가 생겼습니다. 개인적으로 디자이너들은 이런 고유한 특성을 알아두어야 하며, 항상 이러한 특성을 훌륭한 경험으로 창조해 낼 방법을 찾아야 한다고 생각합니다.


이 글은 Elli Bishop이 오페라 개발자 사이트에 게시한 Creating Game-Style Parallax Scrolling: Zombie Edition을 번역한 글입니다.

Posted by 행복한고니 트랙백 0 : 댓글 1

댓글을 달아 주세요

  1. addr | edit/del | reply BlogIcon 먹튀 검증 2018.07.26 21:07 신고

    잘보고갑니다

사용자 삽입 이미지
Andrew Wooldridge씨가 CanvasQuest라는 단순한 Rogue 와 비슷한 게임을 만들었습니다. 맵 로딩 같은 재밌는 기능도 포함되어있고, 스프라이트를 통해 텍스트를 렌더링하는데 그래픽을 사용했습니다.

from Canvas Quest: Roque like RPG game on Ajaxian
Posted by 행복한고니 트랙백 0 : 댓글 0

댓글을 달아 주세요

사용자 삽입 이미지

또 다시 Jacob Seidelin 씨의 작품입니다. 아예 JavaScript 게임이라는 분야를 만들 작정으로 보일 정도네요. ^^;; 이번 작품은 수퍼 마리오 카트입니다. 당연히 JavaScript를 이용했습니다.

대부분의 렌더링은 canvas 엘리먼트를 이용했으며, FF2, FF3, Opera(9.27과 beta) 그리고 Safari 3.1.1에서 동작합니다. Safari에서는 카트 스프라이트에 사소한 결함이 있습니다만, 게임을 즐기는 데는 지장이 없을 것 같습니다. 또한, WebKit nightly 빌드를 이용하신다면, 최신판인지 확인해보시길 바랍니다. 최근의 몇몇 버전들은 canvas에 문제가 있었습니다. IE 지원은 고려하고 있지 않습니다. 죄송합니다.

(축소된) 코드의 용량은 11kb이지만 지난달의 마리오 게임과는 다르게 몇개의 외부 이미지 파일을 사용했습니다. 이것은 게임을 보다 부드럽게 즐기기 위한 테스트이지만, 어쨌든 파일 크기는 중요하지 않습니다. 제가 보기엔 꽤 괜찮습니다.

몇 가지의 렌더링 옵션을 설정할 수 있습니다. "Quality" 는 얼마나 많은 수직선이 렌더링 되느냐를 다루고, "Screen scale"은 화면의 크기를 다룹니다. 둘 다 시각적인 효과와 성능을 맞바꾸는 옵션들입니다.

달려보실래요?

from JavaScript Super Mario Kart on Ajaxian
Posted by 행복한고니 트랙백 0 : 댓글 2

댓글을 달아 주세요

  1. addr | edit/del | reply BlogIcon 시리니 2008.05.31 13:39

    허허;; 정말 대단합니다!

따로 설명은 필요없을 것 같습니다. jQuery를 이용해서 만든 Cubespace를 확인해보시면 되니까요.
통통 튀는 애니메이션이 꽤 귀엽습니다. ^^
Cubespace

from Cubespace : Isometric Pixel Fun on Ajaxian
Posted by 행복한고니 트랙백 0 : 댓글 2

댓글을 달아 주세요

  1. addr | edit/del | reply BlogIcon daybreaker 2008.05.23 05:52

    저걸로 블럭 수백개 들어가는 거 만들어봤는데 scalability가 아무래도 떨어지더군요.;; 처음 몇 개 놓을 땐 통통 튀고 괜찮은데 한 200개쯤 놓기 시작하면 클릭과 반응 사이에 몇 초씩 딜레이가...orz

Live Chess
Piotr Dachtera씨가 자신이 예전에 만들었던 체스를 Comet을 이용해 보다 확장성있도록 만들었습니다. 클라이언트 사이드에는 dojox.cometd 를 사용했고 서버로는 Jetty를 사용했습니다. Dylan씨가 이에 대한 글을 작성했습니다.

Mathieu Nouzareth씨는 역시 Jetty와 Comet 기술을 사용한 Flash 기반 게임 플랫폼인 Cafe.com에 대한 글을 코멘트에 남겼습니다.

from Live Chess with Comet on Ajaxian

Posted by 행복한고니 트랙백 0 : 댓글 0

댓글을 달아 주세요

Pictionary


XSketch는 "여러명이 즐기는 단어 스케치 게임입니다. Adobe Flash, Java, Ajax, GWT 등을 이용해 작성되었습니다. 게임 진행방법은 다른 게이머들에게 자신이 가진 단어를 맞추도록 그림을 그려 설명하는(혹은 그 반대로) Pictionary와 유사합니다.

Ryan Dewsbury 씨가 이 게임을 만들어 그의 컬렉션 GPokrKDice에 추가했습니다.

이건 특히 중독성있네요!

from XSketch: Pictionary with GWT on Ajaxian
Posted by 행복한고니 트랙백 0 : 댓글 0

댓글을 달아 주세요

Pierre Chassaing 씨가 Prototype과 Script.aculo.us를 이용해서 JavaScript로 ProtoRPG라는 롤 플레잉 게임을 만들었습니다. 느낌은 꼭 NetHack 스타일인 것 같습니다.

ProtoRPG

ProtoRPG


이 글은 현재 Ajaxian 에서 삭제된 상태입니다.
Posted by 행복한고니 트랙백 0 : 댓글 0

댓글을 달아 주세요

from Super Mario; 14KB of JavaScript on Ajaxian

사용자 삽입 이미지
Jacob Seidelin씨가 재밌는 것을 만들어냈습니다. 14KB의 코드로 닌텐도의 히트작인 수퍼 마리오 게임을 만들었네요.

한 개의 JavaScript 파일에 작게 유지되는 실험을 하나 했습니다. 어떠한 이미지를 비롯 어떠한 외부 파일도 사용되지 않았으며, 모든 것은 canvas 엘리먼트와 구식 방법인 div 생성/배열(IE에서)으로만 렌더링됩니다. 스프라이트는 인코딩된 문자열에 저장되며 각 스프라이트 당 4색상만 허용하는 포맷을 이용합니다. 하지만 각 스프라이트별로 40~60 바이트 정도의 용량은 차지합니다.

우리는 base64로 인코딩된 (URI 형태의) MIDI 음악도 있습니다. IE에서는 음악이 없고, 브라우저마다 조금씩의 사소한 문제가 있는 것 같지만, 작업 예정에 있습니다.

Posted by 행복한고니 트랙백 0 : 댓글 0

댓글을 달아 주세요