如何等待画布中图片加载完成

3

我需要与画布中加载的图像进行交互。

但是我不知道如何实现等待图像加载。如果我只期望画布测试在图像加载时开始与其交互,那么该怎么办?

我必须使用driver.sleep(),但这是一个不好且不可靠的解决方案。以下是页面代码的一部分:

<canvas class='ol-unselectable' width='816' height='400' style='width: 100%; height: 100%;'></canvas>

另外,该应用程序是使用Angular编写的。

浏览器中的开发人员控制台中的Network选项卡显示,在加载图像时会发出Img请求。

我认为可以编写一些代码来检查在浏览器中将图像加载到画布中并通过js执行程序使用它。

但我不知道如何做。请帮帮我。

更新:我尝试构建自定义等待条件:

exports.isAllImageLoad = function isAllImageLoad(driver) {
    return new Condition('image loading', function(driver) {
        return driver.executeScript(
            'var img = new Image();' +
            'img.onload = function() { return true; };' +
            'img.onload()'
        ).then(function(result) {
            console.log('image loading: ' + result);
            return result;
        });
    });
};

并使用它:

return driver.wait(isAllImageLoad(driver), waitTimeOut);

但控制台显示img.onload()的结果是null

更新。我尝试使用以下代码:

exports.isAllImageLoad = function isAllImageLoad(driver) {
    return new Condition('image loading', function(driver) {
        return driver.executeScript(
            'var image = new Image();' +
            'function mainLoop(){' +
                'if(image.complete){' +
                    'return true;' +
                '}else{' +
                    'return false;' +
                '}' +
            '}' +
            'mainLoop();'
        ).then(function(result) {
            console.log('image loading: ' + result);
            return result;
        });
    });
};

但是同样的代码返回了null

感谢回复。所有的解决方案都建议使用图像URL,但事实是,图像加载取决于用户之前的操作。 - Valentina
我尝试构建自定义等待条件:exports.isAllImageLoad = function isAllImageLoad(driver) { return new Condition('image loading', function(driver) { return driver.executeScript( 'var img = new Image();' + 'img.onload = function() { return true; };' + 'img.onload()' ).then(function(result) { console.log('image loading: ' + result); return result; }); }); };并将其与以下代码一起使用: return driver.wait(isAllImageLoad(driver), waitTimeOut); 但控制台显示结果为 null - Valentina
2个回答

1
这是一种替代等待onload事件的方法。
当DOM处理完图像并成功加载,或者图像加载失败时,它会将信号量image.complete设置为true。
您可以使用该信号量来确定是否安全地呈现图像。
var image = new Image();
image.src = "imageURI";
function mainLoop(){
     if(image.complete){
          ctx.drawImage(image,0,0,100,100);
     }else{
          ctx.fillRect(0,0,100,100); // image placeholder
     }
     requestAnimationFrame(mainLoop);
}
mainLoop();

这可以让你在图片加载时继续渲染。
虽然你无法直接判断图片是否已加载或出现错误。
另一种方法是附加自己的信号量。
var image = new Image();
image.src = "imageURI";
image.onload =  function(){this.ready=true}

使用准备好的信号量来表示图像已经准备好渲染。

我尝试像这样使用您的代码:exports.isAllImageLoad = function isAllImageLoad(driver) { return new Condition('image loading', function(driver) { return driver.executeScript( 'var image = new Image();' + 'function mainLoop(){' + 'if(image.complete){' + 'return true;' + '}else{' + 'return false;' + '}' + '}' + 'mainLoop();' ).then(function(result) { console.log('image loading: ' + result); return result; }); }); };但是返回值为null - Valentina
或者您可以使用naturalWidth,当图像加载时必须设置(0宽度的图像不会加载)。 - Kaiido
@Valentina,那不起作用。你只是创建了一个图像。图像需要一个URL或DataURL作为src,即使检查“complete”的方法是轮询方法,在同一执行上下文中函数第一次调用返回true的几率非常低。 - Blindman67

0

您可以将所有代码放在image onload事件中,以便在图像成功加载后进行处理。

演示 (在图像成功加载后在画布上绘制图像)

var ctx = document.getElementById('canvas').getContext('2d');
ctx.fillStyle = 'black';
ctx.font="50px Arial";
ctx.fillText('Loading...', 300, 200);
var image = new Image();
image.src = 'https://s-media-cache-ak0.pinimg.com/originals/e9/dc/10/e9dc10141d0b4e5c9e360cc5669e65ed.jpg';
image.onload = function() {
  ctx.clearRect(0, 0, 816, 480)
  ctx.drawImage(image, 0, 0);
}
#canvas {
  background-color: lightgrey;
}
<canvas id="canvas" class="ol-unselectable" width="816" height="400" style="width: 100%; height: 100%;"></canvas>


我使用UI测试,无法将代码放入onload事件中,我只需要等待图像加载完成即可。 - Valentina
@Valentina,你可以使用不同的CustomEvent处理程序。这将在每次成功加载图像时触发。 - m87

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接