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

发布于 2024-12-19 23:42:00 字数 638 浏览 0 评论 0原文

我有一个数组,其中包含有关如何绘制图像的所有信息。我想绘制 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];
}

I have an array that contains all the information about how the image should be drawn. I want to draw 2 images and when I do it, it's only drawing the last image. 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];
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

花心好男孩 2024-12-26 23:42:01
let img = new Image();
  img.crossOrigin = 'Anonymous';
  const createCanvas = async (imageSrc) => {
      img.src = imageSrc;
      await img.decode();
      context.drawImage(img, x, y, sw, sh)    
  }
let img = new Image();
  img.crossOrigin = 'Anonymous';
  const createCanvas = async (imageSrc) => {
      img.src = imageSrc;
      await img.decode();
      context.drawImage(img, x, y, sw, sh)    
  }
难以启齿的温柔 2024-12-26 23:42:00

我无法解释更具体的原因,但这是我找到的解决方案。这对我有用。

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

心如荒岛 2024-12-26 23:42:00

我并不肯定,但 imageObj 可能不是您在 imageObj.onload 函数中期望的 imageObj 。而不是做

 context.drawImage(imageObj, sourceX, sourceY,

看看当你这样做时会发生什么

 context.drawImage(this, sourceX, sourceY,

I'm not positive, but that imageObj may not be the imageObj you'd expect in the imageObj.onload function. Instead of doing

 context.drawImage(imageObj, sourceX, sourceY,

See what happens when you do

 context.drawImage(this, sourceX, sourceY,
月隐月明月朦胧 2024-12-26 23:42:00

如果您要加载多个图像,建议您首先预加载所有图像。请参阅此处了解更多信息:

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

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/

伤感在游骋 2024-12-26 23:42:00

我有类似的问题,
我喜欢 https://developer.mozilla 的解决方案

。 org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations

只需调用 window.requestAnimationFrame(draw);从您的绘图函数中,它将运行无限循环并在图像准备好后立即绘制图像

i had similar problems,
i like the solution from

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

just call window.requestAnimationFrame(draw); from your draw function, it will run an infinit loop and draw your images as soon as they are ready

旧时光的容颜 2024-12-26 23:42:00

这是一个解决方案,以及推荐的替代方案;两者都使用 .bind([,][,])

bind 包装预期的函数,并执行使用附加指定参数 (args) 对其进行调用。 bind 的第一个参数将是函数的 this 实例。将其设置为 undefined 将传递原始 this 实例。

匿名函数。

  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示例Fiddle< /a>

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

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.

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

油饼 2024-12-26 23:42:00
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游戏的一部分,希望对你有帮助干杯!

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!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文