一旦用户点击Mask图像,我们允许用户上传自定义图像,如果有单个掩码图像,这工作正常:https://codepen.io/kidsdial/pen/jJBVON
要求:
但如果有……
由于您使用画布元素作为实际绘图,我们可以利用它:
$('.container').click(function(e) { var elements = document.elementsFromPoint(e.clientX, e.clientY); elements.some(element => { if(!element.getContext) return false; var rect = element.getBoundingClientRect(); var x = e.pageX - rect.left; var y = e.pageY - rect.top; var pixel = element.getContext('2d').getImageData(x,y,1,1).data; if(pixel[3] === 255) { setTimeout(() => { $('#fileup').click(); }, 20); return true; } return false; }); });
clientX 和 clientY 是相对于客户区的点击坐标(浏览器中当前可见的页面区域)。使用这些 document.elementsFromPoint() 为我们提供了点击位置下的所有元素。
clientX
clientY
document.elementsFromPoint()
然后我们扫描所有找到的元素,检查它们是否具有该属性 getContext 。 .some() 让我们迭代元素数组,同时让我们提前终止,如果我们选择。我们测试 getContext 看看它是否是一个canvas元素,如果不是,我们可以跳过它。
getContext
.some()
如果它是画布,我们可以继续下一步。 getContext('2d') 抓取画布的绘图上下文,我们可以从中提取原始像素数据 getImageData() 。
getContext('2d')
getImageData()
pageX 和 pageY 来自事件的是相对于整个页面的点击坐标。 getBoundingClientRect() 获取元素相对于页面的位置。组合这些给出了相对于元素的点击坐标。我们用它 getImageData() 在该画布中的单击位置抓取画布像素数据。
pageX
pageY
getBoundingClientRect()
像素数据是交错的红色,蓝色,绿色和alpha(不透明度)值,每个值的范围从0到255。由于我们抓取了一个像素,它将有4个值,最后一个是alpha。然后我们可以使用它来确定我们是否触发文件对话框。
如果我们碰巧在画布中的单击位置找到不透明像素,我们可以触发文件对话框,然后通过返回跳过其余元素 true 来自 .some() 打回来。
true
这是一个有效的解决方案。我只是更新了获取数据的方式。我将所有蒙版保存在一个数组中。然后查找与目标点击关联的数组
var mask; var target; let jsonData = { "path" : " UNEVENSHAPES\/", "info" : { "author" : "", "keywords" : "", "file" : "UNEVENSHAPES", "date" : "Uncalibrated", "title" : "", "description" : "Normal", "generator" : "Export Kit v1.2.8" }, "name" : "UNEVENSHAPES", "layers" : [ { "x" : 0, "height" : 612, "layers" : [ { "x" : 0, "color" : "0xFFFFFF", "height" : 612, "y" : 0, "width" : 612, "shapeType" : "rectangle", "type" : "shape", "name" : "rectangle1" }, { "x" : 20, "height" : 377, "layers" : [ { "x" : 0, "height" : 377, "src" : "d15ad70281961be451263b418a07798b_frame0.png", "y" : 0, "width" : 218, "type" : "image", "name" : "mask_pic1" }, { "radius" : "27 \/ 27", "color" : "0xACACAC", "x" : 52, "y" : 257, "height" : 53, "width" : 53, "shapeType" : "ellipse", "type" : "shape", "name" : "useradd_ellipse1" } ], "y" : 215, "width" : 218, "type" : "group", "name" : "user_pic1" }, { "x" : 191, "height" : 120, "layers" : [ { "x" : 0, "height" : 120, "src" : "2b5d28d0439bc3ce1d856e6c4e5607be_frame1.png", "y" : 0, "width" : 268, "type" : "image", "name" : "mask_pic2" }, { "radius" : "26 \/ 27", "color" : "0xACACAC", "x" : 115, "y" : 43, "height" : 53, "width" : 53, "shapeType" : "ellipse", "type" : "shape", "name" : "useradd_ellipse2" } ], "y" : 472, "width" : 268, "type" : "group", "name" : "user_pic2" }, { "x" : 414, "height" : 302, "layers" : [ { "x" : 0, "height" : 302, "src" : "52c93b6e0a0ffeeb670d0981f89f7fa5_frame2.png", "y" : 0, "width" : 178, "type" : "image", "name" : "mask_pic3" }, { "radius" : "26 \/ 27", "color" : "0xACACAC", "x" : 69, "y" : 182, "height" : 53, "width" : 53, "shapeType" : "ellipse", "type" : "shape", "name" : "useradd_ellipse3" } ], "y" : 290, "width" : 178, "type" : "group", "name" : "user_pic3" }, { "x" : 374, "height" : 377, "layers" : [ { "x" : 0, "height" : 377, "src" : "e92f354018aa8f7e6d279601a868a6b2_frame3.png", "y" : 0, "width" : 218, "type" : "image", "name" : "mask_pic4" }, { "radius" : "26 \/ 27", "color" : "0xACACAC", "x" : 129, "y" : 60, "height" : 53, "width" : 53, "shapeType" : "ellipse", "type" : "shape", "name" : "useradd_ellipse4" } ], "y" : 20, "width" : 218, "type" : "group", "name" : "user_pic4" }, { "x" : 150, "height" : 120, "layers" : [ { "x" : 0, "height" : 120, "src" : "010054750abb290d1bd7fcecfab60524_frame4.png", "y" : 0, "width" : 269, "type" : "image", "name" : "mask_pic5" }, { "radius" : "27 \/ 27", "color" : "0xACACAC", "x" : 103, "y" : 15, "height" : 53, "width" : 53, "shapeType" : "ellipse", "type" : "shape", "name" : "useradd_ellipse5" } ], "y" : 20, "width" : 269, "type" : "group", "name" : "user_pic5" }, { "x" : 20, "height" : 302, "layers" : [ { "x" : 0, "height" : 302, "src" : "e7a5874b58376883adbeafea7ce5e572_frame5.png", "y" : 0, "width" : 176, "type" : "image", "name" : "mask_pic6" }, { "radius" : "26 \/ 27", "color" : "0xACACAC", "x" : 50, "y" : 68, "height" : 53, "width" : 53, "shapeType" : "ellipse", "type" : "shape", "name" : "useradd_ellipse6" } ], "y" : 20, "width" : 176, "type" : "group", "name" : "user_pic6" }, { "x" : 222, "height" : 335, "layers" : [ { "x" : 0, "height" : 335, "src" : "591743efa89d8ee936a6d660d52e82b2_frame6.png", "y" : 0, "width" : 265, "type" : "image", "name" : "mask_pic7" }, { "radius" : "26 \/ 27", "color" : "0xACACAC", "x" : 126, "y" : 114, "height" : 53, "width" : 53, "shapeType" : "ellipse", "type" : "shape", "name" : "useradd_ellipse7" } ], "y" : 123, "width" : 265, "type" : "group", "name" : "user_pic7" }, { "x" : 123, "height" : 334, "layers" : [ { "x" : 0, "height" : 334, "src" : "22997a60cf61d7b59e92620b86ab86d6_frame7.png", "y" : 0, "width" : 264, "type" : "image", "name" : "mask_pic8" }, { "radius" : "27 \/ 27", "color" : "0xACACAC", "x" : 73, "y" : 167, "height" : 53, "width" : 53, "shapeType" : "ellipse", "type" : "shape", "name" : "useradd_ellipse8" } ], "y" : 155, "width" : 264, "type" : "group", "name" : "user_pic8" } ], "y" : 0, "width" : 612, "type" : "group", "name" : "unevenshape04" } ] }; $(document).ready(function() { $('.container').click(function(e) { console.log(e); var res = e.target; target = res.id; console.log(target); setTimeout(() => { $('#fileup').click(); }, 20) }); function getAllSrc(layers){ let arr = []; layers.forEach(layer => { if(layer.src){ arr.push({src: layer.src, x: layer.x , y: layer.y}); } else if(layer.layers){ let newArr = getAllSrc(layer.layers); if(newArr.length > 0){ newArr.forEach(({src, x,y}) =>{ arr.push({src, x: (layer.x + x) , y: (layer.y + y) }); }); } } }); return arr; } function json(data) { var width = 0; var height = 0; /* let layer1 = data.layers; width = layer1[0].width; height = layer1[0].height; let layer2 = layer1[0].layers; */ let arr = getAllSrc(data.layers); let layer1 = data.layers; width = layer1[0].width; height = layer1[0].height; let counter = 0; let table = []; // for (i = 1; i < layer2.length; i++) { for (let {src, x,y} of arr) { // var x = layer2[i].x; // var y = layer2[i].y; // var src = layer2[i].layers[0].src; $(".container").css('width', width + "px").css('height', height + "px").addClass('temp'); var mask = $(".container").mask({ maskImageUrl: 'http://piccellsapp.com:1337/parse/files/PfAppId/' + src, onMaskImageCreate: function(img) { img.css({ "position": "absolute", "left": x + "px", "top": y + "px" }); }, id : counter }); table.push(mask); fileup.onchange = function() { // get the element associated to it. let mask2 = table[target]; mask2.loadImage(URL.createObjectURL(fileup.files[0])); }; counter++; } } json(jsonData); }); // end of document ready // jq plugin for mask (function($) { var JQmasks = []; $.fn.mask = function(options) { // This is the easiest way to have default options. var settings = $.extend({ // These are the defaults. maskImageUrl: undefined, imageUrl: undefined, scale: 1, id: new Date().getUTCMilliseconds().toString(), x: 0, // image start position y: 0, // image start position onMaskImageCreate: function(div) {}, }, options); var container = $(this); let prevX = 0, prevY = 0, draggable = false, img, canvas, context, image, timeout, initImage = false, startX = settings.x, startY = settings.y, div; container.mousePosition = function(event) { return { x: event.pageX || event.offsetX, y: event.pageY || event.offsetY }; } container.selected = function(ev) { var pos = container.mousePosition(ev); var item = $(".masked-img canvas").filter(function() { var offset = $(this).offset() var x = pos.x - offset.left; var y = pos.y - offset.top; var d = this.getContext('2d').getImageData(x, y, 1, 1).data; return d[0] > 0 }); JQmasks.forEach(function(el) { var id = item.length > 0 ? $(item).attr("id") : ""; if (el.id == id) el.item.enable(); else el.item.disable(); }); }; container.enable = function() { draggable = true; $(canvas).attr("active", "true"); div.css({ "z-index": 2 }); } container.disable = function() { draggable = false; $(canvas).attr("active", "false"); div.css({ "z-index": 1 }); } container.onDragStart = function(evt) { container.selected(evt); prevX = evt.clientX; prevY = evt.clientY; var img = new Image(); evt.originalEvent.dataTransfer.setDragImage(img, 10, 10); evt.originalEvent.dataTransfer.setData('text/plain', 'anything'); }; container.getImagePosition = function() { return { x: settings.x, y: settings.y, scale: settings.scale }; }; container.onDragOver = function(evt) { if (draggable && $(canvas).attr("active") === "true") { var x = settings.x + evt.clientX - prevX; var y = settings.y + evt.clientY - prevY; if (x == settings.x && y == settings.y) return; // position has not changed settings.x += evt.clientX - prevX; settings.y += evt.clientY - prevY; prevX = evt.clientX; prevY = evt.clientY; container.updateStyle(); } }; container.updateStyle = function() { clearTimeout(timeout); timeout = setTimeout(function() { context.clearRect(0, 0, canvas.width, canvas.height); context.beginPath(); context.globalCompositeOperation = "source-over"; image = new Image(); image.setAttribute('crossOrigin', 'anonymous'); image.src = settings.maskImageUrl; image.onload = function() { canvas.width = image.width; canvas.height = image.height; context.drawImage(image, 0, 0, image.width, image.height); div.css({ "width": image.width, "height": image.height }); }; img = new Image(); img.src = settings.imageUrl; img.setAttribute('crossOrigin', 'anonymous'); img.onload = function() { settings.x = settings.x == 0 && initImage ? (canvas.width - (img.width * settings.scale)) / 2 : settings.x; settings.y = settings.y == 0 && initImage ? (canvas.height - (img.height * settings.scale)) / 2 : settings.y; context.globalCompositeOperation = 'source-atop'; context.drawImage(img, settings.x, settings.y, img.width * settings.scale, img.height * settings.scale); initImage = false; }; }, 0); }; // change the draggable image container.loadImage = function(imageUrl) { console.log("load"); if (img) img.remove(); // reset the code. settings.y = startY; settings.x = startX; prevX = prevY = 0; settings.imageUrl = imageUrl; initImage = true; container.updateStyle(); }; // change the masked Image container.loadMaskImage = function(imageUrl, from) { if (div) div.remove(); canvas = document.createElement("canvas"); context = canvas.getContext('2d'); canvas.setAttribute("draggable", "true"); canvas.setAttribute("id", settings.id); settings.maskImageUrl = imageUrl; div = $("<div/>", { "class": "masked-img" }).append(canvas); // div.find("canvas").on('touchstart mousedown', function(event) div.find("canvas").on('dragstart', function(event) { if (event.handled === false) return; event.handled = true; container.onDragStart(event); }); div.find("canvas").on('touchend mouseup', function(event) { if (event.handled === false) return; event.handled = true; container.selected(event); }); div.find("canvas").bind("dragover", container.onDragOver); container.append(div); if (settings.onMaskImageCreate) settings.onMaskImageCreate(div); container.loadImage(settings.imageUrl); }; container.loadMaskImage(settings.maskImageUrl); JQmasks.push({ item: container, id: settings.id }) return container; }; }(jQuery));