Как мне убедиться, что изображения загружаются в правильном порядке на холсте? - PullRequest
0 голосов
/ 10 ноября 2018

У меня есть следующий файл JavaScript с функцией menu, которая вызывает функцию draw 4 раза для отображения 4 разных изображений на экране.

Мне нужно отобразить их в том порядке, в котором они закодированы, но каждый раз, когда я обновляюсь, я получаю что-то другое. Я понимаю, что это наиболее вероятно, потому что некоторые изображения загружаются быстрее, чем другие.

Я посмотрел некоторые другие примеры этого на сайте, и решение, по-видимому, заключается в рисовании изображений только тогда, когда все они загружены первыми, однако я не могу заставить это работать.

Есть ли другой способ?

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();

Обновление

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();

Ответы [ 2 ]

0 голосов
/ 10 ноября 2018

Рисование изображения на холсте - это синхронная операция, а загрузка этих изображений невозможна.

Итак, разделите вашу логику на 1.Loading, затем 2.Drawing

.при загрузке части будет просто создано столько <img> элементов, сколько вам нужно нарисовать, операция значительно очищена благодаря Promises.

Как только это будет сделано, часть рисования просто перебирает изображения и рисует их:

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>

Обратите внимание, что это основные операции, когда требуются внешние активы:

  • Загрузка всех необходимых активов.
  • Тогда начните использовать их.
0 голосов
/ 10 ноября 2018

Вы можете сделать свою функцию рисования асинхронной. Вызов 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));
    }());

Что будет гарантировать порядок рисования.

вывод: 1 2 3 4

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...