缩放一幅图像会影响另一幅图像

时间:2019-04-29 13:42:40

标签: javascript jquery html5 zoom

背景

我们正在容器中显示两个蒙版。...

用户单击两个蒙版并上传图像。...

现在编辑文本同时显示在两个图像上。...

一旦用户点击“编辑文本”,我们就会显示弹出框。...

我们可以看到正在显示 Zoomin Zoomout 按钮。...

重现问题的步骤

1。单击 Zoomin (放大) 5次,第一张图片...。

2。现在单击Zoomin以获得第二张图片 ....

第一张图片的缩放值现在与第二张图片相等。...

但是,如果我们缩放一个图像,则不应更改其他图像的缩放值。...

这里是16 seconds Video to show the issue

enter image description here

要求

我可以通过为每个图像使用多个变量来静态解决问题。...

但是我需要动态的解决方案,因为我仅对zoom_inzoom_out使用一个名为scale的变量。...

这里是Codepen

以下是代码段:

var target;
    const imageUrl = "https://i.imgur.com/RzEm1WK.png";

    let jsonData = {
        "layers": [{
            "x": 0,
            "height": 612,
            "layers": [{
                "x": 160,
                "src": "ax0HVTs.png",
                "y": 291,
                "height": 296,
                "width": 429,
                "name": "mask_1"
            },
                {
                    "x": 25,
                    "src": "hEM2kEP.png",
                    "height": 324,
                    "width": 471,
                    "y": 22,
                    "name": "mask_2"
                }
            ],
            "y": 0,
            "width": 612
        }]
    };

    const containerElement = $('#container');
    const fileUp = $('#fileup');

    $(function() {

        // Upload image onclick mask image

        containerElement.click(function(e) {
            var res = e.target;
            target = res.id;
            // console.log(target);
            if (e.target.getContext) {
                // click only inside Non Transparent part
                var pixel = e.target.getContext('2d').getImageData(e.offsetX, e.offsetY, 1, 1).data;
                if (pixel[3] === 255) {
                    setTimeout(() => {
                        $('#fileup').click();
                    }, 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 mask = $(".container").mask({
                    imageUrl: imageUrl,

                    // Fetch Mask images
                    maskImageUrl: 'https://i.imgur.com/' + src,
                    // end

                    onMaskImageCreate: function(img) {
                        // Mask image positions
                        img.css({
                            "position": "absolute",
                            "left": x + "px",
                            "top": y + "px"
                        });
                        // end

                    },
                    id: counter
                });
                table.push(mask);
                fileup.onchange = function() {

                    let mask2 = table[target];
                    const imgView = URL.createObjectURL(fileup.files[0]);
                    const newImageLoadedId = mask2.loadImage(URL.createObjectURL(fileup.files[0]));
                    document.getElementById('fileup').value = "";

                    if (($(".masked-img" + newImageLoadedId + ' #renderImage').length) === 0) {
                        $('.masked-img' + newImageLoadedId).append("<img id='renderImage' style='width: 300px' src=" + imgView + ">");
                    } else {
                        $('#renderImage').attr('src', imgView);
                    }

                    //  Edit image - IGNORE this code

                    if ($(".masked-img" + newImageLoadedId).length === 1) {
                        $("<span class=\"pip pip" + newImageLoadedId + "\">" +
                            "<a onclick='document.getElementById(\"dark" + newImageLoadedId + "\").style.display=\"block\";'><span class=\"edit edit" + newImageLoadedId + "\" >Edit </span></a>" +
                            "</span>").insertAfter(".masked-img" + newImageLoadedId).css({
                            "left": ImagePosition[newImageLoadedId].x + (ImagePosition[newImageLoadedId].width / 2) + "px",
                            "top": ImagePosition[newImageLoadedId].y + (ImagePosition[newImageLoadedId].height / 2) + "px"
                        });;
                        $("<div id=\'dark" + newImageLoadedId + "\' class=\'dark_content\'>" +
                            $('#demoTemplate').html() +
                            "<a href=\"javascript:void(0)\" onclick=\"document.getElementById(\'dark" + newImageLoadedId + "\').style.display=\'none\'\">Close</a>" + "</div>").appendTo(".pip" + newImageLoadedId).css({
                            "left": $('.edit' + newImageLoadedId).width() + 2 + "px",
                            "top": "0px"
                        });
                    }
                    //  end
                };
                counter++;
            }
        }
        json(jsonData);
    }); // end of function

    // Image code

    (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.getImagePosition = function() {
                return {
                    x: settings.x,
                    y: settings.y,
                    scale: settings.scale
                };
            };

            container.updateStyle = function() {
                return new Promise((resolve, reject) => {
                    context.beginPath();
                    context.globalCompositeOperation = "source-over";
                    image = new Image();
                    image.setAttribute('crossOrigin', 'anonymous');
                    image.src = settings.maskImageUrl;
                    // console.log(image.src);
                    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
                        });
                        resolve();
                    };
                });
            };

            function renderInnerImage() {
                // img = $('#renderImage'); // new Image()
                img = new Image();
                img.setAttribute('crossOrigin', 'anonymous');
                img.src = settings.imageUrl;
                // console.log(image.src);
                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;
                };
            }

            // change the draggable image

            container.loadImage = function(imageUrl) {
                console.log("load");
                settings.y = startY;
                settings.x = startX;
                // console.log(settings.y);
                // console.log(settings.x);
                prevX = prevY = 0;
                settings.imageUrl = imageUrl;
                // console.log(settings.imageUrl);
                initImage = true;
                container.updateStyle().then(renderInnerImage);
                // 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;
                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
            });
            // Edit image
            div.addClass('masked-img' + settings.id);
            // end
            return container;
        };
    }(jQuery));

    // zoom

    var angle = 0;
    var scale = 1;

    function zoom_in(data) {
        var getParent = data.parentElement.parentElement.parentElement;
        var getId = getParent.id.substring(getParent.id.length - 1);
        console.log(getId);
        scale += .25;
        $('.masked-img' + getId + ' #renderImage').css({
            transform: 'scale('+ scale +')'
        });
    }

    function zoom_out(data) {
        var getParent = data.parentElement.parentElement.parentElement;
        var getId = getParent.id.substring(getParent.id.length - 1);
        console.log(getId);
        scale -= .25;
        $('.masked-img' + getId + ' #renderImage').css({
            transform: 'scale('+ scale +')'
        });
    }
.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;
    }

    .pip {
        display: inline-block;
        margin: 0;
        position: absolute;
    }

    .edit {
        display: block;
        background: #444;
        border: 1px solid black;
        color: white;
        text-align: center;
        cursor: pointer;
        position: absolute;
        z-index: 3;
    }

    .edit:hover {
        background: white;
        color: black;
        position: absolute;
        z-index: 3;
    }

    .dark_content {
        display: none;
        position: relative;
        top: 25%;
        left: 25%;
        width: 250px;
        height: 250px;
        padding: 16px;
        border: 16px solid orange;
        background-color: white;
        z-index: 1002;
        overflow: auto;
    }
<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>

<template id='demoTemplate'>
   <span>
      <div class="btn-group">
         <button type="button" class="js-zoom-in" onclick="zoom_in(this)">Zoom In</button>
         <button type="button" class="js-zoom-out" onclick="zoom_out(this)">Zoom Out</button>
      </div>
      <img id="image" src ="" style ="display:none">
   </span>
</template>

1 个答案:

答案 0 :(得分:3)

问题在于,每次调用函数时,以及每次scale都分配有先前的值时,都使用相同的变量scale。因此,您可以为每个元素使用不同比例的数组。

创建一个空数组:

var scales = [];

在调用函数时检查var(用于此元素)是否已经存在:

if (scales[getId] === undefined) {
    scales[getId] = 1.25;
} else {
    scales[getId] += 0.25;  
}

if (scales[getId] === undefined) {
    scales[getId] = 0.75;
} else {
    scales[getId] -= 0.25;  
}

完整代码:

var target;
const imageUrl = "https://i.imgur.com/RzEm1WK.png";

let jsonData = {
  "layers": [{
    "x": 0,
    "height": 612,
    "layers": [{
        "x": 160,
        "src": "ax0HVTs.png",
        "y": 291,
        "height": 296,
        "width": 429,
        "name": "mask_1"
      },
      {
        "x": 25,
        "src": "hEM2kEP.png",
        "height": 324,
        "width": 471,
        "y": 22,
        "name": "mask_2"
      }
    ],
    "y": 0,
    "width": 612
  }]
};

const containerElement = $('#container');
const fileUp = $('#fileup');

$(function() {

  // Upload image onclick mask image

  containerElement.click(function(e) {
    var res = e.target;
    target = res.id;
    // console.log(target);
    if (e.target.getContext) {
      // click only inside Non Transparent part
      var pixel = e.target.getContext('2d').getImageData(e.offsetX, e.offsetY, 1, 1).data;
      if (pixel[3] === 255) {
        setTimeout(() => {
          $('#fileup').click();
        }, 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 mask = $(".container").mask({
        imageUrl: imageUrl,

        // Fetch Mask images
        maskImageUrl: 'https://i.imgur.com/' + src,
        // end

        onMaskImageCreate: function(img) {
          // Mask image positions
          img.css({
            "position": "absolute",
            "left": x + "px",
            "top": y + "px"
          });
          // end

        },
        id: counter
      });
      table.push(mask);
      fileup.onchange = function() {

        let mask2 = table[target];
        const imgView = URL.createObjectURL(fileup.files[0]);
        const newImageLoadedId = mask2.loadImage(URL.createObjectURL(fileup.files[0]));
        document.getElementById('fileup').value = "";

        if (($(".masked-img" + newImageLoadedId + ' #renderImage').length) === 0) {
          $('.masked-img' + newImageLoadedId).append("<img id='renderImage' style='width: 300px' src=" + imgView + ">");
        } else {
          $('#renderImage').attr('src', imgView);
        }

        //  Edit image - IGNORE this code

        if ($(".masked-img" + newImageLoadedId).length === 1) {
          $("<span class=\"pip pip" + newImageLoadedId + "\">" +
            "<a onclick='document.getElementById(\"dark" + newImageLoadedId + "\").style.display=\"block\";'><span class=\"edit edit" + newImageLoadedId + "\" >Edit </span></a>" +
            "</span>").insertAfter(".masked-img" + newImageLoadedId).css({
            "left": ImagePosition[newImageLoadedId].x + (ImagePosition[newImageLoadedId].width / 2) + "px",
            "top": ImagePosition[newImageLoadedId].y + (ImagePosition[newImageLoadedId].height / 2) + "px"
          });;
          $("<div id=\'dark" + newImageLoadedId + "\' class=\'dark_content\'>" +
            $('#demoTemplate').html() +
            "<a href=\"javascript:void(0)\" onclick=\"document.getElementById(\'dark" + newImageLoadedId + "\').style.display=\'none\'\">Close</a>" + "</div>").appendTo(".pip" + newImageLoadedId).css({
            "left": $('.edit' + newImageLoadedId).width() + 2 + "px",
            "top": "0px"
          });
        }
        //  end
      };
      counter++;
    }
  }
  json(jsonData);
}); // end of function

// Image code

(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.getImagePosition = function() {
      return {
        x: settings.x,
        y: settings.y,
        scale: settings.scale
      };
    };

    container.updateStyle = function() {
      return new Promise((resolve, reject) => {
        context.beginPath();
        context.globalCompositeOperation = "source-over";
        image = new Image();
        image.setAttribute('crossOrigin', 'anonymous');
        image.src = settings.maskImageUrl;
        // console.log(image.src);
        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
          });
          resolve();
        };
      });
    };

    function renderInnerImage() {
      // img = $('#renderImage'); // new Image()
      img = new Image();
      img.setAttribute('crossOrigin', 'anonymous');
      img.src = settings.imageUrl;
      // console.log(image.src);
      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;
      };
    }

    // change the draggable image

    container.loadImage = function(imageUrl) {
      console.log("load");
      settings.y = startY;
      settings.x = startX;
      // console.log(settings.y);
      // console.log(settings.x);
      prevX = prevY = 0;
      settings.imageUrl = imageUrl;
      // console.log(settings.imageUrl);
      initImage = true;
      container.updateStyle().then(renderInnerImage);
      // 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;
      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
    });
    // Edit image
    div.addClass('masked-img' + settings.id);
    // end
    return container;
  };
}(jQuery));

// zoom

var angle = 0;
var scale = 1;

var scales = [];

function zoom_in(data) {
  var getParent = data.parentElement.parentElement.parentElement;
  var getId = getParent.id.substring(getParent.id.length - 1);

  console.log(getId);

  if (scales[getId] === undefined) {
    scales[getId] = 1.25;
  } else {
    scales[getId] += 0.25;
  }

  $('.masked-img' + getId + ' #renderImage').css({
    transform: 'scale(' + scales[getId] + ')'
  });
}

function zoom_out(data) {
  var getParent = data.parentElement.parentElement.parentElement;
  var getId = getParent.id.substring(getParent.id.length - 1);
  console.log(getId);

  if (scales[getId] === undefined) {
    scales[getId] = 0.75;
  } else {
    scales[getId] -= 0.25;
  }

  $('.masked-img' + getId + ' #renderImage').css({
    transform: 'scale(' + scales[getId] + ')'
  });
}
.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;
}

.pip {
  display: inline-block;
  margin: 0;
  position: absolute;
}

.edit {
  display: block;
  background: #444;
  border: 1px solid black;
  color: white;
  text-align: center;
  cursor: pointer;
  position: absolute;
  z-index: 3;
}

.edit:hover {
  background: white;
  color: black;
  position: absolute;
  z-index: 3;
}

.dark_content {
  display: none;
  position: relative;
  top: 25%;
  left: 25%;
  width: 250px;
  height: 250px;
  padding: 16px;
  border: 16px solid orange;
  background-color: white;
  z-index: 1002;
  overflow: auto;
}
<input id="fileup" name="fileup" type="file" style="display:none">

<div id="container" class="container">
</div>

<template id='demoTemplate'>
			<span>
				<div class="btn-group">
					<button type="button" class="js-zoom-in" onclick="zoom_in(this)">Zoom In</button>
					<button type="button" class="js-zoom-out" onclick="zoom_out(this)">Zoom Out</button>
				</div>
				<img id="image" src ="" style ="display:none">
			</span>
		</template>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>