简体   繁体   English

分配较高的z索引以遮罩图像

[英]Assign higher z-index to mask images

We are Fetching mask image from JSON & displaying inside Container 我们正在从JSON获取蒙版图像并在Container中显示

在此处输入图片说明

Onclick Mask image, we are allowing to upload another image on mask as below, also user can drag the uploaded image as in Codepen1 , everything was fine... Onclick蒙版图像,我们允许如下在蒙版上上传另一个图像,用户也可以像Codepen1一样拖动上传的图像,一切都很好...

在此处输入图片说明

Now Client want to display mask image above Box image, so I displayed mask image on top of box image as below : 现在客户端要在Box图像上方显示遮罩图像,因此我在Box图像顶部显示了遮罩图像,如下所示:

Issue : 问题

在此处输入图片说明

when I click on mask image [left side], higher z-index value assign to box image, so box image will override mask image. 当我单击蒙版图像[左侧]时,较高的z-index值分配给框图像,因此框图像将覆盖蒙版图像。 because mask image & box image are overlapped with each other. 因为蒙版图像和盒子图像相互重叠

when I click on mask image [right side], then there is no problem... 当我单击蒙版图像[右侧]时,就没有问题了...

Also, I can able to drag the uploaded image successfully from the right side of mask image but not from the left side. 另外,我可以从蒙版图像的右侧成功拖动上载的图像,而不能从左侧成功拖动。

Z-index code : Z索引代码

 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.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();
            });
        };

Snippet : 片段

 var target; const imageUrl = ""; let jsonData = { "layers": [{ "name": "design3", "x": 0, "y": 0, "width": 300, "height": 300, "layers":[ { "type":"image", "src":"14IVyVb.png", "name":"bg_img", "x":0, "y":0, "width":200, "height":200 }, { "type":"image", "src":"l8vA9bB.png", "name":"mask_image", "x":100, "y":15, "width":180, "height":166 }] }] }; const containerElement = $('#container'); const fileUp = $('#fileup'); let mask; $(function() { // Upload image onclick mask image containerElement.click(function(e) { // filtering out non-canvas clicks if (e.target.tagName !== 'CANVAS') return; // getting absolute points relative to container const absX = e.offsetX + e.target.parentNode.offsetLeft + e.currentTarget.offsetLeft; const absY = e.offsetY + e.target.parentNode.offsetTop + e.currentTarget.offsetTop; const $canvasList = $(this).find('canvas'); // moving all canvas parents on the same z-index $canvasList.parent().css({ zIndex: 0 }); $canvasList.filter(function() { // filtering only applicable canvases const bbox = this.getBoundingClientRect(); const canvasTop = bbox.top + window.scrollY; const canvasLeft = bbox.left + window.scrollX; return ( absX >= canvasLeft && absX <= canvasLeft + bbox.width && absY >= canvasTop && absY <= canvasTop + bbox.height) }).each(function() { // checking white in a click position const x = absX - this.parentNode.offsetLeft - e.currentTarget.offsetLeft; const y = absY - this.parentNode.offsetTop - e.currentTarget.offsetTop; const pixel = this.getContext('2d').getImageData(x, y, 1, 1).data; if (pixel[3] === 255) { if (!$(e.currentTarget).data('image_set' + target)) $(this).parent().css({ zIndex: 2 }) target = this.id; console.log(target); if (!$(e.currentTarget).data('image_set' + target)) setTimeout(fileUp.click.bind(fileUp), 20); } }) }); // Fetch mask images from json file - IGNORE this code function getAllSrc(layers) { let arr = []; layers.forEach(layer => { if (layer.src) { arr.push({ src: layer.src, x: layer.x, y: layer.y, height: layer.height, width: layer.width, name: layer.name }); } else if (layer.layers) { let newArr = getAllSrc(layer.layers); if (newArr.length > 0) { newArr.forEach(({ src, x, y, height, width, name }) => { arr.push({ src, x: (layer.x + x), y: (layer.y + y), height, width, name: (name) }); }); } } }); return arr; } function json(data) { var width = 0; var height = 0; let arr = getAllSrc(data.layers); let layer1 = data.layers; width = layer1[0].width; height = layer1[0].height; let counter = 0; let table = []; // container dimensions containerElement.css('width', width + "px").css('height', height + "px").addClass('temp'); //end for (let { src, x, y, name } of arr) { //Get Height and width of mask image [ edit button ] var ImagePosition = arr; //code end var imageUrl1 = imageUrl; var mask = $(".container").mask({ imageUrl: name.indexOf('mask_') !== -1 ? imageUrl1 : undefined, // Fetch Mask images maskImageUrl: 'http://i.imgur.com/' + src, // end onMaskImageCreate: function(img) { // Mask image positions img.css({ "position": "absolute", "left": x + "px", "top": y + "px" }); // end }, id: counter }); // here ImagePosition.map(function(cur, index) { var available = cur.name.includes('mask_'); if (!available) { $('.masked-img' + index).css('pointer-events', 'none'); } }); table.push(mask); fileup.onchange = function() { let mask2 = table[target]; const newImageLoadedId = mask2.loadImage(URL.createObjectURL(fileup.files[0])); document.getElementById('fileup').value = ""; }; counter++; } return mask; } mask = json(jsonData); }); // end of function // Image code (function($) { window.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); // Create the image properties settings.maskImage = new Image settings.image = new Image // set the cross-origin attributes settings.maskImage.setAttribute('crossOrigin', 'anonymous'); settings.image.setAttribute('crossOrigin', 'anonymous'); settings.maskImage.onload = function() { // once the mask is loaded, load the image container.loadImage(settings.imageUrl) container.drawMask() } settings.image.onload = function() { // once the image is loaded, render to canvas container.drawImage() } 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.drawMask = function() { if (!settings.maskImage) return true; canvas.width = settings.maskImage.width; canvas.height = settings.maskImage.height; context.save(); context.beginPath(); context.globalCompositeOperation = "source-over"; // draw the masked image after scaling if (settings.maskImage) context.drawImage(settings.maskImage, 0, 0, settings.maskImage.width, settings.maskImage.height); context.restore() }; container.drawImage = function() { const img = settings.image 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.save(); context.translate(settings.x + img.width / 2, settings.y + img.height / 2); context.rotate(settings.rotate); context.scale(settings.scale, settings.scale); context.translate(-(settings.x + img.width / 2), -(settings.y + img.height / 2)); let width = img.width, height = img.height; if (img) context.drawImage(img, settings.x, settings.y, width, height); context.restore(); initImage = false; } // change the draggable image container.onDragStart = function(evt) { // console.log('Draw started'); if (evt.target.getContext) { var pixel = evt.target.getContext('2d').getImageData(evt.offsetX, evt.offsetY, 1, 1).data; $(canvas).attr("active", "true"); 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.onDragOver = function(evt) { // console.log('Drag over'); if (evt.target.getContext) { var pixel = evt.target.getContext('2d').getImageData(evt.offsetX, evt.offsetY, 1, 1).data; if (pixel[3] === 255) { 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; //logTMatrix(settings); clearTimeout(timeout); timeout = setTimeout(function() { container.drawMask(); container.drawImage(); }, 1); } } else { evt.stopPropagation(); return false; } } }; container.loadImage = function(imageUrl) { if (!imageUrl) return true; settings.y = startY; settings.x = startX; prevX = prevY = 0; initImage = true; settings.image.src = imageUrl; // CHANGED // sirpepole Add this return settings.id; }; container.loadMaskImage = function(imageUrl, from) { canvas = document.createElement("canvas"); context = canvas.getContext('2d'); canvas.setAttribute("draggable", "true"); canvas.setAttribute("id", settings.id); // settings.maskImageUrl = imageUrl; settings.maskImage.src = imageUrl // CHANGED 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); // Moved this to the settings.maskImage.onload }; if (settings.maskImageUrl) { container.loadMaskImage(settings.maskImageUrl); } JQmasks.push({ item: container, id: settings.id }) // Edit image div.addClass('masked-img' + settings.id); div.attr('data-id', settings.id); // ends return container; }; }(jQuery)); 
 .container { background: silver; position: relative; } .container img { position: absolute; top: 0; bottom: 250px; left: 0; right: 0; margin: auto; z-index: 999; } .masked-img { overflow: hidden; position: relative; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"> </script> <input id="fileup" name="fileup" type="file" style="display:none"> <div id="container" class="container"> </div> 

Here is Video link & Code in Pastebin & Fiddle & Codepen 这里是视频链接在和代码引擎收录小提琴Codepen

I am confused by the overall implementation and there are multiple lines terminated without semicolon. 我对整体实现感到困惑,并且有多行以无分号结尾。 Anyway, the root cause is inside container.selected() . 无论如何,根本原因是在container.selected()内部。 You don't need to implement your way to find which canvas is selected. 您无需实施查找所选画布的方法。 You attach the event by using div.find("canvas").on('touchend mouseup', function(event) {...}; and the browser will trigger the event with the correct target for you. When the event is triggered, the listener will be invoked. The target is given in the event object (namely event.currentTarget ). That is the spirit of event listener. 通过使用div.find("canvas").on('touchend mouseup', function(event) {...};附加事件,浏览器将为您触发具有正确目标的事件。触发后,将调用侦听器,目标是在事件对象中指定的(即event.currentTarget ),这就是事件侦听器的精髓。

The original container.selected() predicts which canvas is touched by using mouse pointer position. 原始的container.selected()可以使用鼠标指针的位置来预测要触摸哪个画布。 Since box image and mask image have certain area overlaped, the result may contains two canvas and z-index is applied to the wrong one. 由于框形图像和蒙版图像具有一定的重叠区域,因此结果可能包含两个画布,并且将z-index应用于错误的画布。

I modify container.selected() as follow 我将container.selected()修改如下

container.selected = function(ev) {
    var pos = container.mousePosition(ev);
    var item = ev.currentTarget;

    JQmasks.forEach(function(el) {
        var id = $(item).attr("id");
        if (el.id == id)
            el.item.enable();
        else
            el.item.disable();
    });
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM