I tried to make this happen with canvas' globalCompositeOperation
, but had no luck so I'm asking here. There are similar questions here, but I did not find my case among them.
我尝试用canvas的globalCompositeOperation来实现这一点,但是运气不好,所以我在这里问。这里也有类似的问题,但我没有在其中找到我的情况。
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. 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) - 第二个图像屋顶是一个覆盖“掩蔽”的图像,它的屋顶区域是红色的(可以是任何东西,但红色表示清晰,见下图)
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
. (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)
(在sidenote中,我还希望能够打乱背景图案HSL-values,但我认为,一旦我将图案均匀地显示出来,这就变得非常简单了)
Expected result:
The expected result would be a house which roof is textured with the repeatPattern image.
预期的结果是一个屋顶用重复模式图像纹理的房子。
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
roofOverlay
1 个解决方案
#1
17
Here’s how to composite your “roof pattern” on top of your “house” using “roofOverlay”
下面是如何将你的“屋顶模式”在你的“房子”顶部使用“屋顶”
This is a multi-part process:
这是一个多部分的过程:
- Draw the house on canvas#1.
- 在画布#1上画房子。
- Draw the red roofOverlay on canvas#2.
- 在画布2上绘制红色的屋顶覆盖物。
- Set canvas#2’s context.globalCompositeOperation = 'source-in'
- 设置画布# 2的上下文。globalCompositeOperation = '来源——这个地方就是'
- Draw your desired pattern on canvas#2
- 在画布#2上画出你想要的图案。
- 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.
注意:我假设你想把房子和屋顶放在不同的画布上,这样你就可以随意选择不同的屋顶。如果你需要把所有东西都画在一张画布上,你可以把屋顶的画布画在房子的画布上。
<!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/*/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/*/lattice.jpg";
}
red.src="https://dl.dropbox.com/u/1122582/*/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>
#1
17
Here’s how to composite your “roof pattern” on top of your “house” using “roofOverlay”
下面是如何将你的“屋顶模式”在你的“房子”顶部使用“屋顶”
This is a multi-part process:
这是一个多部分的过程:
- Draw the house on canvas#1.
- 在画布#1上画房子。
- Draw the red roofOverlay on canvas#2.
- 在画布2上绘制红色的屋顶覆盖物。
- Set canvas#2’s context.globalCompositeOperation = 'source-in'
- 设置画布# 2的上下文。globalCompositeOperation = '来源——这个地方就是'
- Draw your desired pattern on canvas#2
- 在画布#2上画出你想要的图案。
- 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.
注意:我假设你想把房子和屋顶放在不同的画布上,这样你就可以随意选择不同的屋顶。如果你需要把所有东西都画在一张画布上,你可以把屋顶的画布画在房子的画布上。
<!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/*/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/*/lattice.jpg";
}
red.src="https://dl.dropbox.com/u/1122582/*/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>