HTML5

웹,모바일에서 사용가능한 스크래치 기능

먹세 2013. 4. 5. 10:54

웹에서는 마우스로, 모바일에서는 터치로 스크래치 기능을 구현

내가한건아니고.. adobe에서 샘플로 제공함


<!DOCTYPE html >

<html>

<head>

<title>HTML5 Canvas Scratch-off Demo</title>

<meta charset="UTF-8" />

<style type="text/css">

body {

font-family: sans-serif;

margin-left: 0px;

margin-top: 0px;

margin-right: 0px;

margin-bottom: 0px;

}


h1 {

font-weight: bold;

font-size: 1.2em;

}


.fineprint {

font-size: 0.6em;

}


.bigtext {

font-size: 5em;

}


.cell {

display: table-cell;

vertical-align: middle;

text-align: center;

}


.cell canvas {

vertical-align: middle;

}


.canthumb {

border: 0px solid #222;

}


.bigtopmargin {

margin-top: 5ex;

}


.hidden {

display: none;

}


.blink {

text-decoration: blink; /* Ha ha!! */

}


#main {

    margin:25px;

}


#maincanvas {

border: 0px solid #222;

cursor: pointer;

}

</style>


<script type="text/javascript">

//<![CDATA[


(function() {


// 빨간색 부분을 이미지 경로로 변경

var image = { // back and front images

'back': { 'url':'back.jpg', 'img':null },

'front': { 'url':'fore.jpg', 'img':null }

};


var canvas = {'temp':null, 'draw':null}; // temp and draw canvases


var mouseDown = false;


/**

 * Helper function to get the local coords of an event in an element,

 * since offsetX/offsetY are apparently not entirely supported, but

 * offsetLeft/offsetTop/pageX/pageY are!

 *

 * @param elem element in question

 * @param ev the event

 */

function getLocalCoords(elem, ev) {

var ox = 0, oy = 0;

var first;

var pageX, pageY;


// Walk back up the tree to calculate the total page offset of the

// currentTarget element.  I can't tell you how happy this makes me.

// Really.

while (elem != null) {

ox += elem.offsetLeft;

oy += elem.offsetTop;

elem = elem.offsetParent;

}


if (ev.hasOwnProperty('changedTouches')) {

first = ev.changedTouches[0];

pageX = first.pageX;

pageY = first.pageY;

} else {

pageX = ev.pageX;

pageY = ev.pageY;

}


return { 'x': pageX - ox, 'y': pageY - oy };

}


/**

 * Recomposites the canvases onto the screen

 *

 * Note that my preferred method (putting the background down, then the

 * masked foreground) doesn't seem to work in FF with "source-out"

 * compositing mode (it just leaves the destination canvas blank.)  I

 * like this method because mentally it makes sense to have the

 * foreground drawn on top of the background.

 *

 * Instead, to get the same effect, we draw the whole foreground image,

 * and then mask the background (with "source-atop", which FF seems

 * happy with) and stamp that on top.  The final result is the same, but

 * it's a little bit weird since we're stamping the background on the

 * foreground.

 *

 * OPTIMIZATION: This naively redraws the entire canvas, which involves

 * four full-size image blits.  An optimization would be to track the

 * dirty rectangle in scratchLine(), and only redraw that portion (i.e.

 * in each drawImage() call, pass the dirty rectangle as well--check out

 * the drawImage() documentation for details.)  This would scale to

 * arbitrary-sized images, whereas in its current form, it will dog out

 * if the images are large.

 */

function recompositeCanvases() {

var main = document.getElementById('maincanvas');

var tempctx = canvas.temp.getContext('2d');

var mainctx = main.getContext('2d');


// Step 1: clear the temp

canvas.temp.width = canvas.temp.width; // resizing clears


// Step 2: stamp the draw on the temp (source-over)

tempctx.drawImage(canvas.draw, 0, 0);


/* !!!! this way doesn't work on FF:

// Step 3: stamp the foreground on the temp (!! source-out mode !!)

tempctx.globalCompositeOperation = 'source-out';

tempctx.drawImage(image.front.img, 0, 0);


// Step 4: stamp the background on the display canvas (source-over)

//mainctx.drawImage(image.back.img, 0, 0);


// Step 5: stamp the temp on the display canvas (source-over)

mainctx.drawImage(canvas.temp, 0, 0);

*/


// Step 3: stamp the background on the temp (!! source-atop mode !!)

tempctx.globalCompositeOperation = 'source-atop';

tempctx.drawImage(image.back.img, 0, 0);


// Step 4: stamp the foreground on the display canvas (source-over)

mainctx.drawImage(image.front.img, 0, 0);


// Step 5: stamp the temp on the display canvas (source-over)

mainctx.drawImage(canvas.temp, 0, 0);

}


/**

 * Draw a scratch line

 * 

 * @param can the canvas

 * @param x,y the coordinates

 * @param fresh start a new line if true

 */

function scratchLine(can, x, y, fresh) {

var ctx = can.getContext('2d');

ctx.lineWidth = 50;

ctx.lineCap = ctx.lineJoin = 'round';

ctx.strokeStyle = '#f00'; // can be any opaque color

if (fresh) {

ctx.beginPath();

// this +0.01 hackishly causes Linux Chrome to draw a

// "zero"-length line (a single point), otherwise it doesn't

// draw when the mouse is clicked but not moved:

ctx.moveTo(x+0.01, y);

}

ctx.lineTo(x, y);

ctx.stroke();

}


/**

 * Set up the main canvas and listeners

 */

function setupCanvases() {

var c = document.getElementById('maincanvas');

// set the width and height of the main canvas from the first image

// (assuming both images are the same dimensions)

c.width = image.back.img.width;

c.height = image.back.img.height;


// create the temp and draw canvases, and set their dimensions

// to the same as the main canvas:

canvas.temp = document.createElement('canvas');

canvas.draw = document.createElement('canvas');

canvas.temp.width = canvas.draw.width = c.width;

canvas.temp.height = canvas.draw.height = c.height;


// draw the stuff to start

recompositeCanvases();


/**

* On mouse down, draw a line starting fresh

*/

function mousedown_handler(e) {

var local = getLocalCoords(c, e);

mouseDown = true;


scratchLine(canvas.draw, local.x, local.y, true);

recompositeCanvases();


if (e.cancelable) { e.preventDefault(); } 

return false;

};


/**

* On mouse move, if mouse down, draw a line

*

* We do this on the window to smoothly handle mousing outside

* the canvas

*/

function mousemove_handler(e) {

if (!mouseDown) { return true; }


var local = getLocalCoords(c, e);


scratchLine(canvas.draw, local.x, local.y, false);

recompositeCanvases();


if (e.cancelable) { e.preventDefault(); } 

return false;

};


/**

* On mouseup.  (Listens on window to catch out-of-canvas events.)

*/

function mouseup_handler(e) {

if (mouseDown) {

mouseDown = false;

if (e.cancelable) { e.preventDefault(); } 

return false;

}


return true;

};


c.addEventListener('mousedown', mousedown_handler, false);

c.addEventListener('touchstart', mousedown_handler, false);


window.addEventListener('mousemove', mousemove_handler, false);

window.addEventListener('touchmove', mousemove_handler, false);


window.addEventListener('mouseup', mouseup_handler, false);

window.addEventListener('touchend', mouseup_handler, false);

}


/**

 * Set up the DOM when loading is complete

 */

function loadingComplete() {

var loading = document.getElementById('loading');

var main = document.getElementById('main');


loading.className = 'hidden';

main.className = '';

}


/**

 * Handle loading of needed image resources

 */

function loadImages() {

var loadCount = 0;

var loadTotal = 0;

var loadingIndicator;


function imageLoaded(e) {

loadCount++;


if (loadCount >= loadTotal) {

setupCanvases();

loadingComplete();

}

}


for (k in image) if (image.hasOwnProperty(k))

loadTotal++;


for (k in image) if (image.hasOwnProperty(k)) {

image[k].img = document.createElement('img'); // image is global

image[k].img.addEventListener('load', imageLoaded, false);

image[k].img.src = image[k].url;

}

}


/**

 * Handle page load

 */

window.addEventListener('load', function() {

var resetButton = document.getElementById('resetbutton');


loadImages();


resetButton.addEventListener('click', function() {

// clear the draw canvas

canvas.draw.width = canvas.draw.width;

recompositeCanvases()


return false;

}, false);


}, false);


})();


//]]>

</script>

</head>

<body>

<div><canvas id="maincanvas"></canvas></div>

</body>

</html>



반응형

'HTML5' 카테고리의 다른 글

HTML 특수문자 코드표  (0) 2013.12.12
페북 공유하기  (0) 2013.05.21
객체 3d로 돌리기  (0) 2013.04.05
웹스토리지 예제  (0) 2013.04.05
스크롤시 이미지 고정  (0) 2013.04.05