[Canvas]검색결과, 17건
- [HTML5 Game] Character Animation Using Sprites 2013.09.17
- [HTML5 Game] Character Animation 2013.09.14 (1)
- [HTML5 실습] Canvas를 이용한 텍스트-> 이미지 변환기 2010.10.13 (2)
- [HTML5 실습] Canvas에 그린 그림을 이미지로 만들기 2010.10.08 (6)
- jQuery Visualize, HTML5 차트 라이브러리 소개 2010.09.15
- RGraph, HTML5 그래프 라이브러리 소개 2010.09.14
- [HTML5] Canvas 2010.08.19 (3)
이전 글에서 캐릭터의 움직임을 위한 애니메이션 기법을 알아봤다.
이전 글: http://m.mkexdev.net/235
이 글에서는 캐릭터 애니메이션을 처리하기 위해 각각의 동작을 분리된 개별 이미지로 처리했었다.
하지만 이런 방식은 많은 이미지 리소스를 다운로드 해야 하기 때문에 비효율적이다.
이번 글에서는 Image Sprites 기법을 이용해 애니메이션을 구현하는 예를 살펴 보겠다.
Image Sprites 모든 캐릭터의 모든 동작을 하나의 이미지로 만들어 필요한 부분만 잘라내서 사용하는 방식으로 리소스의 다운로드 비용을 줄이고 효율성을 높이는 기법으로 실제 게임 개발에 많이 사용되고 있기도 하다.
아래 그림은 http://opengameart.org 의 샘플 이미지로 8 * 36 즉, 총 8가지 패턴의 서로 다른 동작 36개를 하나의 이미지로 모아놓은 것이다. 이번 예에서는 이 이미지를 Sprites 해서 애니메이션을 구현해 볼 것이다.
* 간단한 개념
HTML5 Canvas에 이미지를 그릴 때, 이미지 원본의 특정 좌표에서 원하는 너비,높이 만큼 이미지를 그릴 수 있다. 예를 들어 아래 그림과 같이 4개의 서로 다른 모습이 하나의 이미지에 포함되어 있을 때 개별 이미지의 너비/높이 값으로 특정 이미지 좌표와 크기를 산출할 수 있으며 이렇게 산출된 값으로 원하는 영역의 이미지를 Canvas에 그릴 수 있게 된다. 즉 아래 그림과 같이 4개의 동작일 경우, (0,0) ~ (384,0)까지 128*128 크기로 차례대로 그려주면 되는 것이다.
* HTML
HTML은 이전 글과 동일한 구조다.
<html lang="en">
<head>
<script type="text/javascript" src="js/animationCharacterUsingSprites.js"></script>
</head>
<body>
<canvas id="GameCanvas" width="300" height="300" style="border: 1px solid #000;">
HTML5 Canvas를 지원하지 않습니다. 크롬 또는 사파리와 같은 HTML5 지원 브라우저를 이용해 주세요
</canvas>
</body>
</html>
* JavaScript
자바스크립트 역시 전체적인 흐름은 이전 글의 내용과 동일하다.
다만 이전 글에서는 개별 이미지를 담는 배열과 이 배열의 인덱스를 탐색하기 위한 프레임 값의 업데이트가 있었던 것에 반해, 여기서는 하나의 이미지에서 원하는 부분을 잘라내기 위한 이미지 X좌표 값의 업데이트가 구현된다.
1. 캐릭터, 생성자 함수와 메서드
/* Define Character Class */
function Character(assetObj,canvasElement){
this.assetObj = assetObj; //Custom Asset Object
this.canvasSize = {width: canvasElement.width, height: canvasElement.height}; //Canvas Size
this.canvasContext = canvasElement.getContext('2d'); //Canvas Context
this.spritesX = 0; //Image X Position
}
Character.prototype.startAnimation = function(){
//Clear Canvas
this.canvasContext.clearRect(0, 0, this.canvasSize.width, this.canvasSize.height);
//Draw Image on Canvas
this.canvasContext.drawImage(this.assetObj.assetImage,
this.spritesX * this.assetObj.spritesWidth, this.assetObj.spritesY,
this.assetObj.spritesWidth, this.assetObj.spritesHeight,
100, 100,
this.assetObj.spritesWidth, this.assetObj.spritesHeight);
//Update Sprite Image X Position
this.spritesX = ++this.spritesX % this.assetObj.spritesCount;
}
이번 코드의 생성자 함수에서는 이미지 배열이 아닌 하나의 이미지 정보를 담고 있는 커스텀 객체를 매개변수로 전달받는다. 그리고 원본 이미지에서 잘라 낼 X 좌표 값을 위한 spritesX 변수를 선언하였다. 이 변수는 총 36개의 동작의 X좌표 계산을 위한 변수이며 '0 에서 35'의 값을 가지게 된다. 이 값에 개별 동작의 너비 값인 128px를 곱해 주면 0 ~ 4480 즉, 실제 잘라 낼 이미지의 X좌표를 계산할 수 있게 된다.
HTML5의 Canvas는 원본 이미지에서 원하는 부분을 잘라내어 그릴 수 있도록 아래와 같은 매개변수를 가진 drawImage()함수를 제공한다.
drawImage 매개변수>
- image, in float sx, in float sy, in float sw, in float sh, in float dx, in float dy, in float dw, in float dh
drawImage 매개변수 설명>
- 이미지 객체, 자르기 X 값, 자르기 Y 값, 자를 너비, 자를 높이, 그릴 위치 X 값, 그릴 위치 Y 값, 그릴 너비, 그릴 높이
(실제 제대로 된 해석은 원본 X값, 대상 X값.. 이런 식이지만 원본 이미지를 자른다는 개념을 명확히 하기 위해 임의대로 설명함)
2. 프로그램 로직
하나의 이미지만을 사용하기 때문에 이전 코드에 비해 전역변수가 줄어 들었다. 그리고 초당 프레임 수인 fps도 15로 작게 설정되었다. 샘플을 실행해 보면 알겠지만 초당 30 프레임으로 동작시키면 캐릭터가 너무 빠르게 움직이므로 적절한 값으로 변경해 주었다.
var character; //Character Instance
var canvasElement; //Canvas Element
var asset; //Asset Image Ojbect
그리고 초기화 함수를 보면 단 한개의 이미지만을 로딩하는 것을 확인할 수 있으며 이미지 객체와 개별 동작의 수, 개별 이미지의 너비/높이 및 Y 좌표 값을 담은 커스텀 객체를 생성해서 캐릭터 객체의 생성자 함수로 전달해 주고 있다. 이 값들을 이용해 원본 이미지에서 어떤 부분의 이미지들을 애니메이션 할 것인가가 결정된다.
canvasElement = document.getElementById("GameCanvas");
//Create Asset Image Ojbect
asset = new Image();
asset.src = 'image/zombie.png';
//Assign Imgae Load Event
asset.onload = onAssetLoadComplete;
}
function onAssetLoadComplete(){
//Create Custom Asset Object
var assetObj =
{assetImage:asset, spritesCount:36, spritesWidth:128, spritesHeight:128,
spritesY: 128 * 0};
//Create Character Instance
character = new Character(assetObj,canvasElement);
//Run Game Loop
setInterval(animationLoop, 1000 / fps);
}
function animationLoop(){
character.startAnimation();
}
window.addEventListener("load", init, false);
실행화면
코드를 실행하면 좀비가 걸어가다 머리가 터지며 죽는 모습의 애니메이션을 확인할 수 있다.
마무리 하며...
지금까지 캐릭터 이미지를 구현하기 위한 두 가지 방법을 알아 보았다. 사실 두 가지 방법은 이미지를 몇 개 사용하는지만 다를 뿐 동일한 프로그램 로직을 가지고 있다. 실제 게임 개발에서는 Image Sprites 기법을 많이 사용하므로 이 기법으로 여러가지 테스트 프로그램을 작성해 보는 것이 도움이 될 것이다.
두개의 글을 통해 애니메이션 구현 기법을 충분히 숙지하였으니, 다음 글에서는 공개된 라이브러리를 사용해서 애니메이션을 구현해 보도록 하겠다. 라이브러리를 활용하면 좀 더 안정적으로 그리고 생산성 높게 개발할 수 있으므로 자신의 개발 무기로 장착해 두는 것이 좋을 것이다.
'모바일 > HTML5' 카테고리의 다른 글
[HTML5 Game] Background Animation (1) | 2013.09.20 |
---|---|
[HTML5 Game] Character Animation Using Trident.js (3) | 2013.09.17 |
[HTML5 Game] Character Animation (1) | 2013.09.14 |
CSS3 3D Effect (0) | 2013.08.02 |
... (0) | 2013.07.23 |
HTML5의 Canvas 요소를 활용하여 그럴싸한 2D 게임을 개발할 수 있다.
UDACITY에서도 HTML5 기반의 게임 개발 강의를 무료로 제공하고 있다
=> https://www.udacity.com/course/cs255
여기서 제공하는 캐릭터 애니메이션 구현 기법을 살펴보자. 코드는 내 입맛에 맞게 수정을 가했지만 전체적인 맥락은 동일하다.
대략적은 구현 흐름을 보면, 캐릭터의 움직임을 위해서 각각의 컷을 개별 이미지로 준비하고 이 이미지들을 Canvas에 차례대로 반복해서 그려주는 것이다. 이미지들은 매우 빠른 속도로 Canvas에 그려지는데 이때 적용되는 개념이 초당 프레임(FPS, frame per second)이다.
FPS는 게임 개발 영역에서는 자연스러운 개념으로 인간이 느끼지 못하는 속도로 프레임을 교체하여 자연스러운 움직임이 가능하도록 하는 것으로 영화 필름의 재생을 생각해 보면 이해하기 쉽다.
아래 그림은 캐릭터 움직임을 19개 이미지로 분할한 모습을 보여준다.
* HTML
애니메이션 처리는 모두 자바스크립트에서 구현한다. HTML 파일은 단지 Canvas 요소와 자바스크립트을 참조하는 코드만 존재한다.
<html lang="en">
<head>
<script type="text/javascript" src="js/animationCharacter.js"></script>
</head>
<body>
<canvas id="GameCanvas" width="300" height="300" style="border: 1px solid #000;">
HTML5 Canvas를 지원하지 않습니다. 크롬 또는 사파리와 같은 HTML5 지원 브라우저를 이용해 주세요
</canvas>
</body>
</html>
* JavaScript
자바스크립트로 이미지를 다운로드하여 애니메이션을 구현한다. 애니메이션 처리를 위한 자바스크립트의 핵심 함수는 setInterval()이다. 이 함수는 주어진 간격으로 함수를 반복(loop) 실행시켜주는 함수로 setTimeout() 함수와 함께 HTML5 게임 개발에 필수적으로 사용되는 함수이다. 먼저 캐릭터 객체를 위한 코드부터 살펴보자
1. 캐릭터, 생성자 함수와 메서드
this.assets = assets; //Asset Image Array
this.canvasSize = {width: canvasElement.width, height: canvasElement.height}; //Canvas Size
this.canvasContext = canvasElement.getContext('2d'); //Canvas Context
this.currentFrame= 0; //Current Frame
}
Character.prototype.startAnimation = function(){
//Clear Canvas
this.canvasContext.clearRect(0, 0, this.canvasSize.width, this.canvasSize.height);
//Draw Image on Canvas
this.canvasContext.drawImage(this.assets[this.currentFrame], 100, 100);
//Update Current Frame
this.currentFrame = ++this.currentFrame % this.assets.length;
}
생성자 함수에서는 게임 캐릭터의 개별 이미지를 담을 assets 배열과, 이 이미지를 그려줄 Canvas 요소를 매개변수로 받아서 초기화 작업을 수행한다. CurrentFrame는 개별 이미지를 담고 있는 assets 배열의 인덱스로 사용될 변수로 총 19개의 이미지를 순서대로 교체하기 위해 0~18까지의 값을 가지게 된다.
그리고 실제 애니메이션 동작을 처리하는 startAnimation 메서드에서는 먼저 Canvas를 초기화시킨다. Canvas를 초기화하지 않으면 이전에 그린 그림과 새로 그리는 그림이 서로 겹쳐지게 되어 잔상이 남게 되기 때문에 초기화 하는 작업을 제일 먼저 수행한다.
다음으로 19개의 캐릭터 이미지를 담고 있는 assets 배열에서 CurrentFrame에 해당하는 이미지를 선택해서 Canvas에 그려준다. 마지막으로 19개의 이미지를 순회하기 위해 CurrentFrame 값을 업데이트 하는데 0~18까지 순회하도록 나머지 연산을 수행한다. 결국 이 startAnimation 메서드가 끊임없이 반복 수행됨으로써 캐릭터의 움직임을 구현할 수 있게 되는 것이다.
2. 프로그램 로직
이제 이미지를 다운로드해서 setInterval()함수와 캐릭터 객체를 활용하는 코드를 살펴보자.
먼저 전역변수를 정의한다.
var character; //Character Instance
var canvasElement; //Canvas Element
var assetfiles; //Asset Image File Array
var assets = []; //Asset Image Ojbect Array
var currentAssetLoadCount = 0; //Asset Image File Load Count
fps는 frame per count 약자로 초당 프레임 수를 나타내는데 30이라는 값은 1초에 30번 함수를 호출하겠다는 의미이다. 즉 1초에 30번 프레임이 이동 시키겠다는 의미이다.
다음으로 초기화함수를 정의한다.
canvasElement = document.getElementById("GameCanvas");
//Define Asset Image File Array
assetfiles =
[ 'image/robowalk/robowalk00.png', 'image/robowalk/robowalk01.png',
'image/robowalk/robowalk02.png', 'image/robowalk/robowalk03.png', 'image/robowalk/robowalk04.png', 'image/robowalk/robowalk05.png',
'image/robowalk/robowalk06.png', 'image/robowalk/robowalk07.png', 'image/robowalk/robowalk08.png', 'image/robowalk/robowalk09.png', 'image/robowalk/robowalk10.png', 'image/robowalk/robowalk11.png',
'image/robowalk/robowalk12.png', 'image/robowalk/robowalk13.png', 'image/robowalk/robowalk14.png', 'image/robowalk/robowalk15.png', 'image/robowalk/robowalk16.png','image/robowalk/robowalk17.png',
'image/robowalk/robowalk18.png'
];
for (var i = 0; i < assetfiles.length; i++) {
//Create Asset Image Ojbect
var asset = new Image();
asset.src = assetfiles[i];
//Insert Asset Image in Asset Image Array
assets.push(asset);
//Assign Imgae Load Event
asset.onload = onAssetLoadComplete;
}
}
페이지가 로딩되면 제일 처음 실행될 초기화 함수에서는 HTML DOM에서 Canvas 요소를 선택하고 총 19개의 캐릭터 이미지를 파일을 불러와서 이미지 객체를 생성하여 assets 배열에 담는다. 실제 웹 환경에서는 이미지 다운로드 시간에 지연이 있을 수 있으므로 이미지 로드가 모두 완료된 후 다음 로직을 수행해야 한다. 이미지 로딩이 완료되면 발생하는 onload 이벤트에 onAssetLoadComplete 함수를 할당한다.
onAssetLoadComplete 함수 코드는 다음과 같다.
//Check Load Complete of All Images
if(++currentAssetLoadCount >= assetfiles.length){
//Create Character Instance
character = new Character(assets,canvasElement);
//Run Game Loop
setInterval(animationLoop, 1000 / fps);
}
}
function animationLoop(){
character.startAnimation();
}
이 함수에서는 모든 캐릭터 이미지가 로딩 완료되었는지 체크하고 완료되었다면 캐릭터 객체를 생성하고 setInterval() 함수로 반복 루프를 시작시킨다. setInterval() 함수는 반속 실행을 위한 시간 간격을 밀리세컨트 단위로 설정하게 되는데 1000/fps 즉 1000/30은 0.33초 마다 함수를 수행하라는 의미가 되므로 결과적으로 1초에 30번 Character 객체의 startAnimation() 함수가 수행시키게 된다.
그리고 마지막으로 페이지가 로딩되면 초기화 함수가 수행될 수 있도록 이벤트를 연결시킨다.
실행화면
코드를 모두 작성하고 HTML5를 지원하는 브라우저(크롬 or 사파리)로 확인하면 로봇 캐릭터가 움직이는 애니메이션을 확인할 수 있다. 다음 그림은 화면을 캡쳐한 것이다.
마무리 하며...
이번 글에서는 UDACITY 강의를 기반으로 HTML5 기반의 애니메이션 처리를 살펴봤다. 여기서는 총 19개에 달하는 각각의 캐릭터 이미지를 사용했지만 실제 게임 개발에서는 이렇게 많은 이미지를 사용한다는 것은 매우 비효율적인 것이 된다. 그래서 대부분 Image Sprite 라는 기법을 이용해 모든 에셋이 포함된 하나의 이미지를 기반으로 필요한 에셋만 잘라내서 활용하는 방식이 사용된다. 또한 이러한 애니메이션 처리를 위한 오픈소스 라이브러리도 많이 존재한다. 다음 글에서는 Image Sprite 기법과 애니메이션 라이브러리를 사용하여 애니메이션을 구현하는 기법을 알아보자.
참고> 이 글에서 사용된 게임 에셋 이미지(UDACITY 이미지) 다운로드 경로
=> https://www.udacity.com/media/js/standalone/libs/gamedev_assets/robowalk/robowalk01.png
'모바일 > HTML5' 카테고리의 다른 글
[HTML5 Game] Character Animation Using Trident.js (3) | 2013.09.17 |
---|---|
[HTML5 Game] Character Animation Using Sprites (0) | 2013.09.17 |
CSS3 3D Effect (0) | 2013.08.02 |
... (0) | 2013.07.23 |
HTML5 개발을 도와주는 도구들 (4) | 2010.11.01 |
몇해전 MKEXDev.NET 의 로고가 필요하게 된 적이 있었다
대학생에게 무료로 개발도구를 배포하는 마이크로소프트의 DreamSpark 이벤트에 후원 커뮤니티로 선정되어 사이트 로고를 보내줘야 했다. 당시 내 사이트에는 특별한 로고가 없었으나 MS 프로모션 담당자는 이미지로 된 로고를 원했다. 그래서 급조하기로 했는데 개발을 주제로 한 사이트라 뭐.. 특별한 디자인을 하고 싶지는 않았다. 그냥 텍스트에 간단한 효과를 줘서 깔끔하게만 보이면 되겠다 싶었다.
그래서 아는 디자이너에게 매우 심플하게 만들어 달라고 부탁해서 나온 로고가 바로 아래와 같은 모습니다.
심플하면서도 깔끔한 텍스트 기반의 로고로 개인적으로 흡족하며 지금까지 사이트 로고로 사용하고 있다
이를 계기로 문득, 텍스트를 입력하면 간단한 효과만 처리해서 이미지로 변환해 주는 툴이 있으면 좋겠다는 생각이 들었는데 마침 HTML5를 접하면서 간단하게라도 데모격으로 한번 만들어 보자고 맘을 먹었다
목표는 완성도가 아니라 기능을 구현하면서 HTML5를 익히자는 것이므로 툴의 완성도는 기대하지 말기 바란다
CSS3 ? Canvas ?
텍스트에 효과를 주는 방법은 많다. HTML5 관련 스펙만 봐도 CSS3 혹은 Canvas 를 이용할 수 있다
CSS의 Transform 이나 text-stroke, opacity, Gradients 등과 같은 기능만으로도 화려한 텍스트 효과처리가 가능하다. 그러나 앞서도 밝혔지만 CSS 보다는 HTML5 주요 기능을 익히는 것이 목적이므로 Canvas를 이용하기로 결정했다. Canvas를 이용해도 텍스트 크기, 그라디에이션, 색상, 폰트, 그림자, 투명도 등 처리가 가능하다
게다가 Canvas의 내용을 이미지로 변환할 수 있으니 더욱 적합하다는 생각을 하게 되었다
데모 실행
코드를 보기 전에 먼저 데모 실행화면을 살펴 보자
하단 텍스트상자에 글자를 입력하면 상단의 캔버스에 표시되며 몇 가지 텍스트 효과를 줄 수 있다
이 모든 텍스트 효과처리는 HTML5 Canvas 관련 기능을 이용한 것이며 캔버스의 최종 결과를 이미지로 변환시켜 주는 기능이 지원된다. 텍스트상자에 글이 입력되거나 삭제될 때 바로바로 그 내용이 캔버스로 반영되며 텍스트 효과도 즉시 적용되어 캔버스에 나타난다.
참고로 텍스트 효과는 데모에 적용된 기능 이외에도 그림자 효과, 그라디에이션 효과 등 더 다양한 처리가 가능하지만 데모에서는 기본적인 효과만 집중했음을 밝힌다
IE8 이전 버전을 제외한 크롬, 사파리, 오페라에서 실행 가능하며, 다음의 주소에서 확인할 수 있다
http://mkexdev.net/m/textToImageByCanvas.html
구현 하기
전체 코드를 보기 전에 몇 가지 핵심적인 내용을 살펴 보자
자바스크립트 키 관련 이벤트
HTML5 Canvas API 설명전에 먼저 자바스크립트의 키 관련 이벤트를 짚고 넘어가자
자바스크립트에는 키보드 입력과 관련된 총 3개의 이벤트가 제공된다.
keydown, keyup, keypress 가 그것인데 이들 이벤트는 키 입력에 반응하는 것이 조금씩 다르다
keydown 과 keyup 은 유사하지만하지만 keypress 는 이 둘과 약간 차이가 있는데 데모 제작과 관련해 주목해야 할 것은 keypress 는 백스페이스키(<-) 에 반응하지 않는다는 것이다.
그리고 keydown 과 keyup 의 경우 이벤트로 넘겨진 keyCode 에는 영문 대/소문자를 구분하지 않고 모두 대문자로 취급한다는 것이다. 제작하고자 하는 데모는 대/소문자를 구분해야 하며 백스페이스키로 글자를 삭제해야 하기 때문에 하나의 이벤트로 만족할 수 없었다. 즉 keypress 이벤트로 문자 입력을 처리하고 keyup으로 백스페이스와 Delete키에 반응하도록 처리했다는 것을 먼저 알린다
아래 코드와 같이 두 이벤트를 동시에 정의해서 문자 키 입력에 두 이벤트가 반응하지만, 백스페이스와 Delete 키 등의 특수키에는 keyup 이벤트만 반응한다. keyup 이벤트는 일반 문자 입력은 무시하도록 처리한다.
<input type="text" id="myText" size="60" onkeypress="inputText(event.keyCode);" onkeyup="inputBackSpace(event.keyCode);">
캔버스 지우기
캔버스의 내용을 모두 지우기 위해서는 몇 가지 방법이 있지만,
기본적으로 캔버스의 너비 혹은 높이 정보를 다시 설정하면 캔버스내용이 모두 지워진다고 알려져 있다
canvas.width = canvas.width;
그러나 이 방법은 현재 사파리와 파이어폭스에서만 정상 동작한다
브라우저마다 HTML5 지원 현황이 달라서 발생하는 문제로 보인다.따라서 모든 브라우저에서 동작하도록 하려면 clearRect 로 캔버스 내용을 명시적으로 지워줘야 한다
아래 코드와 같이 (0,0) 부터 캔버스의 너비,높이만큼이 사각형 영역을 지움으로써 캔버스를 초기화 할 수 있다
context.clearRect(0,0,canvas.width, canvas.height);
캔버스에 텍스트 그리는 방법
Canvas의 2D Context 를 통해 각종 그리기 작업을 할 수 있는데 텍스트의 경우 fillText 와 strokeText 메서드를 통해 그릴 수 있다. fillText는 속이 찬 텍스트, strokeText는 테두리만 있는 텍스트를 그릴 수 있다
데모에서는 텍스트상자에 글자가 입력될 때 마다 바로바로 캔버스에 그리기를 수행하는데,
이때 입력된 글자 하나씩 캔버스에 그리는 방법과 캔버스를 지우고 텍스트상자에 지금까지 입력된 전체 내용을 다시 그리는 방법 중 하나를 택해야 한다
전자의 경우 텍스트가 입력되는 위치를 직접 지정해 줘야 하기 때문에 조금 복잡하며 후자의 경우 매번 캔버스를 지우고 다시 그리는 작업을 해 줘야 하기 때문에 조금 비효율적이다
따라서 데모에서는 전자의 경우처럼 텍스트 입력 시 마다 글자 하나씩 캔버스에 입력하기로 했으며 이때 알아야 하는 입력 위치는 다음과 같이 measureText 메서드를 통해 전체 문자열의 길이를 구함으로써 해결하였다
(텍스트 상자가 멀티라인을 지원하지 않기 때문에 Y 좌표는 필요치 않다)
var textWidth = context.measureText(text).width;
context.fillText(text, textWidth , 0); //글자가 위치할 캔버스 X 좌표를 설정한다
다만 백스페이스키(<-)와 Delete 키를 눌렀을 때 글자가 지워지는 것은 심플한 처리를 위해,캔버스 내용을 지우고 다시 입력하는 후자의 방식을 따르기로 했다.
(글자 지우기 역시 clearRect 를 통해 정해진 글자 영역만 지울 수 있지만 이 경우 x 좌표의 변화와 폰트 크기에 따른 clearRect 크기 변경 등 신경 쓸 부분이 많아 오히려 버그 유발 요인이 될 수 있어 사용을 피하기로 했다)
context.clearRect(0,0,canvas.width, canvas.height); //캔버스를 지우고
context.fillText(text, 0, 0); //다시 전체 글자를 그린다
그리고 텍스트에 폰트, 색상과 같은 효과 처리는 2D Context의 속성들을 통해 이뤄지는데 이미 입력된 내용은 반영되지 않기 때문에 이때도 역시 캔버스를 지우고 다시 그리는 방식을 취한다
기타 살펴볼 내용
캔버스를 통한 텍스트 효과 처리시 다음의 주요 코드가 이용 되었다
: context.textBaseline = "top"
캔버스에 텍스트가 위치하는 수평 기준선을 top 으로 해 줌으로써 글자가 기준선 아래로 표시되도록 한다
: context.font = "20px 'Tahoma'"
font 속성을 통해 캔버스에 표시될 텍스트 폰트를 처리하는데 css 의 폰트 속성과 같이 정의할 수 있다
: context.fillStyle = "red" , context.strokeStyle
fillStyle 속성을 통해 채우기 스타일을 지정할 수 있다. 기본은 검정이다. strokeStyle 속성은 선의 색상을 지정하는데 이용한다
: String.fromCharCode(keyCode)
HTML5 , Canvas와는 무관하지만 데모에서는 유용하다. 키 이벤트로 넘여온 keyCode 를 문자로 변환해 주는 자바스크립트 내장 함수이다. 한 글자씩 입력 할 경우 필요하다
: 캔버스 내용을 이미지로 변환하기
이미 살펴본 내용이다. 캔버스의 toDataURL 메서드를 통해 이미지데이터문자열을 기반으로 이미지객체를 생성한다. [HTML5 실습] Canvas에 그린 그림을 이미지로 만들기
이것으로 구현을 위한 핵심적인 내용을 대략 살표 보았다. 이제 전체 코드를 제시한다
전체 코드는 http://mkexdev.net/m/textToImageByCanvas.html 의 소스보기를 통해서도 볼 수 있다
<html>
<head></head>
<body>
<form name="myForm">
<canvas id="cv" width="400" height="70" style="position: relative; border: 1px solid #000;"></canvas>
<button onclick="clearCanvas()">Clear</button>
<input type="button" onclick="convertImage()" value="이미지로변환">
<img id="myImage">
<br>
<input type="radio" name="isFill" value="Fill" onchange="chkFill();" checked>Fill
<input type="radio" name="isFill" value="Stroke" onchange="chkFill();">Stroke
<br>
Font: <input id="fontSize" type="range" min="10" max="60" step="5" value="50" onchange="changeFont();" />
<select id="fontFace" onchange="changeFont();">
<option value="Tahoma" selected>Tahoma</option>
<option value="Verdana">Verdana</option>
<option value="Gulim">Gulim</option>
<option value="Georgia">Georgia</option>
<option value="Symbol">Symbol</option>
<option value="Terminal">Terminal</option>
</select>
<br>
Fill Color: <select id="fontColor" onchange="changeColor(1);">
<option value="Black" selected>Black</option>
<option value="Red">Red</option>
<option value="Blue">Blue</option>
<option value="Green">Green</option>
<option value="Yellow">Yellow</option>
</select>
Stroke Color: <select id="strokeColor" onchange="changeColor(2);">
<option value="Black" selected>Black</option>
<option value="Red">Red</option>
<option value="Blue">Blue</option>
<option value="Green">Green</option>
<option value="Yellow">Yellow</option>
</select>
<p>
<input type="text" id="myText" size="60" onkeypress="inputText(event.keyCode);" onkeyup="inputBackSpace(event.keyCode);">
<div id="msgDiv"></div>
</form>
</body>
</html>
<script type="text/javascript">
if(window.addEventListener){
window.addEventListener('load', Init, false);
}
var canvas, context, myText,msgDiv
var isFill = true;
function Init() {
canvas = document.getElementById('cv');
context = canvas.getContext('2d');
context.font = eval("'"+ document.getElementById('fontSize').value +'px '+ document.getElementById('fontFace').value+"'");
context.textBaseline = "top";
myText = document.getElementById('myText');
myText.focus();
msgDiv = document.getElementById("msgDiv");
}
function inputText(keyCode){
msgDiv.innerText = keyCode;
//글자의 가로위치를 구하기 위해 현재 입력된 문자열의 너비를 구한다
var textWidth = context.measureText(myText.value).width;
drawText(String.fromCharCode(keyCode), textWidth);
}
function inputBackSpace(keyCode){
if(keyCode == 8 || keyCode == 46){ //백스페이스 키와 Delete키를 받기 위한 함수
clearCanvas();
drawText(myText.value,0);
}
}
function drawText(text, posX){
if(!isFill){ context.strokeText(text, posX , 0); }
else{ context.fillText(text, posX , 0); }
}
function chkFill(){
isFill = myForm.isFill[0].checked;
clearCanvas();
drawText(myText.value,0);
}
function changeFont(){
clearCanvas();
context.font = eval("'"+ document.getElementById('fontSize').value +'px '+ document.getElementById('fontFace').value+"'");
drawText(myText.value,0);
}
function changeColor(flag){
clearCanvas();
if(flag == 1){
context.fillStyle = document.getElementById('fontColor').value;
}
else{
context.strokeStyle = document.getElementById('strokeColor').value;
}
drawText(myText.value,0);
}
function clearCanvas(){
//canvas.width = canvas.width; //사파리, 파폭에서만 동작(크롬, 오페라 X)
context.clearRect(0,0,canvas.width, canvas.height);
}
function convertImage(){
var image = new Image();
var myImage = document.getElementById('myImage');
myImage.src = canvas.toDataURL();
}
</script>
HTML5 Canvas+Text Example
한참 삘(feel) 받아서 데모를 제작하다가 이 사이트를 알게 되었다
=> http://whatdo.net/html5/example/#2
내가 구현하고자 했던 대부분의 기능이 제공되고 있었다.
사실 데모의 완성도를 꽤 올리고자 맘 먹고 시도하던 도중에 이 사이트를 보게 되었고 동기가 한풀 꺽였다
이미 제공되고 있는 사이트가 있으니 내가 만들고자 하는데모에 새로움은 별로 없기에 받았던 삘(feel)이 사그러져 버렸다 ㅎㅎ. 그래서 적당한 선에서 데모 제작을 완료하고 포스팅 하게 된 것이다
이 사이트를 보면 조금은 다른 방식으로 구현하고 있지만 더 많은 canvas 기능이 활용되었고 구현 방식 역시 배울점이 많아 보인다. 소스보기를 통해 분석해 보면 많은 도움을 얻게 될 것이니 반드시 참고 바란다
'모바일 > HTML5' 카테고리의 다른 글
[HTML5]로컬자원활용,그 위치와 용량 그리고 유효기간은? (3) | 2010.10.19 |
---|---|
HTML5, 속도와 호환성 문제 그리고 느린 대응 (2) | 2010.10.18 |
[HTML5 실습] Canvas에 그린 그림을 이미지로 만들기 (6) | 2010.10.08 |
W3C, HTML5 도입 이르다? (1) | 2010.10.08 |
Aptana, HTML5를 지원하는 웹 개발 툴 (2) | 2010.10.04 |
Canvas 객체의 toDataURL() 함수를 통해 캔버스에 그린 그림을 문자열 형태로 변환할 수 있는데,
이 문자열에는 이미지 MIME 타입과 인코딩 방법 그리고 인코딩 된 이미지 데이터 문자열이 포함된다
대략 다음과 같은 모습이다
https://t1.daumcdn.net/cfile/tistory/226CDB4956E6D5F802"FONT-FAMILY: Tahoma">그럼, 실제 Canvas 내용이 문자열로 변환된 것을 확인해 보자
아래 그림은 Canvas에 적당히 그림을 그리고 toDataURL() 함수를 이용해 URL문자열을 띄워 본 것이다
toDataURL() 로 반환된 것이 문자열이라는 것은 다음과 같이 타입조사를 해 보면 알 수 있다
alert(typeof canvas.toDataURL()); //string 이 출력됨
이 문자열은 Canvas에 그려진 내용을 Data URL로 변환한 것이기 때문에 그 자체로 이미지 정보가 된다
따라서 이 문자열을 이미지 객체에 바인딩하거나 다른 이미지로 생성할 수 있게 된다
Canvas 에 그린 그림을 이미지로 변환하기
한 가지 간단한 샘플을 만들어 보자.
Canvas 로 그린 내용을 문자열로 변환하여 img 요소의 src 로 사용하는 것이다
Canvas 에 그리기 작업을 수행하는 코드는 이전 글인 [HTML5] Canvas '마무로 데모' 코드를 이용하므로 구현 코드는 생략하도록 한다. 이 글에서는 Canvas 결과를 이미지 소스로 바인딩하는 것을 제시한다
다음 코드와 같이 Canvas와 버턴, 그리고 img 요소를 정의한다
Canvas에 그림을 그리고 버턴을 클릭하면 오른쪽 img 요소에 그 내용이 이미지 소스로 활용되는 예이다
<button onclick="toDataURL();">이미지로 변환=></button>
<img id="myImage">
.....
<script type="text/javascript">
function toDataURL(){
var myImage = document.getElementById('myImage');
myImage.src = canvas.toDataURL();
}
</script>
이렇게 생성된 이미지는 완전한 하나의 이미지 객체 이므로 로컬에 이미지로 저장하는 등의 이미지 작업이 가능하다
참고로 이렇게 생성된 이미지의 HTML 코드는 아래와 같다
Canvas 에 그린 그림을 다른 Canvas 로 복사하기
이번에는 Canvas에 그린 내용을 다른 Canvas로 옮기는 즉 복사하는 예를 살펴보자.
복사 방법이야 여러 가지가 있을 수 있겠지만 여기서는 toDataURL() 함수로 반환된 이미지데이터문자열을 이용해서 복사하는 방법을 알아보자
언뜻 생각하기에 toDataURL() 함수가 있다면 fromDataURL() 함수가 있지 않을까 생각이 든다
다시말해 캔버스 내용을 URL 문자열로 반환해 주는 함수가 있다면 역으로 URL 문자열을 캔버스 내용으로 사용할 수 있는 함수 말이다. 그런데 찾아 보니 그런 함수는 없어 보인다. 아쉬운 부분이다
그렇다면 우리가 직접 fromDataURL 함수를 만들어 보기로 하자
아래 코드와 같이 두 개의 Canvas를 정의하고 왼쪽 캔버스의 내용을 오른쪽 캔버스로 복사하기 위해 toDataURL()로 얻어진 문자열을 이미지 객체의 소스로 바인딩하고 이미지가 로딩될 때 복사 대상 캔버스의 drawImage 함수를 이용해 이미지를 그리는 로직이다.
<button onclick="fromDataURL();">캔버스 복사=></button>
<canvas id="copyCanvas" width="200" height="200" style=" position: relative; border: 1px solid #000;"></canvas>
...
<script type="text/javascript">
function fromDataURL(){
var copyCanvas = document.getElementById('copyCanvas');
var copyContext = copyCanvas.getContext('2d');
var image = new Image();
image.src = canvas.toDataURL();
image.onload = function(){
copyContext.drawImage(image,0,0);
}
}
</script>
데모를 실행한 결과 화면은 아래와 같다
어떻게 보면 fromDataURL() 함수는 끼워 맞춘 듯한 느낌이다
하지만 toDataURL()로 얻어진 이미지데이터문자열을 이런 형태로도 이용할 수 있다는 힌트만 가지면 되겠다
위에서, Canvas 그림을 다른 Canvas로 복사할 때 이미지객체를 생성하는 단계가 있었다
확인 해 보니, 이미지객체를 경유하지 않고 대상 Canvas에 원본 Canvas를 drawImage 해 주면 된다
따라서 단지 복사가 목적이라면 중간 경유로 사용된 이미지객체의 생성은 불필요 하겠다
fromDataURL 함수는 아래와 같이 수정하면 된다
function fromDataURL(){
var copyCanvas = document.getElementById('copyCanvas');
var copyContext = copyCanvas.getContext('2d');
copyContext.drawImage(canvas,0,0);
}
Canvas 내용을 문자열로 얻을 수 있다는 것은...
웹에서 다양한 시나리오를 구현할 수 있다는 의미가 된다
글에서 알아본 것과 같이 캔버스 내용을 이미지로 변환하여 로컬 컴퓨터에 저장할 수 있으며
또 다른 예로 캔버스 내용을 서버로 업로드 하여 다른 사람과 공유하거나 관리할 수 있게 된다
또한 캔버스 내용을 쿠키나 localStorage 등에 저장하여 계속 사용할 수 있으며 페이지 통신을 통해 두 페이지간 캔버스 내용을 교환할 수도 있다.
결론적으로 문자열로 처리 가능한 모든 시나리오에 캔버스를 이용할 수 있다는 의미가 된다
다만 이렇게 생성한 이미지는 일반 이미지 파일과는 달리 브라우저에 캐시되지 않기 때문에
쇼핑몰 이미지 리스트와 같은 많은 이미지를 서버에서 불러와 캐시되는 시나리오에는 적합하지 않을 수 있다
자신만의 다양한 시나리오를 구상해 실현해 보기 바란다
....
참고로 toDataURL() 함수는 두개의 매개변수를 가지는데, 첫번째 인수는 이미지MIME 타입을 지정하는데 이용되며 나머지 인수는 이미지 품질 정도와 같은 추가 이미지 효과를 지정하는데 사용된다
이전 샘플과 같이 매개변수 없이 호출하게 되면 기본적으로 image/png 타입으로 설정된다
만일 jpeg 를 원한다면 다음의 코드가 가능하다
canvas.toDataURL("image/jpeg");
그러나 테스트를 해 보니 브라우저별로 지원되는 부분이 조금씩 다르니 참고하기 바란다
toDataURL 에 대한 더 자세한 내용은 다음의 W3C 스펙 설명을 확인 하자
http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#todataurl-method
'모바일 > HTML5' 카테고리의 다른 글
HTML5, 속도와 호환성 문제 그리고 느린 대응 (2) | 2010.10.18 |
---|---|
[HTML5 실습] Canvas를 이용한 텍스트-> 이미지 변환기 (2) | 2010.10.13 |
W3C, HTML5 도입 이르다? (1) | 2010.10.08 |
Aptana, HTML5를 지원하는 웹 개발 툴 (2) | 2010.10.04 |
드디어 W3C에서 HTML5 Last Call 프로세스 돌입!! (0) | 2010.09.30 |
이전 글에서 소개한 RGraph 와 유사한 라이브러리를 소개한다
jQuery 의 플러그인 형태로 제공되는 Visualize 라이브러리 이다
HTML5 그래픽 관련 툴을 찾던 중 알게 된 이들 라이브러리는 아주 유용하며 안정감 마저 든다
아직 표준안이 완성되지 않은 기술에 기반 라이브러리가 먼저 등장하는 점은 HTML5를 선호하는 사람에게는 매우 고무적이라 볼 수 있겠다
Visualize 역시 HTML5 의 Canvas 를 통해 차트를 표현하며 jQuery 기반으로 동작한다
RGraph 가 그래프 및 차트에 이용되는 데이터를 스크립트를 통해 RGraph 객체로 정의하는 반면,
Visualize 는 HTML 테이블에 정의된 데이터를 자동으로 분석해서 차트로 변환해 주는 특징이 있다
또한 RGraph 처럼 브라우저 호환성을 위한 장치가 마련되어 있다
직접 테이블의 데이터를 수정하면서 차트의 변화를 확인할 수 있는 다음의 링크로 이동해 보자
http://www.filamentgroup.com/examples/charting_v2/
그리고 라이브러리 소개 페이지이다
http://www.filamentgroup.com/lab/
update_to_jquery_visualize_accessible_charts_with_html5_from_designing_with/
'모바일 > Javascript' 카테고리의 다른 글
Raphael, 자바스크립트 (벡터) 그래픽 라이브러리 (0) | 2010.09.29 |
---|---|
Gordon, 자바스크립트로 만든 플래시 런타임 (0) | 2010.09.29 |
RGraph, HTML5 그래프 라이브러리 소개 (0) | 2010.09.14 |
Modernizr 라이브러리: HTML5, CSS3 새요소 지원여부 검사 (0) | 2010.09.06 |
[JQuery] JQuery 사용 환경 설정 (0) | 2010.08.04 |
HTML5 의 Canvas 를 이용해서 각종 그래프를 만들어 주는 라이브러리이다
비 상업적 사이트일 경우 무료로 사용 가능하다
(상업적 사이트일 경우 소정의 수수료를 요구하는 것 같다)
바차트, 도넛차트, 파이차트, 간트차트, 로즈차트 등 다양한 형태의 차트를 지원하며 도움말이 충실히 제공되어 쉽게 사용할 수 있다. 그래프 표현 뿐만 아니라 줌기능, 컨텍스트 메뉴 등록, 비동기 출력, 애니메이션 효과 등 2D 그래픽과 관련한 유용한 기능들도 구현되어 있다
그리고 예제를 보면 Canvas를 지원하지 않는 브라우저를 위한 코드 즉 IE8 의 Canvas 적용을 위한 ExplorerCanvas 와 구글 프레임을 적용하는 등 브라우저 호환성을 신경 쓴 모습이다
이 사이트에서 공식적으로 소개하는 브라우저 지원 목록은 아래와 같다
- Mozilla Firefox 3.0+
- Google Chrome 1+
- Apple Safari 3+
- Opera 9.5+
- Microsoft Internet Explorer 8+ (see note)
현재 시점에서(2010.09.14) 최종 릴리즈 버전으로 2010.08.28일자가 등록되어 있으며 최종 베타버전으로는 2010.09.11자가 올라와 있다.
캔버스기반의 그래프라이브러리로 훌륭한 선택이 될 수 있을것 같으며 꼭 적용하지 않더라도 캔버스를 이용한 그래픽 작업을 하는데 있어 좋은 학습 자료가 될 수 있을 것 같다
아래의 사이트에서 자세히 확인해 보도록 하자
http://www.rgraph.net/
'모바일 > Javascript' 카테고리의 다른 글
Gordon, 자바스크립트로 만든 플래시 런타임 (0) | 2010.09.29 |
---|---|
jQuery Visualize, HTML5 차트 라이브러리 소개 (0) | 2010.09.15 |
Modernizr 라이브러리: HTML5, CSS3 새요소 지원여부 검사 (0) | 2010.09.06 |
[JQuery] JQuery 사용 환경 설정 (0) | 2010.08.04 |
[JQTouch] 모바일 웹 UI 라이브러리 (0) | 2010.08.04 |
HTML5 의 많은 새로운 기능 중 가장 자주 언급되어 왔던 것이 아마 Canvas(캔버스) 일 것이다
Canvas 는 Web Workers 나 Web Storage와 같은 다른 HTML5 스펙보다 덜 기술적이며 보다 직관적이다.
개발자 뿐만 아니라 비개발자들 역시 Canvas의 개념을 쉽게 이해할 수 있고 흥미를 보여왔기 때문에 가장 먼저 그리고 가장 흔하게 소개된 HTML5 기술인 것이다
Canvas 는 말 그대로 그림을 그릴 수 있는 화폭, 즉 그림판과 같다
그것도 다른 곳에 아닌 브라우저 위에서 동작하는 그림판인 것이다
Canvas 위에 선, 도형, 텍스트, 이미지와 같은 그래픽을 표현할 수 있고 색깔, 그림자, 패턴과 같은 여러 효과를 적용할 수 있다. 그리고 기본적으로 Canvas 는 2차원 그래픽 표현을 위한 스펙이지만 추가로
WebGL를 기반으로 하는 3D 그래픽용 Canvas 의 스펙 개발이 진행중이다
브라우저 지원 현황
브라우저 지원 현황 역시 다른 HTML5 기술보다 더 일반적이다
다시 말해 대부분의 브라우저에서 Canvas를 지원한다는 의미이다
그림1. 브라우저별 2D Canvas 지원 현황 (출처: http://caniuse.com/)
IE9 이전 버전에서 Canvas 지원하기
현재까지 출시된 IE8 까지는 HTML5 지원이 거의 되지 않는다
Canvas 역시 IE9 이전 버전에서는 동작하지 않는다
다만 구글에서 제공하는 크롬프레임을 설치하면 IE9 이전버전에서도 HTML5 를 동작시킬 수 있다
그러나 Canvas의 경우 더 쉽게 IE에 적용할 방법이 있다.
ExplorerCanvas 라이브러리를 이용하면 이전버전의 IE에서도 Canvas를 동작시킬 수 있게 된다
(ExplorerCanvas는 이전 버전의 IE에서 Canvas API가 동작할 수 있도록 해 주는 오픈소스 자바스크립트 라이브러리이다)
정의하여 IE일 경우 이 스크립트가 적용되도록 처리하면 된다
<head>
<!--[if IE]><script type="text/javascript" src="excanvas.js"></script><![endif]-->
...
Canvas 학습 지원 사이트
Canvas로 구현할 수 있는 것은 아주 많다
개념적으로 보편적인 기술인 만큼 그 응용 개발 역시 매우 다양하게 펼칠 수 있다
그러나 응용도 기본이 갖춰져야 제대로 되는 만큼 기본사용법의 정확한 숙지가 필요하다
이 글에서도 기본적인 사용법과 간단한 데모를 작성해 보겠지만,
그전에 Canvas 학습을 도와주는 훌륭한 사이트가 있어 소개한다
이 두 사이트에서 제공하는 Canvas 튜토리얼은 정확한 기본기를 갖추고 응용력을 기르는데 충분한 도움을 줄 것이다. Canvas를 적용할 서비스는 굉장히 많으며 특히 게임과 같은 동적이고 화려한 그래픽이 필요한 서비스에는 활용도가 무궁무진할 것이다. 잘 정리된 기본 학습 도구를 활용하는 것이 매우 중요하므로 위 사이트들을 꼭 참고하기 바란다
Canvas 다루기
지금부터 Canvas를 다루는 기본적인 방법에 대해 알아 보도록 하자
<canvas> 태그와 그리기 컨텍스트
그림을 그리기 위해서는 제일 먼저 브라우저에 화폭이 준비되어 있어야 한다
<canvas>라는 마크업 태그를 이용하여 브라우저에 캔버스 영역을 지정할 수 있다
HTML 문서에 <canvas> 태그를 삽입하는 것 만으로 브라우저에 그림판이 준비된다
다만 캔버스는 기본적으로 테투리가 없기 때문에 위 코드만으로는 브라우저에서 캔버스를 눈으로 확인하기는 힘들다. 따라서 스타일을 적용해 캔버스의 테두리를 보이게 하는 것이 좋을 수 있다
style="position: relative; border: 1px solid #000;"></canvas>
그리고 이 캔버스를 이용해 그리기를 수행하려면 '그리기 컨텍스트'를 얻어야 한다
그리기 컨텍스트는 앞서 정의한 <canvas> DOM 객체의 getContext 메서드로 얻을 수 있다
var context = canvas.getContext("2d"); //DOM 객체로부터 2D 컨텍스트를 얻는다
이후 그리기 작업은 '그리기 컨텍스트'를 통해 이루어진다
캔버스의 좌표
캔버스에 각종 도형 및 선과 같은 2차원 그래픽 작업을 할 때 각 점의 위치를 지정해야 하는데
이는 캔버스의 2차원 좌표가 기준이 된다
사각형 모양을 하고 있는 캔버스는 제일 왼쪽 상단 꼭지점이 (0,0) 시작점이 된다
(0,0) 시작점을 기준으로 그리고자 하는 도형의 가로 위치 x 와 세로위치 y 좌표를 지정하면 된다
그림2. Canvas의 좌표 (출처: http://diveintohtml5.org/canvas.html)
그리기 작업
1) 사각형 그리기
그리기의 가장 기본이 되는 도형이다. Canvas API 에서 사각형을 위한 함수를 따로 제공하고 있다
아래와 같은 사각형 함수인데, 모두 같은 매개변수를 취하고 있다
x,y : 사각형의 시작점 좌표(왼쪽 위 모서리 지점), width,height: 사각형의 너비,높이
fillRect(x, y, width, height) : 색으로 채운 사각형을 그린다
strokeRect(x, y, width, height) : 선만 있는 사각형을 그린다
clearRect(x, y, width, height) : 사각형 영역을 지운다
아래 그림은 간단한 사각형 그리기 샘플이다
차례로 속이 찬 사각형과, 윤곽만 있는 사각형, 그리고 절반이 지워진 사각형이다
아래 결과 화면과 코드를 참고하기 바란다
<html>
<head></head>
<body>
<canvas id="cv" width="400" height="300" style="position: relative; border: 1px solid #000;"></canvas>
</body>
</html>
<script type="text/javascript">
var canvas = document.getElementById("cv");
var context = canvas.getContext("2d");
context.fillRect(10,10,100,100); //색으로채운 사각형
context.strokeRect(120,10,100,100); //윤곽만 있는 사각형
context.fillRect(230,10,100,100); //색으로 채운 사각형
context.clearRect(230,10,50,50); //앞 사각형의 절반을 지움
</script>
2) 각종 도형 및 선 그리기
사각형과는 달리, 삼각형, 오각형, 육각형 및 원과 같은 도형은 선들을 연결하여 직접 그려줘야 한다
완성된 도형은 선들의 집합체이며 각각의 선들을 패스(Path) 라 한다
(엄밀히 말하자면 각 선은 서브패스이며 서브패스 전체를 가리켜 패스라 한다)
결국 도형을 그린다는 것은 각 선을 연결한다는 의미이며 이는 패스(Path)를 그리는 과정인 것이다
패스(Path)그리기 순서
첫째, 패스 그리기를 시작을 알린다
: beginPath() 함수로 canvas에 패스그리기를 알린다. 이전의 패스는 모두 초기화된다
둘째, 패스 경로 즉 시작점과 종료점을 지정한다
: moveTo(x,y) 함수로 패스의 시작점을 지정하고 lineTo(x,y) 함수로 패스가 이어질 점을 지정한다
셋째, 패스 경로를 따라 실제로 그린다
: 이전 과정까지는 패스 즉 경로에 대한 정보를 셋팅하는 것이다
실제 지정된 패스를 따라 선을 그려야 하는데, 이는 stroke(), fill()과 같은 잉크(ink)함수가 이용된다
삼각형 그리기
간단한 삼각형 그리기 샘플을 보자.
아래와 같은 삼각형을 그리기 위해 패스그리기를 수행한 예이다
var canvas = document.getElementById("cv");
var context = canvas.getContext("2d");
context.beginPath(); //패스 그리기 시작
context.moveTo(50,10); //패스 시작점 지정
context.lineTo(20 ,100); //패스 이동점 지정
context.lineTo(80 ,100);
context.lineTo(50 ,10);
context.stroke(); //윤관선 그리기
//context.fill(); //색 채우기
</script>
beginPath() 로 패스그리기의 시작을 알리고 moveTo()로 패스 시작점을 설정한다
그리고 lineTo() 를 이용하여 패스의 경로를, 그리는 방향 대로 이동한다
마지막으로 stroke()로 패스의 윤곽선을 그린다
주석처리된 fill() 함수로 패스를 그릴 경우 패스 속이 색(기존 검정색)으로 채워지게 된다
이런식으로 삼각형은 물론, 사각형, 오각형,.. N각형의 도형을 맘껏 그릴 수 있다
원 그리기
앞서 살펴본 삼각형 그리기는 직선을 연결한 도형일 경우에는 적합하지만 곡선이나 원을
그릴 수는 없다. 즉 lineTo() 함수는 직선을 그리는 함수이다
원이나 곡선 역시 패스 그리기의 일종으로 앞서 살펴본 과정을 그대로 따른다
다만 직선을 그리는 함수인 lineTo() 대신 원을 그리는 함수인 arc() 나 배지곡선을 그리는 함수인 quadraticCurveTo() 함수를 이용하면 된다
간단한 원그리기 샘플을 살펴 보자
var canvas = document.getElementById("cv");
var context = canvas.getContext("2d");
context.beginPath(); //패스 그리기 시작
context.arc(70,70,50,0, 2*Math.PI, true); //원그리기
context.stroke(); //윤관선 그리기
</script>
패스 닫기
패스를 이용해 도형을 마음껏 그릴 수 있으려면 관련 학습을 조금 더 해야 한다
패스와 관련된 추가 학습은 다른 사이트를 참고하도록 하며 이 글에서는 명시적으로 패스를 닫는 closePath() 함수에 대해 알아보면서 패스 정리를 마치고자 한다
closePath()는 패스를 명시적으로 닫는 역할을 한다
반드시 사용해야 하는 것은 아니지만 명시적으로 closePath()를 호출해 주면
마지막 패스의 좌표와 시작좌표를 자동으로 연결해 주기 때문에 편리하다
다음은 앞서 살펴본 삼각형 그리기 예에서 마지막 패스를 생략하고 closePath()를 대신 사용하였다
즉 마지막 lineTo() 함수가 없어도 자동으로 시작점과 연결해 주기 때문에 결과는 동일하다
var canvas = document.getElementById("cv");
var context = canvas.getContext("2d");
context.beginPath(); //패스 그리기 시작
context.moveTo(50,10); //패스 시작점 지정
context.lineTo(20 ,100); //패스 이동점 지정
context.lineTo(80 ,100);
context.closePath(); //마지막 패스 이동점 대신 패스를 명시적으로 닫는다
context.stroke(); //윤관선 그리기
</script>
스타일 및 효과
캔버스에 그리기 작업을 할 경우 별다른 스타일을 지정하지 않으면 기본 스타일이 적용된다
앞서 살펴본 샘플에서 도형의 안,팎의 색이 검정색이었던 것은 기본값이기 때문이다
스타일을 적용하면 도형의 색 지정 뿐만 아니라 그라데이션 효과, 그림자 효과등을 줄 수 있다
색 지정
우선 간단히 색을 지정하는 예를 보자. 앞서 살펴본 사각형 그리기 예에서 색을 지정한다
채우기 스타일은 fillStyle 로 윤곽선 스타일은 strokeStyle 로 색을 지정하면 된다
색을 지정할 때 blue, red 와 같은 문자는 물론 #ffffff 혹은 rgb(255,0,0) 등 모든 CSS 컬러를 사용할 수 있다. 색을 지정하지 않았을 땐 기본값으로 #000000(검정색) 이 된다
var canvas = document.getElementById("cv");
var context = canvas.getContext("2d");
context.fillStyle = "blue";
context.fillRect(10,10,100,100); //파란색으로 채운 사각형
context.strokeStyle = "red";
context.strokeRect(120,10,100,100); //빨가색 윤곽선 사각형
</script>
그라데이션 효과
fillStyle 이나 strokeStyle를 통해 색깔 지정 뿐만 아니라 그라데이션 효과도 줄 수 있다
그라데이션은 선형그라데이션과 원형그라데이션 두 가지 종류가 있다
선형 그라데이션
: (x,y) 지점에서 (x1,y1) 까지 직선으로 색조가 변화한다
createLinearGradient(x,y,x1,y1) 함수 이용
원형 그리데이션
: 중심이 (x,y), 반지름 r인 원에서 중심이 (x1,y1), 반지름이 r1 인 원 사이의 색조가 변화한다
createRadialGradient(x,y,r,x1,y1,r1) 함수 이용
createXXXGradient 함수로 그라데이션의 형태를 지정한 후,
addColorStop(offset, color) 함수를 이용하여 각 지점에 이용될 색을 지정한다
offset는 0.0(시작점) 에서 1.0 (끝점) 사이의 위치 값을 나타내며 해당 위치의 색을 지정한다
사각형에 선형 그라데이션 효과를 준 예를 살펴 보자
두 사각형 모두 선형 그라데이션 효과를 준 것이며 직선 방향을 조정하여 가로,세로 효과를 줬다
(화살표는 색조 변화 방향을 나타냄)
var canvas = document.getElementById("cv");
var context = canvas.getContext("2d");
var gradient = context.createLinearGradient(0,0,100,0);
gradient.addColorStop(0,"white");
gradient.addColorStop(1,"blue");
context.fillStyle = gradient;
context.fillRect(10,10,100,100);
gradient = context.createLinearGradient(0,0,0,100);
gradient.addColorStop(0,"white");
gradient.addColorStop(1,"red");
context.strokeStyle = gradient;
context.strokeRect(120,10,100,100);
</script>
그림자 효과
선이나 도형에 그림자 효과를 줄 수 있다.
shadowOffsetX, shadowOffsetY 함수를 이용하여 원본 도형의 위치를 기준으로 그림자의 위치를 지정할 수 있으며 shadowColor 로 그림자 색상 shadowBlur로 그림자의 흐리기를 조정할 수 있다
var canvas = document.getElementById("cv");
var context = canvas.getContext("2d");
context.shadowColor = "green";
context.shadowOffsetX = 5;
context.shadowOffsetY = 5;
context.shadowBlur = 2;
context.fillStyle = "blue";
context.fillRect(10,10,100,100);
</script>
이미지 및 텍스트 그리기
캔버스에는 선이나 각종 도형 이외에도 이미지 파일을 삽입하거나 텍스트를 직접 그릴 수도 있다
캔버스에 텍스트 그리기를 이용하면 글자에 각종 효과를 줄 수 있는 장점이 있다
그리고 이미지 역시 각종 이미지 처리를 할 수 있다는 장점이 있겠다
텍스트 그리기
우선 캔버스에 텍스트를 그리는 예를 살펴 보자
다른 도형 그리기와 마찬가지로 채워진 텍스트 혹은 윤곽선만 있는 텍스트를 그릴 수 있다
var canvas = document.getElementById("cv");
var context = canvas.getContext("2d");
var msg = "Hello, Canvas!"
context.font = "20px '맑은 고딕'";
context.fillText(msg, 10 ,50);
context.font = "40px 'Tahoma'";
context.strokeText(msg, 10 ,100);
</script>
이미지 그리기
drawImage 함수를 이용하여 캔버스에 이미지 파일을 삽입할 수 있다
주의할 점은 drawImage의 호출 시점이다. 이미지가 모두 로딩된 이후에 이 함수를 호출해야 한다
따라서 이미지 로딩이 완료될 때 발생하는 onload 이벤트에서 이 함수를 사용하는 것이 일반적이다
눈의 즐거움을 위해 손담비 사진을 이용해 샘플을 만들어 보자 ^.^
Image 객체의 onload 이벤트에서 drawImage 함수가 호출되는 것을 눈여겨 보기 바라며
이미지를 이용하여 사각형을 그릴 때 채우기 패턴으로 사용할 수도 있다
예에서는 손담비 이미지를 기반으로 패턴을 생성하여 사각형의 채우기 스타일로 사용하고 있다
그리고 회전효과도 가미했다(이미지 그리기와는 무관하지만...)
var canvas = document.getElementById("cv");
var context = canvas.getContext("2d");
var image = new Image();
image.onload = function(){
context.rotate(20*Math.PI/180); //회전효과
context.drawImage(image,30,10); //이미지 그리기
var pattern = context.createPattern(image,"repeat"); //반복패턴정의
context.fillStyle = pattern; //fill 패턴 지정
context.fillRect(200,10,200,250); //이미지로 사각형을 채운다
}
image.src = "sondambi.bmp";
</script>
Canvas 초기화
그림을 그리다 모두 지우고 싶을 때가 있다
캔버스에 각종 그래픽 작업을 하다가 모든 것을 지우고 다시 시작하고 싶은,
일명 리셋(reset)을 하고 싶다면 매우 단순하게 초기화를 할 수 있다
캔버스의 너비나 높이 속성을 다시 설정하는 것만으로 캔버스는 완전 초기화 된다
캔버스에 그려진 내용 뿐만 아니라 그리기컨텍스트의 각종 속성도 기본값으로 돌아 온다
canvas.width = canvas.width;
}
마무리 데모
이제 이 글을 마치기 전에 마무리 데모를 살펴 보자
사실 이 글에서 소개된 캔버스 다루기 내용은 극히 일부에 지나지 않는다.
2D 그래픽 처리와 관련한 다양한 기법과 API들이 존재한다.
반드시 관련 자료를 참고하여 추가 학습을 하길 권하며 3D 캔버스인 WebGL도 필요하다면 관련 자료를
찾아 보기 바란다
마지막 데모는 마우스로 그림을 그릴 수 있는 그림판이다
캔버스에 마우스를 데고 자유자재로 움직이면, 선이 마우스를 따라 그려지는 샘플이다
아래 데모 실행화면을 보자. 필자가 캔버스에 대고 그린 그림이다 -.-;
전체 소스
<html>
<head>
<title>Canvas Paint Example</title>
<!--[if IE]><script type="text/javascript" src="excanvas.js"></script><![endif]-->
</head>
<body>
<div id="container">
<canvas id="drawCanvas" width="400" height="300"
style=" position: relative; border: 1px solid #000;"></canvas>
</div>
</body>
</html>
<script type="text/javascript">
if(window.addEventListener){
window.addEventListener('load', InitEvent, false);
}
var canvas, context, tool;
function InitEvent () {
canvas = document.getElementById('drawCanvas');
if (!canvas) {
alert("캔버스 객체를 찾을 수 없음");
return;
}
if (!canvas.getContext) {
alert("Drawing Contextf를 찾을 수 없음");
return;
}
context = canvas.getContext('2d');
if (!context) {
alert("getContext() 함수를 호출 할 수 없음");
return;
}
tool = new tool_pencil();
canvas.addEventListener('mousemove', ev_canvas, false);
canvas.addEventListener('mouseup', ev_canvas, false);
}
function tool_pencil ()
{
var tool = this;
this.started = false;
this.mousedown = function (ev)
{
context.beginPath();
context.moveTo(ev._x, ev._y);
tool.started = true;
};
this.mousemove = function (ev)
{
if (tool.started)
{
context.lineTo(ev._x, ev._y);
context.stroke();
}
};
// 마우스 떼면 그리기 작업을 중단한다
this.mouseup = function (ev)
{
if (tool.started){
tool.mousemove(ev);
tool.started = false;
}
};
}
// Canvas요소 내의 좌표를 결정 한다.
function ev_canvas (ev)
{
if (ev.layerX || ev.layerX == 0)
{ // Firefox 브라우저
ev._x = ev.layerX;
ev._y = ev.layerY;
}
else if (ev.offsetX || ev.offsetX == 0)
{ // Opera 브라우저
ev._x = ev.offsetX;
ev._y = ev.offsetY;
}
// tool의 이벤트 핸들러를 호출한다.
var func = tool[ev.type];
if (func) {
func(ev);
}
}
</script>
'모바일 > HTML5' 카테고리의 다른 글
HTML5 관련 유용한 레퍼(참조) 사이트 (0) | 2010.08.26 |
---|---|
[HTML5] Video & Audio (6) | 2010.08.24 |
[HTML5] Web SQL Database (0) | 2010.08.17 |
[HTML5] 오프라인 웹 어플리케이션 (0) | 2010.08.12 |
[HTML5] Web Storage (1) | 2010.08.11 |