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>