Загрузить изображение только через прозрачную часть - PullRequest
10 голосов
/ 06 марта 2019

На изображении ниже маски изображены 3 части:

1. Внешняя непрозрачная часть

2.Border

3. Внутренняя прозрачная часть

enter image description here

Прямо сейчас. Когда пользователь нажимает на прозрачную или непрозрачную часть, я разрешаю ему загружать изображение ...

Требование :

когда пользователь нажимает на Непрозрачную деталь, чем не должно отображаться окно диалога для загрузки изображения ....

Вот https://codepen.io/kidsdial/pen/jJBVON

var mask;

let jsonData = {
    "path": " love shape\/",
    "info": {
        "author": "",
        "keywords": "",
        "file": "love shape",
        "date": "sRGB",
        "title": "",
        "description": "Normal",
        "generator": "Export Kit v1.2.8"
    },
    "name": "love shape",
    "layers": [{
        "x": 1,
        "height": 613,
        "layers": [{
                "x": 1,
                "color": "0xFFFFFF",
                "height": 612,
                "y": 30,
                "width": 612,
                "shapeType": "rectangle",
                "type": "shape",
                "name": "bg_rectangle_1"
            },
            {
                "x": 40,
                "height": 480,
                "layers": [{
                        "x": 10,
                        "height": 480,
                        "src": "ncdHNan.png",
                        "y": 10,
                        "width": 514,
                        "type": "image",
                        "name": "mask_image_1"
                    },
                    {
                        "radius": "27 \/ 27",
                        "color": "0xACACAC",
                        "x": 233,
                        "y": 205,
                        "height": 53,
                        "width": 53,
                        "shapeType": "ellipse",
                        "type": "shape",
                        "name": "useradd_ellipse1"
                    }
                ],
                "y": 1,
                "width": 514,
                "type": "group",
                "name": "user_image_1"
            }
        ],
        "y": 1,
        "width": 614,
        "type": "group",
        "name": "loveshape_18"
    }]
};

$(document).ready(function() {

    $('.container').click(function(e) {
        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 arr = getAllSrc(data.layers);

        let layer1 = data.layers;
        width = layer1[0].width;
        height = layer1[0].height;

        for (let {
                src,
                x,
                y
            } of arr) {
            $(".container").css('width', width + "px").css('height', height + "px").addClass('temp');

            var mask = $(".container").mask({
                maskImageUrl: 'https://i.imgur.com/' + src,
                onMaskImageCreate: function(img) {

                    img.css({
                        "position": "absolute",
                        "left": x + "px",
                        "top": y + "px"
                    });
                }
            });

            fileup.onchange = function() {
                mask.loadImage(URL.createObjectURL(fileup.files[0]));
            };
        }

    }
    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) {
            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));
.temp {
background: black;
}

.container {
	background: black;
  position: relative;
 
}

.masked-img {
	overflow: hidden;
	margin-top: 30px;
	position: relative;
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>

<input id="fileup" name="fileup" type="file" style="display:none" >

<div class="container">

</div>

1 Ответ

9 голосов
/ 08 марта 2019

В своем вопросе вы говорите, что сердце прозрачно, а остальная часть холста непрозрачна.Однако ваш код рисует сердце непрозрачным, а остальная часть холста остается прозрачной.Я буду предполагать более позднюю ситуацию ниже.

Поскольку вы используете элемент canvas для фактического рисунка, мы можем воспользоваться этим:

$('.container').click(function(e) {
  if(e.target.getContext) {
    var pixel = e.target.getContext('2d').getImageData(e.offsetX, e.offsetY, 1, 1).data;
    if(pixel[3] === 255) {
      setTimeout(() => {
          $('#fileup').click();
      }, 20);
    }
  }
});

e.target - это элементэто на самом деле получил щелчок.Проверка, имеет ли она свойство getContext, говорит нам, является ли это холстом или нет.Если это не так, нет файлового диалога.

Если это холст, мы можем перейти к следующему шагу.getContext('2d') захватывает контекст рисования холста, из которого мы можем извлечь необработанные данные пикселей через getImageData().

offsetX и offsetY - это координаты щелчка относительно элемента, по которому щелкнули.Мы используем их в getImageData() для захвата данных пикселей холста в месте щелчка.

Данные пикселей представляют собой чередующиеся значения красного, синего, зеленого и альфа (непрозрачности), варьирующиеся от 0 до 255 для каждого.Поскольку мы получили один пиксель, у него будет 4 значения, последнее из которых альфа.Затем мы можем использовать это, чтобы определить, будем ли мы запускать диалоговое окно файла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...