简体   繁体   English

在一个画布上绘制多个图像

[英]Drawing multiple images on one canvas

I have an array that contains all the information about how the image should be drawn. 我有一个数组,其中包含有关如何绘制image所有信息。 I want to draw 2 images and when I do it, it's only drawing the last image. 我想绘制2 images ,当我这样做时,它只绘制最后一张图像。 What can I do? 我能做什么?

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];
}

I couldn't explain more specific reasons, but here is the solution I figured out. 我无法解释更具体的原因,但这是我想出的解决方案。 It works for me. 这个对我有用。

 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; } 
 <canvas id="my-canvas" width="80" height="210"></canvas> 

I'm not positive, but that imageObj may not be the imageObj you'd expect in the imageObj.onload function. 我不是肯定的,但是imageObj可能不是你在imageObj.onload函数中所期望的imageObj。 Instead of doing 而不是做

 context.drawImage(imageObj, sourceX, sourceY,

See what happens when you do 看看你做了什么

 context.drawImage(this, sourceX, sourceY,

i had similar problems, i like the solution from 我有类似的问题,我喜欢解决方案

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

just call window.requestAnimationFrame(draw); 只需调用window.requestAnimationFrame(draw); from your draw function, it will run an infinit loop and draw your images as soon as they are ready 从你的绘图功能,它将运行一个无限循环,并在它们准备好后立即绘制你的图像

If you're loading multiple images, it's recommended that you pre-load all of the images first. 如果您要加载多个图像,建议您先预先加载所有图像。 See here for more information: 浏览此处获取更多信息:

http://www.html5canvastutorials.com/tutorials/html5-canvas-image-loader/ http://www.html5canvastutorials.com/tutorials/html5-canvas-image-loader/

here's a solution, and a recommended alternative; 这是一个解决方案,也是推荐的替代方案; both use <function>.bind(<this>[,<arg1>][,<arg2>]) 都使用<function>.bind(<this>[,<arg1>][,<arg2>])

bind wraps the intended function, and performs a call on it using additional specified parameters (args). bind包装预期的函数,并使用其他指定的参数(args)对其执行调用。 The first parameter of bind will be the this instance of the function. bind的第一个参数是函数的this实例。 Setting it to undefined will pass the original this instance. 将其设置为undefined将传递原始this实例。

anonymous function. 匿名功能。

  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];
  }

I prefer not to use anonymous functions for common event handling though; 喜欢使用 匿名函数来处理常见事件; instead, I would declare an object to store handlers. 相反,我会声明一个对象来存储处理程序。

That way you can replace the handler at runtime. 这样您就可以在运行时替换处理程序。 In a manner like the following. 以下面的方式。

declare object to store event handling functions 声明对象以存储事件处理函数

  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 jsFiddle示例小提琴

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;
};

piece of my js game, i hope it helps cheers! 我的js游戏,我希望它有助于欢呼!

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

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