HTML5 画布;图像剪辑和多个图像

3
我对canvas还不太熟悉,遇到了一些问题。
我想要实现一个目标:在单个canvas中显示两张图片;其中一张是背景图,另一张是剪切为PNG格式的图像并出现在上方。
我已经完成了其中一部分,但是遇到了难题,不知道如何解决。
我已经在jsFiddle上创建了一个示例,网址为:http://jsfiddle.net/jhp79yg9/

      function loadImages(sources, callback) {
        var images = {};
        var loadedImages = 0;
        var numImages = 0;
        // get num of sources
        for(var src in sources) {
          numImages++;
        }
        for(var src in sources) {
          images[src] = new Image();
          images[src].onload = function() {
            if(++loadedImages >= numImages) {
              callback(images);
            }
          };
          images[src].src = sources[src];
        }
      }
      var canvas = document.getElementById('canvas');
      var context = canvas.getContext('2d');

      var sources = {
        img1: 'https://scontent-iad3-1.cdninstagram.com/hphotos-xaf1/t51.2885-15/11351598_1454928098145798_1274636321_n.jpg',
        img2: 'https://igcdn-photos-c-a.akamaihd.net/hphotos-ak-xaf1/t51.2885-15/11379733_1139595366067106_273993739_n.jpg',
        mask: 'http://img12.deviantart.net/65e4/i/2013/003/6/6/png_floating_terrain_by_moonglowlilly-d5qb58m.png'
      };

      loadImages(sources, function(images) {
        context.drawImage(images.img2, 0, 0, 240, 240);
        
        context.drawImage(images.mask, 20, 95, 500, 349);
        context.globalCompositeOperation = 'source-in';
        context.drawImage(images.img1, 0, 0, 540, 540);

      });
<canvas id="canvas" width="540" height="540"></canvas>

在这个例子中,我将第一张图片的大小从540x540减小到了140x140,只是为了方便观察是否出现问题,而事实上确实出现了问题。
问题在于它没有显示第二张图片,而是两次显示了“img1”变量,根本没有显示“img2”。
有人可以提供帮助吗?
此外,我也无法确定前景和背景中分别是哪张图片。如果能提供帮助,那就更好了(裁剪后的图片应该在前景)。
谢谢!

img2 被绘制出来了,但是当 mask 覆盖在上面时,两者被视为一个整体,然后使用 source-in 绘制 img1,根据 alpha 通道的值替换像素。img1 不会被绘制两次。至少对我来说是这样(Firefox 39)。 - Sebastian Simon
2个回答

4
另一种方法是从当前内容中剪切出掩码,然后在当前内容后面绘制背景:
loadImages(sources, function(images) {
    context.drawImage(images.img2, 0, 0, 540, 540);
    context.globalCompositeOperation = 'destination-out';
    context.drawImage(images.mask, 20, 95, 500, 349);
    context.globalCompositeOperation = 'destination-atop';
    context.drawImage(images.img1, 0, 0, 540, 540);
})

http://jsfiddle.net/jhp79yg9/6/


谢谢。这实际上效果更好了一些。还有一个快速的问题,我有一个在点击时交换图像的函数,对于背景中的图像效果很好,但是在裁剪的图像上,它看起来像是将新图像放在旧图像下面。有什么想法吗?编辑:抱歉,我写反了。前景没问题,背景没有改变。 - robbclarke

2

我不太清楚你的需求是什么,但是根据我的猜测,希望这个回答能给你提供所需要的信息。

context.drawImage(images.img2, 100, 180, 350, 350);
context.globalCompositeOperation = 'destination-atop';
context.drawImage(images.mask, 100, 180, 350, 350);
context.drawImage(images.img1, 0, 0, 540, 540);

http://jsfiddle.net/jhp79yg9/5/


我点了赞,尽管我理解问题是“Men's Health”图片应该是背景,“Foo Fighters”应该是前景中的剪裁部分。 - Sebastian Simon
1
@Xufox 虽然这不是很大的区别,但他只需要以不同的顺序绘制图像即可。 - Sebastian Nette
太棒了。谢谢!原来我离成功很近,但又远在天边。感谢你的帮助! - robbclarke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接