当通过HTML按钮单击手动调用时,相同的JavaScript函数会产生不同的结果

时间:2016-10-20 20:37:17

标签: javascript html canvas

我试图理解为什么我的代码中的相同JavaScript函数在函数内部调用时产生的结果不同,而不是通过单击HTML按钮调用时。

基本上,我尝试上传图片并使用杜克大学的Simple Image库将其转换为灰度图像。然后,这些图像显示在两个<canvas>元素上。

这是我的代码(不会产生小提琴的道歉,因为我使用的库不能包含在那里。这里是我codepen的链接 -

HTML -

<script src="http://www.dukelearntoprogram.com/course1/common/js/image/SimpleImage.js"></script>
<h1>Upload and Display an Image</h1>
<canvas id="canvas"></canvas>
<canvas id="canvas2"></canvas>
<p>Filename:
<input type="file" multiple="false" accept="image/*" id="fileInput" onchange="upload()">
</p>
<p><input type="button" value="Make Grayscale" onclick="makeGray()"></p>

CSS -

html {
  margin: 10px;
}

h1 {
  font-family: helvetica;
}

canvas {
  width: 500px;
  height: 250px;
  border-style: solid;
}

#textInput {
  font-size: 20px;
}

JavaScript -

var img;

function upload() {
  img = new SimpleImage(fileInput);
  var canvas = document.getElementById("canvas");

  img.drawTo(canvas);
}

function makeGray() {
  for(var pixel of img.values()) {
    var avg = (pixel.getRed() + pixel.getGreen() + pixel.getBlue())/3;
    pixel.setRed(avg);
    pixel.setGreen(avg);
    pixel.setBlue(avg);
  }
  var canvas = document.getElementById("canvas2");

  img.drawTo(canvas);
}

这可行,因为我可以点击Make Grayscale按钮,并在第一个画布上载后在第二个画布上显示灰度图像。但是,当我摆脱Make Grayscale按钮并调用makeGray()函数内部的upload()函数时,它不会发布灰度图像,而只是在第二个画布上发布正常图像。

我不确定为什么会这样,因为控制台上没有错误。有关这方面的任何信息都会很棒。谢谢!

1 个答案:

答案 0 :(得分:1)

等到图片已加载

当前答案不正确。虽然它会起作用,但这只是运气,如果图像加载时间超过1000毫秒,它将会失败。您需要等待图像加载才能绘制它,你无法猜出多长时间这将需要。

由于文档错误而导致错误的库。

不幸的是,您使用的lib的文档非常稀疏。通过源代码,可以在图像加载时调用onload回调,但由于没有命名参数,我无法确定它是哪个参数。它所使用的FileReader对象也不会覆盖onload事件。

您有两种选择。

  • 知道SimpleImage创建的onload回调是什么参数,并提供在加载图像时调用的函数。
  • 使用已知内容并在可以使用该图像时将该信息轮询到锻炼中。

第二个选项

Lib内部评论说,当图像准备就绪img.imageData !== null时,你所做的最好就是轮询图像并等到它准备好渲染。

该函数轮询等待img的SimpleImage对象img.imageData !== null,然后调用函数callback。轮询间隔是pollTime,如果未提供,则默认为250ms

function pollImage(img,callback,pollTime){
    function isReady(){
        if(img.dataURL === null){ // not ready
            setTimeout(isReady,pollTime); // try again soon
        }else{
            callback(); // yes loaded call the callback
        }
    }
    if(img === null || img === undefined){
        throw new ReferenceError("No image object given!");
    }
    if(typeof callback !== "function"){
        throw new ReferenceError("No callback function given!");
    }

    pollTime = pollTime === undefined ? 250 : pollTime; // default to 1/4 second
    setTimeout(isReady,0); // Start as soon as possible

}

然后将代码更改为

function upload() {
  img = new SimpleImage(fileInput);
  pollImage(
      img,
      function(){  // callback function that is run when image is ready
          var canvas = document.getElementById("canvas");
          makeGray();
      },
      200
  );
}  

第三个选项。

就我个人而言,我发现一个推广主题(x)教学的网站却隐藏了一个稀疏文档界面背后的核心概念,这对任何人都没有好处。不要使用SimpleImage。学习直接使用DOM,它有很好的文档记录,并且使用起来非常简单,并且不会让你猜测何时会出现不可避免的复杂情况。