【问题标题】:Drawing multiple images on one canvas在一张画布上绘制多个图像
【发布时间】:2012-01-14 08:26:27
【问题描述】:

我有一个数组,其中包含有关如何绘制image 的所有信息。我想画 2 images,当我这样做时,它只画最后一张图像。我能做什么?

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

【问题讨论】:

    标签: javascript image html


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

       context.drawImage(imageObj, sourceX, sourceY,
      

      看看你这样做会发生什么

       context.drawImage(this, sourceX, sourceY,
      

      【讨论】:

      • 这可能是答案的一个很好的部分,并且可能是一个解决方案。在 for 循环中声明局部变量是我在这里看到的另一个问题..
      • 也就是说,与context.drawImage 方法一起使用的值仍然超出范围.. 即sourceX sourceY... 都可能是tiles[tiles.length -1]在每个imageObj(或this)实例上都等效,对吧?
      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        我有类似的问题, 我喜欢来自

        的解决方案

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

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

        【讨论】:

          【解决方案5】:

          这里有一个解决方案和推荐的替代方案;两者都使用&lt;function&gt;.bind(&lt;this&gt;[,&lt;arg1&gt;][,&lt;arg2&gt;])

          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:Example Fiddle

          【讨论】:

            【解决方案6】:
            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游戏片段,希望对大家有帮助!

            【讨论】:

            • 这将创建一个无限循环。
            猜你喜欢
            • 1970-01-01
            • 2016-07-08
            • 1970-01-01
            • 2022-08-03
            • 1970-01-01
            • 1970-01-01
            • 2013-11-06
            • 1970-01-01
            • 2019-10-19
            相关资源
            最近更新 更多