Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>canvas drag & drop, merge images</title>
- <style>
- canvas { border:1px solid #888; }
- #canvas2 { display: none; }
- .btns { margin-top: 10px; }
- .btns button { width: auto; height: 30px; padding: 0 10px; background-color: #fff; border: 1px solid #888; cursor: pointer; }
- .btns button.active { background-color: #ff0; }
- </style>
- </head>
- <body>
- <div>
- <p>이미지를 두 개 이상 파일에서 선택해 캔버스에 그릴 수 있습니다.<br>캔버스에 그려진 이미지를 하나씩 마우스로 누른채로 이동시킬 수 있습니다.<br>이미지를 두 개까지 선택할 수 있습니다.<br>선택된 이미지를 살제할 수 있습니다.</p>
- </div>
- <canvas id="canvas" width="800" height="500"></canvas>
- <div><input type="file" id="photo" accept="image/*"></div>
- <div class="btns">
- <button class='action btn-draganddrop active' data-action='dragndrop'>Drag & Drop</button>
- <button class='action btn-select' data-action='select'>이미지선택</button>
- <button class='action btn-merge' data-action='merge'>합치기</button>
- <button class='action btn-delete' data-action='delete'>삭제</button>
- </div>
- <canvas id="canvas2" width="800" height="500"></canvas>
- <script src="http://code.jquery.com/jquery-3.5.1.min.js"></script>
- <script>
- const canvas = document.getElementById("canvas");
- const ctx = canvas.getContext("2d");
- const canvas2 = document.getElementById("canvas2");
- const ctx2 = canvas2.getContext("2d");
- const canvasOffset = $("#canvas").offset();
- const offsetX = canvasOffset.left;
- const offsetY = canvasOffset.top;
- const cw = canvas.width;
- const ch = canvas.height;
- let isDown = false;
- let lastX;
- let lastY;
- let images = [];
- let hit = -1;
- let action = "dragndrop";
- let selections = [];
- const drawAll = () => {
- ctx.clearRect(0, 0, cw, ch);
- for (let i = 0; i < images.length; i++) {
- let image = images[i];
- ctx.drawImage(image.img, image.x, image.y, image.w, image.h);
- ctx.closePath();
- if( action === "select" ) {
- if( selections.includes(i) ) {
- ctx.strokeStyle = "#f00";
- ctx.setLineDash([5]);
- ctx.rect(image.x, image.y, image.w, image.h);
- ctx.stroke();
- }
- }
- }
- }
- const handleMouseDown = e => {
- e.preventDefault();
- e.stopPropagation();
- lastX = parseInt(e.clientX - offsetX);
- lastY = parseInt(e.clientY - offsetY);
- hit = getImageIndxByPosition(e);
- if (hit >= 0) {
- if( action === "dragndrop" ) {
- isDown = true;
- $("#canvas").css("cursor","move");
- } else if( action === "select" ) {
- $("#canvas").css("cursor","pointer");
- if( ! selections.includes(hit) ) {
- if( selections.length == 2 ) {
- alert("두 개까지만 선택할 수 있습니다.");
- } else {
- selections.push(hit);
- drawAll();
- }
- }
- }
- }
- }
- const handleMouseUp = e => {
- e.preventDefault();
- e.stopPropagation();
- hit = -1;
- isDown = false;
- $("#canvas").css("cursor","default");
- }
- const handleMouseMove = e => {
- if (!isDown || hit < 0 ) return;
- e.preventDefault();
- e.stopPropagation();
- mouseX = parseInt(e.clientX - offsetX);
- mouseY = parseInt(e.clientY - offsetY);
- let dx = mouseX - lastX;
- let dy = mouseY - lastY;
- lastX = mouseX;
- lastY = mouseY;
- images[hit].x += dx;
- images[hit].y += dy;
- drawAll();
- }
- const getImageIndxByPosition = e => {
- hit = -1;
- for (let i = 0; i < images.length; i++) {
- let image = images[i];
- if (lastX > image.x && lastX < (image.x + image.w) && lastY > image.y && lastY < (image.y + image.h)) {
- hit = i;
- }
- }
- return hit;
- }
- const handlePhotoSelect = e => {
- let photo = e.target.files[0];
- if( ! photo ) return;
- const img = new Image();
- img.onload = () => {
- let imgdata = {};
- imgdata.w = img.width;
- imgdata.h = img.height;
- imgdata.x = 0;
- imgdata.y = 0;
- imgdata.img = img;
- ctx.drawImage(img, 0, 0, imgdata.w, imgdata.h);
- images.push(imgdata);
- }
- const reader = new FileReader();
- reader.onload = file => {
- img.src = file.target.result;
- }
- reader.readAsDataURL(photo);
- }
- const handleActions = obj => {
- action = $(obj).attr("data-action");
- $("div.btns button").removeClass("active");
- $(obj).addClass("active");
- if( action === "select" ) {
- selections = [];
- ctx.beginPath();
- drawAll();
- } else if( action === "merge" ) {
- if( selections.length < 2 ) {
- alert("합치기를 하려면 2개의 이미지가 선택되어야 합니다.");
- $("div.btns button.btn-draganddrop").click();
- return;
- } else {
- if( checkOverlap() ) {
- mergePhoto();
- } else {
- alert("합치기를 하려면 2개의 이미지가 일부라도 겹쳐야 합니다.");
- drawAll();
- $("div.btns button.btn-draganddrop").click();
- }
- }
- } else if( action === "delete" ) {
- if( selections.length < 1 ) {
- alert("삭제 하려면 1개의 이미지가 선택되어야 합니다.");
- $("div.btns button.btn-draganddrop").click();
- return;
- } else {
- let images2 = [];
- for(let i=0; i<images.length; i++ ) {
- if( ! selections.includes(i) ) images2.push(images[i]);
- }
- images = images2;
- drawAll();
- $("div.btns button.btn-draganddrop").click();
- }
- }
- }
- const checkOverlap = () => {
- if( selections.length < 2 ) return false;
- return !( images[0].x > (images[1].x + images[1].w) ||
- (images[0].x + images[0].w) < images[1].x ||
- images[0].y > (images[1].y + images[1].h) ||
- (images[0].y + images[0].h) < images[1].y );
- }
- const mergePhoto = () => {
- ctx.clearRect(0, 0, cw, ch);
- let xs = [];
- let ys = [];
- for(let i = 0; i < selections.length; i++ ) {
- let tmpimg = images[selections[i]];
- ctx2.drawImage(tmpimg.img, tmpimg.x, tmpimg.y, tmpimg.w, tmpimg.h);
- xs.push(tmpimg.x);
- xs.push(tmpimg.x + tmpimg.w);
- ys.push(tmpimg.y);
- ys.push(tmpimg.y + tmpimg.h);
- }
- let xmin = Math.min.apply(null, xs);
- let xmax = Math.max.apply(null, xs);
- let ymin = Math.min.apply(null, ys);
- let ymax = Math.max.apply(null, ys);
- let crop_width = xmax - xmin;
- let crop_height = ymax - ymin;
- let crop_img = ctx2.getImageData(xmin, ymin, crop_width, crop_height);
- let canvas3 = document.createElement("canvas");
- canvas3.width = crop_width;
- canvas3.height = crop_height;
- let ctx3 = canvas3.getContext("2d");
- ctx3.putImageData(crop_img, 0, 0);
- let img = new Image();
- img.onload = () => {
- let images2 = [];
- for(let i=0; i<images.length; i++ ) {
- if( ! selections.includes(i) ) images2.push(images[i]);
- }
- images2.push({img:img, x:xmin, y: ymin, w:crop_width, h:crop_height});
- images = images2;
- drawAll();
- $("div.btns button.btn-draganddrop").click();
- }
- img.src = canvas3.toDataURL("image/png");
- }
- $("#canvas").mousedown(function (e) { handleMouseDown(e); });
- $("#canvas").mousemove(function (e) { handleMouseMove(e); });
- $("#canvas").mouseup(function (e) { handleMouseUp(e); });
- $("#canvas").mouseout(function (e) { handleMouseUp(e); });
- $("#photo").change(function (e) { handlePhotoSelect(e); });
- $("div.btns button").click(function () { handleActions(this); });
- </script>
- </body>
- </html>
Add Comment
Please, Sign In to add comment