简体   繁体   English

如何确保图像以正确的顺序加载到画布上?

[英]How do I make sure that images load in the right order on the canvas?

I have the following JavaScript file with a function called menu that calls the draw function 4 different times to display 4 different images on the screen. 我有以下JavaScript文件,其中包含一个称为menu的函数,该menu调用draw函数4次不同的时间以在屏幕上显示4个不同的图像。

I need to display them in the order they are coded in, but every time I refresh I get something different. 我需要按编码顺序显示它们,但是每次刷新时,都会得到一些不同的信息。 I understand that this is most likely because some of the images load faster than others. 我知道这很可能是因为某些图像加载得比其他图像快。

I have looked up some other examples of this on the site and the solution seems to be drawing the images only when all of them are loaded first, however I can't get that to work. 我在站点上查找了其他示例,解决方案似乎仅在首先加载所有图像时才绘制图像,但是我无法使其正常工作。

Is there another way? 还有另一种方法吗?

var cvs = document.getElementById("canvas");
var ctx = cvs.getContext("2d");
var audio = new Audio('sounds/sound.ogg');
cvs.addEventListener("click", function(){
        audio.play();
});
var logoSound;

ctx.fillStyle= "#87ceeb";
ctx.fillRect(0,0,1330,800);

function draw(src, a, b) {
  var ctx = document.getElementById('canvas').getContext('2d');
  var img = new Image();
  img.onload = function() {
    ctx.drawImage(img, x, y);
  };
  img.src = src;
}

function menu() {
    draw("images/clouds.png", 0, 300);
    draw("images/background.png", 0, 360);
    draw("images/display.png", 410, 0);
    draw("images/plank.png", 405, 300);
}

menu();

Update 更新资料

async function draw(src,x,y) {
    var ctx = document.getElementById('canvas').getContext('2d');
  var img = new Image();
  img.onload = function(){
    ctx.drawImage(img,x,y);
  };
img.src = src;
}

// main
(async function menu (){
    await draw("images/clouds.png", 0, 300);
    await draw("images/background.png", 0, 360);
    await draw("images/display.png", 410, 0);
    await draw("images/plank.png", 405, 300);
    await draw("images/info.png", 1195, 660);
}());

function cloud2(){
    ctx.drawImage(cloud, speed, 0);

    cvs.requestAnimationFrame(cloud);
}

menu();

You could make your draw function asynchronous. 您可以使绘图函数异步。 The setTimeout call is a simulation of your asynchronous on load handler. setTimeout调用是对异步加载处理程序的模拟。

    async function draw (msg) {
        return new Promise ((resolve, reject) => {
            let randomDelay = Math.floor(Math.random() * 3000);
            setTimeout(() => {
                resolve(msg);
            }, randomDelay);
        });
    }

    (async function (){
        console.log(await draw(1));
        console.log(await draw(2));
        console.log(await draw(3));
        console.log(await draw(4));
    }());

Which would guarantee the drawing order. 这将保证图纸顺序。

output is: 1 2 3 4 输出为:1 2 3 4

Drawing an image on a canvas is a synchronous operation, what is not, is to load these images. 在画布上绘制图像是一个同步操作,不是加载这些图像。

So split your logic in 1.Loading, then 2.Drawing 因此,将逻辑分为1.Loading,然后2.Drawing

The loading part will just create as many <img> elements as you need to be drawn, operation greatly cleaned up thanks to Promises. 加载部分将根据需要绘制尽可能多的<img>元素,而Promises可以大大清理操作。

Once that's done, the drawing part will just iterate over the images and draw them: 一旦完成,绘图部分将遍历图像并绘制它们:

 const ctx = canvas.getContext('2d'); function loadImages(urls) { return Promise.all(urls.map(loadImage)); } function loadImage(url) { return new Promise((res, rej) => Object.assign((new Image()), { src: url, onload: function(e){res(this)}, onerror: rej })); } function drawImages(images) { images.forEach((img, i) => ctx.drawImage(img, i * 50, 0)); } async function begin()  { // build up our array of urls const urls = Array.from({ length: 10 }, () => 'https://lorempixel.com/50/50?' + Math.random()); // load them all const images = await loadImages(urls); // draw them all drawImages(images); } begin().catch(console.error) 
 <canvas id="canvas" width="500" height="50"></canvas> 

Note that it is the basic operations when external assets are required: 请注意,这是需要外部资产时的基本操作:

  • Load all required assets. 加载所有必需的资产。
  • Then start using them. 然后开始使用它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM