HTML5 이미지 자르기 ( HTML5 Image Splitting example )
캔바스에 그려진 이미지를 일정 크기로 잘라서 다수개의 ImageData 오브젝트를 생성하고 화면에 출력하는 예제
<!DOCTYPE html> <html> <head> <meta charset="EUC-KR"> <title>이미지 조각 맞추기 예제</title> <script type="text/javascript" src="jquery-2.1.1.min.js"></script> <script type="text/javascript"> var canvas = null; var ctx = null; var imgObj = null; var beginX=0, beginY=0; // 이미지가 그려지는 캔바스상의 시작좌표 var fragmentArr = new Array(); var prevFragObj = null; var currFragObj = null; var clickedFrag = null; //ImageFragment Object var clickedGrid = null; //Rect Object $(document).ready(function() { canvas = document.getElementById( "canvas1" ); ctx = canvas.getContext( "2d" ); $('#btnShow').click(function(){ imgObj = new Image(); imgObj.onload=function(e){ drawImg(imgObj); drawGrid(imgObj,'white'); }; imgObj.src='sample.jpg'; }); $('#btnSplit').click(function(){ splitImage(imgObj); }); $('#canvas1').on('mousemove',function(e){ var mx = e.pageX-canvas.offsetLeft; var my = e.pageY-canvas.offsetTop; for(var i=0;i<fragmentArr.length;i++) { if(fragmentArr[i].fragmentPos.isIntersect(mx,my)) { //console.log('배열['i+'] 위에 마우스 위치함'); if(prevFragObj==null) { drawRectOnFrag(fragmentArr[i], 'blue'); prevFragObj = fragmentArr[i]; return; }else if(prevFragObj==fragmentArr[i]) { return; }else { drawRectOnFrag(prevFragObj, 'white'); drawRectOnFrag(fragmentArr[i], 'blue'); prevFragObj = fragmentArr[i]; } return; } } }); $('#canvas1').on('mousedown', function(e){ //원본 이미지 영역을 클릭했는지, 이미지 조각이 그려지는 영역을 클릭했는지 구분한다 var mx = e.pageX-canvas.offsetLeft; var my = e.pageY-canvas.offsetTop; //원본 이미지 영역에서 클릭한 것인가? if(isIntersect(beginX, beginY, imgObj.width, imgObj.height, mx, my)){ //alert('원본 이미지 영역 클릭'); for(var i=0;i<fragmentArr.length;i++) { if(fragmentArr[i].originPos.isIntersect(mx,my)) { //alert(i+' dest 영역 클릭함'); clickedGrid = fragmentArr[i].originPos; //이미지 조각을 원본 이미지 영역의 클릭된 그리드 안에 그림 if(clickedFrag) { ctx.putImageData(clickedFrag.imgData, clickedGrid.x, clickedGrid.y); ctx.fillStyle = 'white'; ctx.rect(clickedFrag.x, clickedFrag.y, Rect.w, Rect.h); ctx.fill(); clickedFrag = null; } return; } } return; }else { // 조각 이미지를 클릭했는지 확인한다 for(var i=0;i<fragmentArr.length;i++) { if(fragmentArr[i].fragmentPos.isIntersect(mx,my)) { //alert('이미지 조각을 클릭함'); clickedFrag = fragmentArr[i]; return; } } } //조각 이미지 영역에서 클릭된 이미지 조각 찾기 }); }); // end of ready(); //캔바스 중앙에 원본 이미지를 그린다 function drawImg(imgObj) { beginX = (canvas.width-imgObj.width)/2; beginY = (canvas.height-imgObj.height)/2; ctx.drawImage(imgObj,beginX,beginY); } //화면상의 이미지가 있는 위치에 6x5 개(총 30개)의 그리드를 그린다 function drawGrid(imgObj,color) { var gridW = imgObj.width/6; var gridH = imgObj.height/5; for(var i=0;i<=5;i++) { //가로선 그리기 ctx.beginPath(); ctx.strokeStyle=color; ctx.moveTo(beginX, beginY+(gridH*i)); ctx.lineTo(beginX+imgObj.width, beginY+(gridH*i)); ctx.stroke(); } for(var i=0;i<=6;i++) { //세로선 그리기 ctx.beginPath(); ctx.strokeStyle=color; ctx.moveTo(beginX+(gridW*i), beginY); ctx.lineTo(beginX+(gridW*i), beginY+imgObj.height); ctx.stroke(); } } //원본 이미지를 6x5 개로 잘라서 배열에 저장하고, 배열저장 순서를 무작위로 섞고, // 캔바스 중앙에 그려진 원본 이미지를 삭제하고 그 자리에 6x5개의 그리드를 그리고, // 캔바스 좌우상하 가장자리에 배열에 저장된 모든 조각 이미지를 그린다 function splitImage(imgObj){ var w = imgObj.width; var h = imgObj.height; var tilesX = 6 var tilesY = 5 var tileWidth = w/tilesX; var tileHeight = h/tilesY; Rect.w = tileWidth; Rect.h = tileHeight; var totalTiles = tilesX * tilesY; var tileData = new Array(); //var fragmentArr = new Array(); // ImageFrament 객체를 저장할 배열 //이미지 조각을 배열에 저장 for(var i=0; i<tilesY; i++) //행 { for(var j=0; j<tilesX; j++) //열 { var originRect = new Rect(j*tileWidth+beginX, i*tileHeight+beginY); var imgFragData = ctx.getImageData(originRect.x, originRect.y, Rect.w, Rect.h); var imgFragObj = new ImageFragment(imgFragData, originRect); fragmentArr.push(imgFragObj); } } //이미지 조각 순서 섞기 fragmentArr = shuffle(fragmentArr); //원본 이미지 지우기 ctx.clearRect(0,0,canvas.width, canvas.height); //원본 이미지가 사라진 위치에 그리드 그리기 drawGrid(imgObj,'blue'); //이미지 조각을 캔바스 상하좌우에 배치하기 var topRight=true; var topDownIdx = 0; var leftRightIdx = 0; for(var i=0; i<fragmentArr.length; i++) { //캔바스 상단/하단에 이미지 조각 배치하기 if(topRight){ if(i*tileWidth<=(canvas.width-tileWidth)){ fragmentArr[i].fragmentPos = new Rect(i*tileWidth, 0), ctx.putImageData(fragmentArr[i].imgData, i*tileWidth, 0); }else if((leftRightIdx * tileWidth)<= (canvas.width-tileWidth)){ fragmentArr[i].fragmentPos = new Rect(leftRightIdx * tileWidth, canvas.height-tileHeight), ctx.putImageData(fragmentArr[i].imgData, leftRightIdx++ * tileWidth, canvas.height-tileHeight); }else { topRight = false i--; } }else{//캔바스 좌우 양단에 이미지 조각 배치하기 if(topDownIdx*tileHeight<=(canvas.height-tileHeight*2)){ fragmentArr[i].fragmentPos = new Rect(0, tileHeight+tileHeight*topDownIdx); ctx.putImageData(fragmentArr[i].imgData, 0, tileHeight+tileHeight*topDownIdx);//왼쪽에 그림 ++i; fragmentArr[i].fragmentPos = new Rect(canvas.width-tileWidth, tileHeight+tileHeight*topDownIdx); ctx.putImageData(fragmentArr[i].imgData, canvas.width-tileWidth, tileHeight+tileHeight*topDownIdx);//오른쪽에 그림 topDownIdx++; } } } } function shuffle(fragmentArr) { var resultArr = new Array(); var idx = 0; while(fragmentArr.length>0) { var idx = Math.floor(Math.random() * fragmentArr.length); var fragObj = fragmentArr[idx]; fragmentArr.splice(idx,1); resultArr.push(fragObj); //console.log(idx+','+tileData.length); } return resultArr; } function ImageFragment(imgData, originPos) { this.imgData = imgData; //이미지 조각의 이미지 데이터(ImageData) this.originPos = originPos; //소스 이미지 상의 위치(Rect) this.fragmentPos = null; //이미지 조각이 그려지는 위치(Rect) } //조각 이미지의 위치와 크기를 표현 function Rect(x,y) { var w = w; var h = h; this.x = x; this.y = y; this.isIntersect = function(x,y) { if(isIntersect(this.x, this.y, Rect.w, Rect.h, x, y)) { return true; } else { return false; } } } function isIntersect(x1,y1,w1,h1, x2,y2) { if((x2>x1 && x2<x1+w1) && (y2>y1 && y2<y1+h1)) { return true; } else { return false; } } //조각 이미지의 테두리를 청색 혹은 백색으로 그린다 function drawRectOnFrag(imgFragObj,color) { var x = imgFragObj.fragmentPos.x; var y = imgFragObj.fragmentPos.y; var w = Rect.w; var h = Rect.h; ctx.beginPath(); ctx.rect(x, y, w, h); ctx.lineWidth = 1; ctx.strokeStyle = color; ctx.stroke(); } </script> <style type="text/css"> canvas {border:1px solid black; } </style> </head> <body> <canvas id="canvas1" width="950" height="700"> </canvas> <button id="btnShow">그림보기</button> <button id="btnSplit">조각내기</button> </body> </html>