如何等待在画布中加载图像

Posted

技术标签:

【中文标题】如何等待在画布中加载图像【英文标题】:How to wait for loading images in canvas 【发布时间】:2017-07-19 20:07:10 【问题描述】:

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

但我不知道如何实现加载图像的等待。 如果我希望只有画布测试开始与它交互,而图像仍在加载。

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

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

此外,应用程序是用 Angular 编写的。

浏览器开发者控制台中的Network标签显示在加载图片的时候是Img请求。

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

但我不知道该怎么做。请帮帮我。

UPD。我尝试构建自定义等待条件:

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

UPD.我尝试使用此代码:

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,但事实是图片加载不同,取决于用户之前的操作。 我尝试构建自定义等待条件: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 【参考方案1】:

这是等待加载的另一种方法。

当 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 或者你可以使用 naturalWidth ,它必须在图像加载时设置(0宽度图像不会加载) @Valentina 那行不通。您只需创建一个图像。图像需要一个 src 作为 URL 或 DataURL,甚至检查是否完成也是一种轮询方法,函数在同一执行上下文中第一次调用返回 true 的几率非常低。【参考方案2】:

您可以将所有代码放在您想要在图像成功加载后处理的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;
&lt;canvas id="canvas" class="ol-unselectable" width="816" height="400" style="width: 100%; height: 100%;"&gt;&lt;/canvas&gt;

【讨论】:

我使用 UI 测试,我无法将我的代码放入 onload 事件中,我需要等到图像加载完毕 @Valentina 您可以使用不同的 CustomEvent 处理程序。每次成功加载图像时都会触发

以上是关于如何等待在画布中加载图像的主要内容,如果未能解决你的问题,请参考以下文章

QML:在 GridView 中加载图像

在 chrome 中加载大图像时出现“Aw Snap”错误

如何在haskell(光泽)中加载图像数组?

使用 fabric.js 在画布中加载 JSON

延迟后如何在 tableView 中加载图像?

如何实现 Asynctask 在 ArrayAdapter 中加载图像