/******************************************* - Title : Munjanara Image Editor ¥± - Date : 2025.04.25 - Author : KKH - Email : vsharp12@naver.com *******************************************/ var version = "1.22.25.6.13.12"; var imageMax = 3; var canvasWidth = 400; var canvasHeight = 600; var limitWidth = 1500; var limitHeight = 1440; var limitByte = 300; // K var minWidth = 40; // ÃÖ¼Ò Æø var minHeight = 40; // ÃÖ¼Ò ³ôÀÌ var alpha = 0.3; var prevScaleX, prevScaleY; var backImageWidth, backImageHeight; var locText = 0; var scaleAll = 1; // ÀúÀå½Ã ¸ðµç ¿ä¼ÒÀÇ Å©±â¸¦ ¹Ý¿µ var imageWidth, imageHeight, fileName; var jobIndex = 0; var canvas, activeObj; var img, cropper; var imageInfo = []; var parentImg = []; function initEditor(){ if(imageInfo.length > 0){ if(!confirm("¸ðµç ¿ä¼Ò¸¦ »èÁ¦Çϰí ÃʱâÈ­ ÇÕ´Ï´Ù.")) return; document.location.reload(); } } function initPage(){ if(!imageInfo[jobIndex].src) return; deleteCropper(); addJsonToCanvas(imageInfo[jobIndex].src); } function deleteObject() { if(cropper) return; var objects = canvas.getObjects(); // ±âº» À̹ÌÁöÀÏ °æ¿ì if (objects.length == 1) { Alert("±âº» À̹ÌÁö´Â »èÁ¦ÇÒ ¼ö ¾ø½À´Ï´Ù."); return; } var activeObj = canvas.getActiveObject(); if(!activeObj){ Alert("»èÁ¦ÇÑ ¿ä¼Ò¸¦ ¼±ÅÃÇØÁÖ¼¼¿ä."); return; } // ÀÏ¹Ý ¿ÀºêÁ§Æ® »èÁ¦ if (activeObj && !activeObj.isEditing) { canvas.remove(activeObj); canvas.discardActiveObject(); canvas.requestRenderAll(); objects = canvas.getObjects(); if(objects.length > 1) canvas.setActiveObject(objects[objects.length - 1]); } } function deleteThumbnail(idx) { if(idx == "null") idx = jobIndex; var thumbnails = document.querySelectorAll('.thumbnail'); imageInfo.splice(idx, 1); for (var i = idx; i < thumbnails.length - 1; i++) { thumbnails[i].innerHTML = thumbnails[i + 1].innerHTML; thumbnails[i].title = thumbnails[i + 1].title; var currentBtn = thumbnails[i].querySelector('.close-button'); if (currentBtn) { currentBtn.onclick = function (e) { e.stopPropagation(); deleteThumbnail($('.close-button').index(this)); }; } } thumbnails[thumbnails.length - 1].innerHTML = ''; canvas.clear(); document.querySelector('#image-overlay').style.display = "flex"; thumbnails[thumbnails.length - 1].title = "À§Ä¡ ¼±ÅÃÀº ¸¶¿ì½º ¿À¸¥ÂÊ ¹öưÀ» ´©¸£¼¼¿ä."; jobIndex = imageInfo.length; if(jobIndex > imageMax) jobIndex = imageMax - 1; console.log('deleteThumbnail() job index : ', jobIndex, idx); } function highlightAppliedFilters(obj) { document.querySelectorAll('.filter-buttons button') .forEach(btn => btn.classList.remove('active-filter')); if (!obj || obj.type !== 'image' || !obj.filters) return; obj.filters.forEach(filter => { var filterType = filter?.type; if (!filterType) return; var btn = document.querySelector(`.filter-buttons button[data-filter="${filterType}"]`); if (btn) btn.classList.add('active-filter'); }); } function toggleFilter(filterType) { if (cropper) return; if (!img) { Alert("±âº» À̹ÌÁö°¡ ¼±ÅõÇÁö ¾Ê¾Ò½À´Ï´Ù."); return; } activeObj = canvas.getActiveObject(); if (!activeObj || activeObj.type !== "image") { activeObj = canvas.getObjects()[0]; if (!activeObj) return; } var obj = activeObj; if (filterType === 'FlipX') { obj.flipX = !obj.flipX; canvas.requestRenderAll(); return; } var existing = obj.filters.find(f => f.type === filterType); if (existing) { obj.filters = obj.filters.filter(f => f.type !== filterType); } else { var filter; switch (filterType) { case 'Grayscale': filter = new fabric.Image.filters.Grayscale(); break; case 'Sepia': filter = new fabric.Image.filters.Sepia(); break; case 'Invert': filter = new fabric.Image.filters.Invert(); break; case 'Brightness': filter = new fabric.Image.filters.Brightness({ brightness: 0.2 }); break; case 'Contrast': filter = new fabric.Image.filters.Contrast({ contrast: 0.3 }); break; case 'Noise': filter = new fabric.Image.filters.Noise({ noise: 180 }); break; case 'Pixelate': filter = new fabric.Image.filters.Pixelate({ blocksize: 4 }); break; case 'Blur': filter = new fabric.Image.filters.Blur({ blur: 0.07 }); break; case 'Saturation': filter = new fabric.Image.filters.Saturation({ saturation: 0.5 }); break; case 'Vignette': filter = new fabric.Image.filters.Vignette({ darkness: 0.5, offset: 0.5 }); break; default: return; } if (filter) obj.filters.push(filter); } obj.applyFilters(); highlightAppliedFilters(obj); canvas.requestRenderAll(); } function removeFilters() { if(cropper) return; activeObj = canvas.getActiveObject(); if (!activeObj) activeObj = canvas._objects[0]; // ±×·ì ¶Ç´Â ´ÙÁß ¼±ÅÃÀÏ °æ¿ì var objs = activeObj.type === 'activeSelection' || activeObj.type === 'group' ? activeObj.getObjects() : [activeObj]; objs.forEach(obj => { if (obj.type === 'image' && obj.filters) { obj.filters = []; obj.applyFilters?.(); } highlightAppliedFilters(obj); }); canvas.renderAll(); } function rotateObject() { if(cropper) return; if(!img){ Alert("´ë»óÀÌ ¼±ÅõÇÁö ¾Ê¾Ò½À´Ï´Ù."); return; } activeObj = canvas.getActiveObject(); if(!activeObj) activeObj = canvas._objects[0]; var angle = ((Math.floor(activeObj.angle / 90) * 90) + 90 ) % 360; activeObj.rotate(angle); activeObj.setCoords(); canvas.renderAll(); } function startCrop() { var objects = canvas.getObjects(); if(!img || !cropper && objects.length > 1){ Alert("ÀÚ¸£±â´Â ¹è°æÀ̹ÌÁö¸¸ Á¸ÀçÇÒ¶§ °¡´ÉÇÕ´Ï´Ù."); return; } var center = canvas.getCenter(); if (cropper){ //canvas.remove(cropper); //cropper = null; applyCrop(); }else{ cropper = new fabric.Rect({ left: center.left - 50, top: center.top - 50, width: 100, height: 100, fill: 'rgba(0, 0, 125, 0.2)', stroke: 'gray', strokeWidth: 0.1, lockRotation: true, // ȸÀü °¡´É selectable: true }); canvas.add(cropper); canvas.setActiveObject(cropper); } } function applyCrop() { var rect = canvas.getActiveObject(); if (!rect || rect.type !== 'rect') { startCrop(); return; } if (!img) { alert("À߸± À̹ÌÁö°¡ ¾ø½À´Ï´Ù."); return; } var bgImg = canvas.getObjects('image')[0]; var scaleX = bgImg.scaleX || 1; var scaleY = bgImg.scaleY || 1; var rectBounds = rect.getBoundingRect(); var imgBounds = bgImg.getBoundingRect(); var cropX = (rectBounds.left - imgBounds.left) / scaleX; var cropY = (rectBounds.top - imgBounds.top) / scaleY; var cropW = rect.getScaledWidth() / scaleX; var cropH = rect.getScaledHeight() / scaleY; // ÀÚ¸¥ °á°ú¸¦ Àӽà ĵ¹ö½º·Î ·»´õ¸µ var tempCanvas = document.createElement('canvas'); tempCanvas.width = cropW; tempCanvas.height = cropH; var ctx = tempCanvas.getContext('2d'); ctx.drawImage( bgImg.getElement(), cropX, cropY, cropW, cropH, // source 0, 0, cropW, cropH // destination ); // »õ À̹ÌÁö °´Ã¼·Î º¯È¯ var dataURL = tempCanvas.toDataURL('image/jpeg'); canvas.clear(); addImageToCanvasFromDataURL(dataURL); } function deleteCropper() { if(cropper){ canvas.remove(cropper); cropper = null; } } // ¿ÀºêÁ§Æ® °æ°è °è»ê function getImageBounds(canvas) { canvas.renderAll(); var imageObjects = canvas.getObjects().filter(obj => obj.type === 'image'); if (imageObjects.length === 0) { return { left: 0, top: 0, right: 0, bottom: 0 }; } if (scaleAll) { return imageObjects.reduce((acc, obj) => { var rect = obj.getBoundingRect(true); // ȸÀü, ½ºÄÉÀÏ Æ÷ÇÔµÈ Àý´ë ¹Ù¿îµå acc.left = Math.min(acc.left, rect.left); acc.top = Math.min(acc.top, rect.top); acc.right = Math.max(acc.right, rect.left + rect.width); acc.bottom = Math.max(acc.bottom, rect.top + rect.height); return acc; }, { left: Infinity, top: Infinity, right: -Infinity, bottom: -Infinity }); } else { var obj = imageObjects[0]; var rect = obj.getBoundingRect(true); return { left: rect.left, top: rect.top, right: rect.left + rect.width, bottom: rect.top + rect.height }; } } function setInfoArea(idx){ var infoArea = document.getElementById("info-area"); var str = ""; str += `
Ver : ${version}
`; infoArea.innerHTML = str; } function saveImagesSequentially(idx, delay) { if(cropper) canvas.remove(cropper); if(!idx) idx = 0; if(!delay) delay = 0; if(idx == 0 && imageInfo.length > 0){ for(var i=1;i<=imageMax;i++){ if(i == 1) tail = ""; else tail = i; opener.PutInitImage(tail); } var objects = canvas.getObjects(); if(objects.length > 0){ imageInfo[jobIndex].wrk = canvas.toJSON(); imageInfo[jobIndex].durl = makeDataURL(idx); } Alert('ó¸®Áß ÀÔ´Ï´Ù. Àá½Ã¸¸ ±â´Ù·ÁÁÖ¼¼¿ä..'); } if (idx >= imageInfo.length){ self.close(); return; } console.log(idx, delay, imageInfo[idx].durl.length); var durl = imageInfo[idx].durl; if (durl != null) { setTimeout(function() { saveImage(idx, function() { saveImagesSequentially(idx + 1, delay); // ´ÙÀ½ À̹ÌÁö ó¸® }); }, delay); delay += 400; } } // ¼­¹ö Àü¼Û function saveImage(idx, callback) { if(imageInfo[idx].filename == null) { imageInfo[idx].filename = 'm20250619200820_' + idx + '.jpg'; } var formData = new FormData(); formData.append("data", imageInfo[idx].durl); formData.append("image_width", imageInfo[idx].width); formData.append("image_height", imageInfo[idx].height); formData.append("image_size", imageInfo[idx].durl.length); formData.append("image_name", imageInfo[idx].filename); $.ajax({ type: 'POST', url: '/image_editor/save.htm', data: formData, processData: false, contentType: false, async: false, success: function (data) { var [url, name, size] = data.split("|"); opener.PutImage(opener.document.send_msg, url, name, size); opener.MoveScrollObject('hp_top', -80); } }); if(callback) callback(); } function makeDataURL(idx) { if(idx == "") idx = jobIndex; var objects = canvas.getObjects(); if (objects.length === 0) return; var bounds = getImageBounds(canvas); var userImageWidth = bounds.right - bounds.left; var userImageHeight = bounds.bottom - bounds.top; // ±âº» À̹ÌÁö(¹è°æ À̹ÌÁö)ÀÇ Å©±â var exportWidth = backImageWidth; var exportHeight = backImageHeight; // ȸÀü ¿©ºÎ ÆÇ´Ü var baseImage = objects.find(obj => obj.type === 'image'); var isRotated = baseImage && baseImage.angle % 180 !== 0; // ȸÀü ½Ã ÀúÀå ¿µ¿ªµµ Àüȯ if (isRotated) { [exportWidth, exportHeight] = [backImageHeight, backImageWidth]; } // ÀúÀå Å©±â Á¦ÇÑ Ã³¸® if (exportWidth > limitWidth || exportHeight > limitHeight) { var scale = Math.min(limitWidth / exportWidth, limitHeight / exportHeight); exportWidth *= scale; exportHeight *= scale; } var scaleX = exportWidth / userImageWidth; var scaleY = exportHeight / userImageHeight; // Àӽà ĵ¹ö½º »ý¼º var tempCanvasEl = document.createElement("canvas"); tempCanvasEl.width = exportWidth; tempCanvasEl.height = exportHeight; var tempCanvas = new fabric.Canvas(tempCanvasEl, { backgroundColor: 'white' }); objects.forEach(obj => { var clone = fabric.util.object.clone(obj); // ±âÁØÁ¡°ú ½ºÄÉÀÏ Àû¿ë clone.originX = 'center'; clone.originY = 'center'; clone.scaleX *= scaleX; clone.scaleY *= scaleY; // Á᫐ ÁÂÇ¥ °è»ê var center = obj.getCenterPoint(); clone.left = (center.x - bounds.left) * scaleX; clone.top = (center.y - bounds.top) * scaleY; clone.setCoords(); tempCanvas.add(clone); }); tempCanvas.renderAll(); var dataURL = tempCanvas.toDataURL({ format: "jpeg", quality: 0.7 }); tempCanvas.dispose(); imageInfo[idx].width = exportWidth; imageInfo[idx].height = exportHeight; return dataURL; } function addText() { if(cropper) return; if(!img){ Alert("±âº» À̹ÌÁö°¡ ¼±ÅõÇÁö ¾Ê¾Ò½À´Ï´Ù."); return; } if(locText > 10) locText = 0; var bgImage = canvas._objects[0]; var text = new fabric.Textbox("³»¿ëÃß°¡", { left: canvas.getWidth() / 2 + (locText * 7) + 8, top: canvas.getHeight() / 2 - (locText * 7), width: bgImage.width * bgImage.scaleX - 25, fontSize: document.getElementById('font-size-select').value, fill: document.getElementById('text-color').value, fontFamily: document.getElementById('font-family-select').value, fontWeight: "bold", backgroundColor: Hex2Rgba(document.getElementById('text-bgcolor').value, alpha), selectable: true, editable: true, padding: 0, lineHeight: 1.4, originX: "center", // Á᫐ ±âÁØ ¹èÄ¡ originY: "top", // Ä¿¼­°¡ Á¤»ó À§Ä¡¿¡ ¿Àµµ·Ï Á¶Á¤ textAlign: document.getElementById('font-align-select').value, objectCaching: false, // Ãß°¡ Á÷ÈÄ¿£ ºñȰ¼ºÈ­ strokeWidth: 16, // ¿Ü°û¼± µÎ²² }); text.setControlsVisibility({ mt: false, // top middle mb: false, // bottom middle //ml: false, // middle left //mr: false, // middle right tl: false, // top left tr: false, // top right bl: false, // bottom left br: false, // bottom right //mtr: false // rotation control (middle top rotate) }); document.fonts.ready.then(() => { canvas.add(text); text.setCoords(); text.set({ dirty: true, objectCaching: false }); canvas.setActiveObject(text); var textCount = canvas.getObjects().filter(obj => obj.type === 'textbox').length; if(textCount == 1){ text.enterEditing(); text.selectAll(); } canvas.requestRenderAll(); }); locText++; } function applyToTextbox(callback) { if(cropper) return; activeObj = canvas.getActiveObject(); if (activeObj?.type === 'activeSelection') { activeObj.getObjects().forEach(obj => { if (obj.type === 'textbox') callback(obj); }); } else if (activeObj?.type === 'textbox') { callback(activeObj); } else { var allObjects = canvas.getObjects(); var recentTextbox = [...allObjects].reverse().find(obj => obj.type === 'textbox'); if (recentTextbox) { canvas.setActiveObject(recentTextbox); callback(recentTextbox); } else { addText(); } } canvas.renderAll(); } function setImageAttr(){ if(!img){ Alert("±âº» À̹ÌÁö°¡ ¼±ÅõÇÁö ¾Ê¾Ò½À´Ï´Ù."); return; } document.querySelector('#image-overlay').style.display = "none"; var center = canvas.getCenter(); var images = canvas.getObjects('image'); img.set({ originX: 'center', originY: 'center', left: center.left + images.length * 8, top: center.top + images.length * 8, lockRotation: false, // ȸÀü °¡´É lockScalingX: false, // XÃà Å©±âÁ¶Àý °¡´É lockScalingY: false, // YÃà Å©±âÁ¶Àý °¡´É hasControls: true, // ÄÁÆ®·Ñ ¹Ú½º º¸À̱â lockScalingFlip: true, // À½¼ö ½ºÄÉÀÏ ¹æÁö (µÚÁýÈû ¹æÁö) hoverCursor: 'move', selectable: true, // ¼±Åà °¡´É evented: true // ¸¶¿ì½º À̺¥Æ® Ȱ¼º }); if (images.length == 1) { console.log('base image : ', images.length); var orgSrc = cropper ? imageInfo[jobIndex].src : null; imageInfo[jobIndex] = {src:null, wrk:null, durl:null, width:null, height:null, filename:null}; img.set({ lockMovementX: true, lockMovementY: true, hasControls: false, selectable: false, evented: false }); backImageWidth = img.width; backImageHeight = img.height; imageWidth = img.width * img.scaleX; imageHeight = img.height * img.scaleY; canvas.discardActiveObject(); var jsonData = canvas.toJSON(); if(!orgSrc){ imageInfo[jobIndex].src = jsonData; addImageToThumbnail(img.toDataURL(), jobIndex); }else{ imageInfo[jobIndex].src = orgSrc; } imageInfo[jobIndex].wrk = jsonData; }else{ var baseImg = canvas._objects[0]; if (baseImg) { var scaleRatioX = (baseImg.scaleX || 1) * 0.5; var scaleRatioY = (baseImg.scaleY || 1) * 0.5; img.scaleX = scaleRatioX; img.scaleY = scaleRatioY; } canvas.setActiveObject(img); // Ȱ¼ºÈ­ } img.setCoords(); if(cropper) cropper = null; } function addImageToCanvasFromDataURL(dataURL) { fabric.Image.fromURL(dataURL, function (image) { image._originalElement = image.getElement(); img = image; var widthRatio = canvasWidth / img.width; var heightRatio = canvasHeight / img.height; var scaleRatio = Math.min(widthRatio, heightRatio, 1); img.scale(scaleRatio); img.setCoords(); img.backgroundColor; imageWidth = img.width * img.scaleX; imageHeight = img.height * img.scaleY; canvas.add(img); setImageAttr(); canvas.renderAll(); imageInfo[jobIndex].durl = makeDataURL(jobIndex); console.log("job index : ", jobIndex , ", image info : ", imageInfo[jobIndex]); }); } function addImageToCanvas(file) { deleteCropper(); if(!document.getElementById('multi-image').checked){ var texts = canvas.getObjects().find(obj => obj.type === 'textbox'); if(texts && !confirm("ÀÔ·Â ÁßÀ̽бÛÀÌ ÀÖ½À´Ï´Ù.\n»õ·Î¿î ÀÛ¾÷À» ÁøÇàÇϽðڽÀ´Ï±î?")){ return } canvas.clear(); } var reader = new FileReader(); var fileSizeKB = (file.size / 1024).toFixed(2); reader.onload = function (event) { addImageToCanvasFromDataURL(event.target.result); }; reader.readAsDataURL(file); document.querySelector('#image-overlay').style.display = "none"; } function addJsonToCanvas(jdata, callback){ canvas.clear(); canvas.loadFromJSON(jdata, function () { img = canvas.getObjects().find(obj => obj.type === 'image'); img.set({ lockMovementX: true, lockMovementY: true, hasControls: false, selectable: false, evented: false }); canvas.renderAll(); canvas.setActiveObject(img); // Ȱ¼ºÈ­ if(callback) callback(); }); } function addImageToThumbnail(src, idx){ var div = document.getElementById('thumbnail' + idx); if(!div) document.location.reload(); //if(!div) return; div.style.position = 'relative'; var im = document.createElement('img'); im.src = src; im.style.width = '100%'; im.style.height = 'auto'; im.style.display = 'block'; im.title = ""; var closeBtn = document.createElement('button'); closeBtn.className = 'close-button'; closeBtn.innerText = '¥¹'; closeBtn.style.fontSize = '12px'; closeBtn.style.position = 'absolute'; closeBtn.style.top = '1px'; closeBtn.style.right = '0px'; closeBtn.style.backgroundColor = 'rgba(0, 0, 0, 0.4)'; closeBtn.style.color = 'white'; closeBtn.style.border = 'none'; closeBtn.style.borderRadius = '50%'; closeBtn.style.width = '20px'; closeBtn.style.height = '20px'; closeBtn.style.cursor = 'pointer'; closeBtn.title = ''; $(closeBtn).click(function (e) { e.stopPropagation(); deleteThumbnail($('.close-button').index(this)); }); div.replaceChildren(im, closeBtn); } function callImageFromServer(url, callback) { if(!url) return; url = url.replace('_1.jpg', '.jpg'); fetch(url) .then(response => response.blob()) .then(blob => { // BlobÀ» Fileó·³ »ç¿ë var fileName = url.substring(url.lastIndexOf('/') + 1); var file = new File([blob], fileName, { type: blob.type }); addImageToCanvas(file); if(callback) callback(); }) .catch(err => { console.error("À̹ÌÁö ºÒ·¯¿À±â ½ÇÆÐ:", err); Alert("À̹ÌÁö¸¦ ºÒ·¯¿ÀÁö ¸øÇß½À´Ï´Ù."); return; }); } function loadImagesSequentially(idx, delay) { if(!idx) idx = 0; if(!delay) delay = 500; if (idx >= parentImg.length) return; if (parentImg[idx]) { setTimeout(function() { jobIndex = idx; callImageFromServer(parentImg[idx].src, function() { loadImagesSequentially(idx + 1, delay); // ´ÙÀ½ À̹ÌÁö ó¸® }); }, delay); delay += 200; } } window.onload = function() { if(!opener){ alert("¸ÞÀÎâ°ú Åë½ÅÀÌ ²÷°å½À´Ï´Ù. âÀ» ´Ù½Ã ¿©¼¼¿ä."); return; } document.addEventListener("keydown", function (e) { //console.log(e.key); if (e.key === "Delete" || e.key === "Backspace") { deleteObject(); } if (e.key === "Enter"){ if(cropper){ applyCrop(); return; } if(img && !canvas.getActiveObject()){ e.preventDefault(); addText(); } } }); document.addEventListener("click", function (e) { activeObj = canvas.getActiveObject(); if (!activeObj) highlightAppliedFilters(canvas._objects[0]); }); document.getElementById("upload").addEventListener("change", function (e) { var file = e.target.files[0]; if (file && file.type.startsWith("image/")) { addImageToCanvas(file); } $('#upload').val(''); // ÀÔ·Â ÃʱâÈ­ }); // ±ÛÀÚ »ö º¯°æ document.getElementById('text-color').addEventListener('input', function () { applyToTextbox(obj => obj.set('fill', this.value)); }); // ±ÛÀÚ ¹è°æ»ö º¯°æ document.getElementById('text-bgcolor').addEventListener('input', function () { var bgColor = Hex2Rgba(this.value, alpha || 0.3); applyToTextbox(obj => obj.set('backgroundColor', bgColor)); }); // ±ÛÀÚ Åõ¸íµµ Åä±Û document.getElementById('text-alpha').addEventListener('click', function () { applyToTextbox(obj => { var bgColor = obj.backgroundColor; if (!bgColor) return; var rgbaMatch = bgColor.match(/rgba?\(([^)]+)\)/); if (!rgbaMatch) return; var parts = rgbaMatch[1].split(',').map(p => p.trim()); if (parts.length < 3) return; var [r, g, b, a] = parts; a = parts.length === 4 ? parseFloat(a) : alpha; alpha = a > 0 ? 0 : 0.3; obj.set('backgroundColor', `rgba(${r}, ${g}, ${b}, ${alpha})`); }); }); // ÆùÆ® º¯°æ document.getElementById('font-family-select').addEventListener('change', function () { applyToTextbox(obj => obj.set('fontFamily', this.value)); }); // ±ÛÀÚ Á¤·Ä document.getElementById('font-align-select').addEventListener('change', function () { applyToTextbox(obj => obj.set('textAlign', this.value)); }); // ±ÛÀÚ »çÀÌÁî º¯°æ document.getElementById('font-size-select').addEventListener('input', function () { applyToTextbox(obj => obj.set('fontSize', parseFloat(this.value))); //console.log(parseFloat(this.value)); }); document.getElementById('font-lineheight-select').addEventListener('input', function () { applyToTextbox(obj => obj.set('lineHeight', parseFloat(this.value))); //console.log(parseFloat(this.value)); }); setTimeout(function() { var canvasContainer = document.getElementById('canvas-container'); canvas = new fabric.Canvas("canvas", { width: canvasContainer.offsetWidth, height: canvasContainer.offsetHeight, }); canvas.on('object:moving', function (e) { var obj = e.target; // °´Ã¼ÀÇ °æ°è obj.setCoords(); if (obj.type == 'textbox' || obj.type == 'rect'){ var bounds = getImageBounds(canvas); // À̹ÌÁö °æ°è var rect = obj.getBoundingRect(true); // ½ÇÁ¦ È­¸é °æ°è var dx = obj.left - rect.left; var dy = obj.top - rect.top; let newLeft = obj.left; let newTop = obj.top; if (rect.left < bounds.left) { newLeft += bounds.left - rect.left; } if (rect.left + rect.width > bounds.right) { newLeft -= (rect.left + rect.width) - bounds.right; } if (rect.top < bounds.top) { newTop += bounds.top - rect.top; } if (rect.top + rect.height > bounds.bottom) { newTop -= (rect.top + rect.height) - bounds.bottom; } obj.set({ left: newLeft, top: newTop }); obj.setCoords(); // ´Ù½Ã °è»ê }else{ var boundingBox = obj.getBoundingRect(true); // true: ½ºÄÉÀÏ/ȸÀü ¹Ý¿µ // ÁÂ¿ì °æ°è Á¦ÇÑ if (boundingBox.left < 0) { obj.left -= boundingBox.left; } else if (boundingBox.left + boundingBox.width > canvas.getWidth()) { obj.left -= (boundingBox.left + boundingBox.width - canvas.getWidth()); } // »óÇÏ °æ°è Á¦ÇÑ if (boundingBox.top < 0) { obj.top -= boundingBox.top; } else if (boundingBox.top + boundingBox.height > canvas.getHeight()) { obj.top -= (boundingBox.top + boundingBox.height - canvas.getHeight()); } } }); canvas.on('object:scaling', function (e) { var obj = e.target; if (obj.type !== 'textbox' && obj.type !== 'rect' ) return; // ¿øÁ¡ÀÌ ¿ÞÂÊ »ó´ÜÀÌ µÇµµ·Ï ¼³Á¤ (Ãʱ⠼³Á¤¿¡¼­µµ °°ÀÌ ÇØÁÖ´Â °Ô ÁÁÀ½) obj.set({ originX: 'left', originY: 'top' }); var bounds = getImageBounds(canvas); var rect = obj.getBoundingRect(true); var newScaleX = obj.scaleX; var newScaleY = obj.scaleY; var newLeft = obj.left; var newTop = obj.top; var objWidth = obj.width * newScaleX; var objHeight = obj.height * newScaleY; // ¿ÞÂÊ °æ°è if (rect.left < bounds.left) { var diff = bounds.left - rect.left; newLeft = bounds.left; var maxWidth = objWidth - diff; newScaleX = Math.max(1, maxWidth / obj.width); } // À§ÂÊ °æ°è if (rect.top < bounds.top) { var diff = bounds.top - rect.top; newTop = bounds.top; var maxHeight = objHeight - diff; newScaleY = Math.max(1, maxHeight / obj.height); } // ¿À¸¥ÂÊ °æ°è if (rect.left + rect.width > bounds.right) { var diff = (rect.left + rect.width) - bounds.right; var maxWidth = objWidth - diff; newScaleX = Math.max(1, maxWidth / obj.width); } // ¾Æ·¡ÂÊ °æ°è if (rect.top + rect.height > bounds.bottom) { var diff = (rect.top + rect.height) - bounds.bottom; var maxHeight = objHeight - diff; newScaleY = Math.max(1, maxHeight / obj.height); } obj.set({ scaleX: newScaleX, scaleY: newScaleY, left: newLeft, top: newTop }); obj.setCoords(); }); canvas.on('mouse:down', function (e) { var obj = e.target; if (obj && obj.type === 'textbox') { obj.bringToFront(); } /* ÇØÁ¦¸øÇÏ°Ô if(cropper){ canvas.setActiveObject(cropper); } */ // ÀÚµ¿ÇØÁ¦ if(!obj){ deleteCropper(); } }); document.getElementById("image-overlay").addEventListener("dragover", function (e) { e.preventDefault(); }); document.getElementById("image-overlay").addEventListener("drop", function (e) { e.preventDefault(); canvas.upperCanvasEl.style.border = "none"; var file = e.dataTransfer.files[0]; if (file && file.type.startsWith("image/")) { addImageToCanvas(file); } }); canvas.upperCanvasEl.addEventListener("dragover", function (e) { e.preventDefault(); }); canvas.upperCanvasEl.addEventListener("drop", function (e) { e.preventDefault(); canvas.upperCanvasEl.style.border = "none"; var file = e.dataTransfer.files[0]; if (file && file.type.startsWith("image/")) { imageInfo[jobIndex].filename = file.name; addImageToCanvas(file); } }); canvas.on('selection:created', function (e) { var obj = e.selected[0]; highlightAppliedFilters(obj); }); canvas.on('selection:updated', function (e) { var obj = e.selected[0]; highlightAppliedFilters(obj); }); canvas.on('selection:cleared', function () { document.querySelectorAll('.filter-buttons button') .forEach(btn => btn.classList.remove('active-filter')); }); }, 0); setInfoArea(); // ¸ÞÀÎâ »ùÇà ¹× ¼Ó¼ºÁöÁ¤ parentImg = opener.document.querySelectorAll('.photo_list_image'); var tnList = document.getElementById('thumbnail-container'); for(var i=0;i= imageMax) jobIndex = imageMax - 1; document.getElementById('upload').click(); $('#image-overlay').show(); }else{ var jsonData; if(idx == jobIndex){ if(!confirm('À̹ÌÁö¸¦ ºÒ·¯¿À°Ú½À´Ï±î?')) return; document.getElementById('upload').click(); return; } var objects = canvas.getObjects(); if(objects.length) { imageInfo[jobIndex].wrk = canvas.toJSON(); imageInfo[jobIndex].durl = makeDataURL(jobIndex); } jobIndex = idx; jsonData = imageInfo[jobIndex].wrk; addJsonToCanvas(jsonData); $('#image-overlay').hide(); } console.log('job index : ', jobIndex, ', click index : ', idx); }; $(div).on('contextmenu', function(e) { e.preventDefault(); var objects = canvas.getObjects(); if(objects.length) { imageInfo[jobIndex].wrk = canvas.toJSON(); imageInfo[jobIndex].durl = makeDataURL(jobIndex); } jobIndex = $('.thumbnail').index(this); if(imageInfo[jobIndex] == null){ canvas.clear(); // ¼±Åà À§Ä¡°¡ ¾Æ´Ñ ¸Ç ¾Õ ºó°ø°£ jobIndex = imageInfo.length; if(jobIndex >= imageMax) jobIndex = imageMax - 1; $('#image-overlay').show(); this.title = "À§Ä¡ ¼±ÅÃÀº ¿À¸¥ÂÊ ¹öưÀ» ´©¸£¼¼¿ä."; } }); } loadImagesSequentially(); };