闭包中的Canvas元素正在意外更改



我正在创建一个网页,允许用户在上传的图像中添加滤色器。为了做到这一点,我希望将图像的原始副本存储在画布中。然后,每当用户更改其中一个颜色值时,我想使用范围滑块将原始图像复制到新的画布中,对其进行编辑,然后绘制新图像。

我不想将更改直接应用于原始图像的原因是它们可能很难反转。例如,如果用户将图像的蓝色通道设置为0,那么除非我有原始图像,否则用户将无法撤消该效果。

我目前的解决方案是创建一个包含画布元素的闭包。当用户上传照片时,会初始化此关闭。我的关闭代码低于

var scaleCanvas = (function() {
  var scaledCvs = document.createElement('canvas'); //Creates a canvas object
  var scaledCtx = scaledCvs.getContext("2d"); //Gets canvas context
  // All the functions in this section can access scaledCanvas
  return {
    init: function(cvs) {
      scaledCvs = cvs;
      console.log("Image Stored")
    }, //close init
    getImg: function() {
      return (scaledCvs);
    } //Close getImg
  }; //close return
})();

画布初始化后,可以使用scaleCcanvas.getImg((函数对其进行访问。这方面的一个例子是在我的函数adjustFilters((期间,它被下面的范围滑块元素调用

<div class="slidecontainer">
    <label>Blue Channel</label>
    <input type="range" min="0" max="150" value="100" class="slider" id="blue" onchange="adjustFilters();"/>
</div>

蓝色滑块更改后,我加载要用于显示图像的画布。然后我使用scaleCcanvas.getImg((加载我的原始图像。然后我应用我感兴趣的效果。然后我绘制图像。但奇怪的是,我的闭包中的scaledCV变量似乎正在更改。我这样说是因为如果我为"0"选择一个值;蓝色";如果为0,则我不可能恢复原始的蓝色通道。除非我的闭包中的scaledCV被以某种方式更改,否则这不应该发生。

function adjustFilters() {
  var canvas = document.getElementById("dispImg"); //gets the canvas element
  canvas.style.display = "block"; //Makes the canvas visible
  var context = canvas.getContext("2d"); //Using 2D context
  // look up the size the canvas is being displayed at
  const width = canvas.clientWidth;
  const height = canvas.clientHeight;
  var imgCV = scaleCanvas.getImg(); //Gets the original canvas image
  var imgCtx = imgCV.getContext('2d');
  var blue = document.getElementById("blue").value / 100; //Gets value of the blue slider
  // Adjusts blue channel
  adjustColor(imgCtx, imgCV.height, imgCV.width, "blue", blue)
  // Draws the Image
  context.clearRect(0, 0, canvas.width, canvas.height);
  context.drawImage(imgCV, 0, 0);
}

我正在寻找如何使我的代码按预期运行的建议。即,除了调用init函数外,我需要不调整闭包中的变量scaledCvs。

谢谢

观察到的行为的原因是画布元素是通过引用传递的,因此

init: function(cvs) {
  scaledCvs = cvs;
  console.log("Image Stored")
}, //close init

不创建cvs的副本,它只是创建一个对它的引用。为了创建实际画布的副本,你需要遵循下面的协议

init: function(cvs) {
                //Create a Copy of the provided canvas (cvs)
                scaledCvs.width=cvs.width;
                scaledCvs.height=cvs.height;
                scaledCtx.drawImage(cvs,0,0);
                }, //close init

为了使整个代码正常工作,您还需要修改getImage((,这样它就不会被传递scaledCV的引用。最终的关闭定义将是

var scaleCanvas = (function() {
        var scaledCvs=document.createElement('canvas'); //Creates a canvas object
        var scaledCtx=scaledCvs.getContext("2d"); //Gets canvas context
        // All the functions in this section can access scaledCanvas
        return {
            init: function(cvs) {
                //Create a Copy of the provided canvas (cvs)
                scaledCvs.width=cvs.width;
                scaledCvs.height=cvs.height;
                scaledCtx.drawImage(cvs,0,0);
                }, //close init
            getImg: function() {
                //Since canvas are passed by reference in order to protect the saved canvas I have to create a copy before passing it out
                var cpCanvas = document.createElement('canvas');
                var context = cpCanvas.getContext("2d");
                cpCanvas.height = scaledCvs.height;
                cpCanvas.width = scaledCvs.width;
                context.drawImage(scaledCvs,0,0);
                return(cpCanvas);
                } //Close getImg
            }; //close return
    })();

所有其他代码可以保持不变。

相关内容

最新更新