admin管理员组文章数量:1291736
I'm looking for a solution to change the texture/pattern for a product.
At this moment i have:
- A .png picture of a couch with a transparent background
- A .png picture of a texture
With the following code:
<canvas id="a" width="800" height="500">Canvas not supported on your browser</canvas>
var width = $(window).width();
var height = $(window).height();
var c = document.getElementById("a");
var ctx = c.getContext("2d");
var can2 = document.createElement('canvas');
document.body.appendChild(can2)
can2.width = c.width;
can2.height = c.height;
var ctx2 = can2.getContext("2d");
var test = new Image();
test.src = "Images/newBank.png";
test.onload = function () {
ctx2.drawImage(test, 0, 0);
};
var img = new Image();
img.src = "Images/texturetrans.png";
img.onload = function () {
ctx2.globalCompositeOperation = 'source-in';
var ptrn = ctx2.createPattern(img, 'repeat');
ctx2.fillStyle = ptrn;
ctx2.fillRect(0, 0, can2.width, can2.height);
}
`
I get this result:
As you can see, the whole object is filled with my texture. No definitions of the pillows etc. are visible anymore. Is it possible to let my texture be a sort of transparent mask?
I'm already able to change the color of the couch:
But I'd like to be able to also add a pattern to my couch!
Any help will be appreciated and I'm already very sorry for my bad English.
I'm looking for a solution to change the texture/pattern for a product.
At this moment i have:
- A .png picture of a couch with a transparent background
- A .png picture of a texture
With the following code:
<canvas id="a" width="800" height="500">Canvas not supported on your browser</canvas>
var width = $(window).width();
var height = $(window).height();
var c = document.getElementById("a");
var ctx = c.getContext("2d");
var can2 = document.createElement('canvas');
document.body.appendChild(can2)
can2.width = c.width;
can2.height = c.height;
var ctx2 = can2.getContext("2d");
var test = new Image();
test.src = "Images/newBank.png";
test.onload = function () {
ctx2.drawImage(test, 0, 0);
};
var img = new Image();
img.src = "Images/texturetrans.png";
img.onload = function () {
ctx2.globalCompositeOperation = 'source-in';
var ptrn = ctx2.createPattern(img, 'repeat');
ctx2.fillStyle = ptrn;
ctx2.fillRect(0, 0, can2.width, can2.height);
}
`
I get this result:
As you can see, the whole object is filled with my texture. No definitions of the pillows etc. are visible anymore. Is it possible to let my texture be a sort of transparent mask?
I'm already able to change the color of the couch:
But I'd like to be able to also add a pattern to my couch!
Any help will be appreciated and I'm already very sorry for my bad English.
Share Improve this question asked Feb 16, 2015 at 16:15 ZheMannZheMann 911 silver badge6 bronze badges 4- 1) fill the canvas with your pattern. 2) use globalCompositeOperation='luminosity' and draw the couch. 3) use globalCompositeOperation='source-in' and draw the couch. Maybe play on globalAlpha to modulate. That's the closest you can get : you need a 3D model/3D renderer to do an accurate texturing. – GameAlchemist Commented Feb 16, 2015 at 16:56
- @GameAlchemist you can use luminosity, but have in mind that this is a non-separable mode and it has to go through HSL, so it's much more puter heavy (even if it uses some Adobe magic for the latter) than using multiply which is simply Cb x Cs. – user1693593 Commented Feb 17, 2015 at 23:56
- @KenFyrstenberg : Using luminosity shouldn't be an issue 1) it's a one-time pute 2) GPU won't mind the conversion, and 3) if you do it by hand it'll be very slow whatever the formula. But after testing your code with 'luminosity' and alpha near 0.5, the best reason to use multiply is ... it looks better ! – GameAlchemist Commented Feb 18, 2015 at 10:53
- @GameAlchemist it's not an issue, just more pute heavy (can bee an issue if there is a lot of its use as in a customizer as here, or client is on a slower puter). Something OP can have in mind it there is need for optimization. Yes agreed, manual multiply (IE) will be slow in either case. – user1693593 Commented Feb 18, 2015 at 19:58
1 Answer
Reset to default 10If you're just after an illustrative approximation you can use a bination of blending and position modes.
First thing is to make sure your main image has transparency - this is important for position to work (I made a rough cut-off in the following demo).
Main steps:
- Draw the pattern
- Draw the main image on top with blending mode
multiply
- Draw the main image on top with positing mode
destination-in
- this will make a cut-out
If you want to reduce the size of the pattern you can either do this by using a smaller version of the image, draw to a temporary canvas at a smaller size and use that as pattern, or use the new transform methods on the pattern itself.
Demo
var img1 = new Image, img2 = new Image, cnt = 2,
canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
// image loading for demo (ignore)
img1.onload = img2.onload = function() {if (!--cnt) go()};
img1.src = "//i.imgur./8WqH9v4.png"; // sofa
img2.src = "//i.sstatic/sQlu8.png"; // pattern
// MAIN CODE ---
function go() {
// create a pattern
ctx.fillStyle = ctx.createPattern(img2, "repeat");
// fill canvas with pattern
ctx.fillRect(0, 0, canvas.width, canvas.height);
// use blending mode multiply
ctx.globalCompositeOperation = "multiply";
// draw sofa on top
ctx.drawImage(img1, 0, 0, img1.width*.5, img1.height*.5);
// change position mode
ctx.globalCompositeOperation = "destination-in";
// draw to cut-out sofa
ctx.drawImage(img1, 0, 0, img1.width*.5, img1.height*.5);
}
<canvas id="canvas" width=600 height=400></canvas>
You can also reverse the order of which image is drawn etc., if you prefer. This is just an example of one way.
If you need accurate texture then there is no way around to either take photos or use a 3D software, or hand-drawn the textures.
NOTE: IE does not support multiply
- For this you need to manually iterate through the pixels and multiply each ponent with each other.
You can test for support this way:
ctx.globalCompositeOperation = "multiply";
if (ctx.globalCompositeOperation === "multiply") {
// blend as above
}
else {
// iterate and blend manually
}
Blending mode luminosity
is mentioned in ments and this can be used too of course. I just want to point a couple of things to consider. The first is that this is a non-separable blending mode meaning it depends on all ponents as it goes through the HSL color model. This makes it a bit more pute intensive.
The second is that if you end up having to do this manually (in for example IE) the code is a bit more plex to emulate, and will be noticeably slower.
本文标签: javascriptFill image with texturepatternStack Overflow
版权声明:本文标题:javascript - Fill image with texturepattern - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741540244a2384280.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论