简体   繁体   English

在HTML5画布中,如何使用我选择的背景屏蔽图像?

[英]In HTML5 canvas, how to mask an image with a background of my choice?

I tried to make this happen with canvas' globalCompositeOperation , but had no luck so I'm asking here. 我尝试用globalCompositeOperation来实现这一点,但没有运气所以我在这里问。 There are similar questions here, but I did not find my case among them. 这里有类似的问题,但我没有找到他的案例。

I have layers in my canvas area as so (drawing order from bottom to top): 我的画布区域中有图层(从下到上绘制顺序):

  • The canvas base is filled with pure white (#fff, with fillRect) 画布底座填充纯白色(#fff,带有fillRect)
  • First image house is a picture of a house. 第一个图像househouse的图片。 The background is transparent. 背景是透明的。 (see below) (见下文)
  • Second image roofOverlay is an overlay "masking" image that has the roof area coloured red (can be anything, but red for clarity, see below) 第二个图像roofOverlay是一个叠加的“遮蔽”图像,其屋顶区域为红色(可以是任何东西,但为了清晰起见,红色,见下文)

Both images take up the whole canvas and are lined up perfectly on top of each other, so that the red roof area matches the house. 两幅图像都占据了整个画布,并且完美地排列在彼此之上,因此红色屋顶区域与房屋相匹配。

I then have a repeating background repeatPattern pattern what I want to use ONLY inside the red areas: to fill the red area with repeatPattern . 然后,我有一个重复的背景repeatPattern模式我希望使用里面的红色区域:以填补红色区域repeatPattern (can be anything, but assume hexagons or whatever) (可以是任何东西,但假设六边形或其他)

In pseudocode, this would ideally be something in the lines of: 在伪代码中,理想情况下,这将是:

roofOverlay.maskBackground(repeatPattern)

(On a sidenote, I would also like to be able to mess with the background pattern HSL-values, but I think that's quite straightforward once I get the pattern to even display) (在旁注中,我也希望能够混淆背景模式HSL值,但我认为一旦我得到模式甚至显示,这是非常简单的)

Expected result: 预期结果:

The expected result would be a house which roof is textured with the repeatPattern image. 预期的结果将是屋顶用repeatPattern图像纹理化的房屋。

Note : I'm aware of clipping paths with masks, but I cannot use them here. 注意 :我知道带有掩码的剪切路径,但我不能在这里使用它们。 The example is simplified and drawing all the paths for multiple different houses would be way too much work. 这个例子是简化的,绘制多个不同房屋的所有路径将是太多的工作。 I only have the overlayed png-files for the roof. 我只有屋顶覆盖的png文件。

Images for reference 图片供参考

屋 house


屋顶覆盖 roofOverlay

Here's how to composite your “roof pattern” on top of your “house” using “roofOverlay” 以下是如何使用“roofOverlay”在“房子”顶部合成“屋顶图案”

在此输入图像描述

This is a multi-part process: 这是一个多部分的过程:

  1. Draw the house on canvas#1. 在画布#1上画出房子。
  2. Draw the red roofOverlay on canvas#2. 在画布#2上绘制红色屋顶覆盖。
  3. Set canvas#2's context.globalCompositeOperation = 'source-in' 设置画布#2的context.globalCompositeOperation ='source-in'
  4. Draw your desired pattern on canvas#2 在画布#2上画出你想要的图案
  5. Compositing will cause your desired pattern to replace the red overlay—only in the red overlay area. 合成将使您所需的图案仅替换红色覆盖区域中的红色覆盖。

Here is a Fiddle that loads grass on your roof: http://jsfiddle.net/m1erickson/SWP6v/ 这是一个在屋顶上装草的小提琴: http//jsfiddle.net/m1erickson/SWP6v/

And here is code that uses a lattice pattern fill on your roof: 这里是使用屋顶上的网格图案填充的代码:

Note: I'm assuming that you want the house and roof on separate canvases so you can flip through a variety of roof choices. 注意:我假设您希望房屋和屋顶在不同的画布上,以便您可以翻阅各种屋顶选择。 If you need everything on 1 canvas, you can just draw the roof canvas onto the house canvas. 如果你需要1个画布上的所有东西,你可以将屋顶画布画到房子画布上。

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
    #container{position:relative;}
    #house{position:absolute; top:0; left:0;}
    #canvas{position:absolute; top:0; left:0;}
</style>

<script>
$(function(){

    var house=document.getElementById("house");
    var ctxHouse=house.getContext("2d");
    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    var red=new Image();
    red.onload=function(){
       canvas.width=red.width;
       canvas.height=red.height;

       var houseImage=new Image();
       houseImage.onload=function(){
           house.width=houseImage.width;
           house.height=houseImage.height;
           ctxHouse.drawImage(houseImage,0,0);
       }
       houseImage.src="https://dl.dropbox.com/u/1122582/stackoverflow/house.png";

       ctx.drawImage(red,0,0);

        var imageObj = new Image();
        imageObj.onload = function() {
          var pattern = ctx.createPattern(imageObj, 'repeat');
          ctx.globalCompositeOperation = 'source-in';
          ctx.rect(0, 0, canvas.width, canvas.height);
          ctx.fillStyle = pattern;
          ctx.fill();
        };
        imageObj.src = "http://dl.dropbox.com/u/139992952/stackoverflow/lattice.jpg";
    }
    red.src="https://dl.dropbox.com/u/1122582/stackoverflow/roof-overlay.png";

}); // end $(function(){});
</script>

</head>

<body>
<div id="container">
        <canvas id="house" width=300 height=300></canvas>
        <canvas id="canvas" width=300 height=300></canvas>
</div>
</body>
</html>

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

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