我试图理解为什么我的代码中的相同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()
函数时,它不会发布灰度图像,而只是在第二个画布上发布正常图像。
我不确定为什么会这样,因为控制台上没有错误。有关这方面的任何信息都会很棒。谢谢!
答案 0 :(得分:1)
等到图片已加载
当前答案不正确。虽然它会起作用,但这只是运气,如果图像加载时间超过1000毫秒,它将会失败。您需要等待图像加载才能绘制它,你无法猜出多长时间这将需要。
由于文档错误而导致错误的库。
不幸的是,您使用的lib的文档非常稀疏。通过源代码,可以在图像加载时调用onload回调,但由于没有命名参数,我无法确定它是哪个参数。它所使用的FileReader对象也不会覆盖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,它有很好的文档记录,并且使用起来非常简单,并且不会让你猜测何时会出现不可避免的复杂情况。