Малювання декількох зображень на одному полотні

У мене є масив, який містить всю інформацію про те, як слід малювати image . Я хочу намалювати 2 зображення , і коли я це роблю, це лише малювання останнього зображення. Що я можу зробити?

for(i = 0; i < tiles.length; i++)
{
    var sourceX = tiles[i][5];
    var sourceY = tiles[i][6];
    var sourceWidth = tiles[i][9];
    var sourceHeight = tiles[i][10];
    var destWidth = sourceWidth;
    var destHeight = sourceHeight;
    var destX = tiles[i][7];
    var destY = tiles[i][8];

    var imageObj = new Image();
    imageObj.onload = function()
    {
        context.drawImage(imageObj, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight);
    };
    imageObj.src = tiles[i][4];
}
6

6 Відповіді

Я не міг пояснити більш конкретні причини, але ось рішення, яке я зрозумів. Це працює для мене.

<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false"> <div class="snippet-code">

const getContext =() => document.getElementById('my-canvas').getContext('2d');

// It's better to use async image loading.
const loadImage = url => {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload =() => resolve(img);
    img.onerror =() => reject(new Error(`load ${url} fail`));
    img.src = url;
  });
};

// Here, I created a function to draw image.
const depict = options => {
  const ctx = getContext();
 //And this is the key to this solution
 //Always remember to make a copy of original object, then it just works :)
  const myOptions = Object.assign({}, options);
  return loadImage(myOptions.uri).then(img => {
    ctx.drawImage(img, myOptions.x, myOptions.y, myOptions.sw, myOptions.sh);
  });
};

const imgs = [
  { uri: 'http://placehold.it/50x50/f00/000?text=R', x: 15, y:  15, sw: 50, sh: 50 },
  { uri: 'http://placehold.it/50x50/ff0/000?text=Y', x: 15, y:  80, sw: 50, sh: 50 },
  { uri: 'http://placehold.it/50x50/0f0/000?text=G', x: 15, y: 145, sw: 50, sh: 50 }
];

imgs.forEach(depict);
#my-canvas { background: #7F7F7F; }
</div> </div>

7
додано

Я не позитивний, але imageObj може бути не imageObj, який ви очікуєте в функції imageObj.onload. Замість того щоб робити

 context.drawImage(imageObj, sourceX, sourceY,

Подивіться, що відбувається, коли ви це зробите

 context.drawImage(this, sourceX, sourceY,
4
додано
це, ймовірно, хороша частина відповіді, і, ймовірно, буде рішенням. оголошення місцевих змінних у форматі for-loop - це інше питання, яке я бачу тут.
додано Автор Brett Caswell, джерело
тобто значення, що використовуються методом context.drawImage , все ще знаходяться поза сферою дії .. тобто sourceX sourceY ... бути tiles [tiles.length -1] еквівалентом на кожному imageObj (або цьому ) екземплярі, чи не так?
додано Автор Brett Caswell, джерело

у мене були подібні проблеми, Мені подобається рішення від

https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations

просто викликати window.requestAnimationFrame (нічия); з вашої функції малювання вона запуститиме цикл infinit і намалювати зображення, як тільки вони будуть готові

1
додано

Якщо ви завантажуєте декілька зображень, рекомендується попередньо завантажити всі зображення. Див. Тут для отримання додаткової інформації:

завантажувач/

1
додано

here's a solution, and a recommended alternative; both use .bind(<this>[,][,])

bind wraps the intended function, and performs a call on it using additional specified parameters (args). The first parameter of bind will be the this instance of the function. Setting it to undefined will pass the original this instance.

анонімна функція.

  var settings;

  for(i = 0; i < tiles.length; i++)
  {
      settings = {};
      settings.sourceX = tiles[i][5];
      settings.sourceY = tiles[i][6];
      settings.sourceWidth = tiles[i][9];
      settings.sourceHeight = tiles[i][10];
      settings.destWidth = sourceWidth;
      settings.destHeight = sourceHeight;
      settings.destX = tiles[i][7];
      settings.destY = tiles[i][8];

      settings.imageObj = new Image();
      settings.imageObj.onload = function(args)
      {
         context.drawImage(args.image, args.sourceX, args.sourceY, args.sourceWidth, args.sourceHeight, args.destX, args.destY, args.destWidth, args.destHeight);
      }.bind(undefined, settings);
      settings.imageObj.src = tiles[i][4];
  }

Хотілося б не використовувати анонімні функції для обробки загальних подій; замість цього я оголошу об'єкт для зберігання обробників.

Таким чином ви можете замінити обробник під час виконання. Подібним чином.

оголосити об'єкт для зберігання функцій обробки подій

  var Handlers = { 
      "drawImageHandler" : function drawImageHandler(args)
      {
          context.drawImage(args.image, args.sourceX, args.sourceY, args.sourceWidth, args.sourceHeight, args.destX, args.destY, args.destWidth, args.destHeight);
      }
  };

  function DebugInit() 
  {
      var func = Handlers.drawImageHandler;
      Handlers.drawImageHandler = function(func, args) {
         console.log("%o", args);
         func(args);
      }.bind(undefined, func);
  }


  var settings = {};
  DebugInit();//when called, encapsulates Handlers.drawImageHandler;

  for(i = 0; i < tiles.length; i++)
  {
      settings = {};
      settings.sourceX = tiles[i][5];
      settings.sourceY = tiles[i][6];
      settings.sourceWidth = tiles[i][9];
      settings.sourceHeight = tiles[i][10];
      settings.destWidth = sourceWidth;
      settings.destHeight = sourceHeight;
      settings.destX = tiles[i][7];
      settings.destY = tiles[i][8];
      settings.imageObj = new Image();
      settings.imageObj.onload = Handlers.drawImageHandler.bind(undefined, settings);      
      settings.imageObj.src = tiles[i][4];
  }

jsFiddle: Example Fiddle

0
додано
img[0]=new Image();
img[0].src="imgimg/img"+i+".png";
img[0].onload=function(){
  cntxt.drawImage(this,400,i*100,100,100);
  i++;
  img[i]=new Image(); 
  img[i].src="invimg/img"+i+".png";
  img[i].onload=this.onload;
};

частина моєї JS гри, я сподіваюся, що це допоможе ура!

0
додано
ІТ КПІ - JavaScript
ІТ КПІ - JavaScript
504 учасників

співтовариство javascript розробників в Telegram