用纹理/图案填充图像

Kci*_*red 4 javascript drawing canvas mask html5-canvas

我正在寻找一种改变产品纹理/图案的解决方案.

这时我有:

  1. 一张长沙发的.png图片有透明背景 在此输入图像描述
  2. 纹理的.png图片在此输入图像描述

使用以下代码:

<canvas id="a" width="800" height="500">Canvas not supported on your browser</canvas>
Run Code Online (Sandbox Code Playgroud)

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);
}
Run Code Online (Sandbox Code Playgroud)

`

我得到这个结果: 在此输入图像描述

如您所见,整个对象充满了我的纹理.枕头等的定义不再可见.是否可以让我的纹理成为一种透明的面具?

我已经能够改变沙发的颜色: 在此输入图像描述

但我希望能够在我的沙发上添加一个图案!

任何帮助将不胜感激,我已经非常抱歉我的英语不好.

小智 8

如果您只是在说明性近似之后,您可以使用混合和合成模式的组合.

首先要确保您的主图像具有透明度 - 这对于合成工作很重要(我在下面的演示中做了一个粗略的截止).

演示结果

主要步骤:

  1. 绘制图案
  2. 使用混合模式在顶部绘制主图像 multiply
  3. 使用合成模式在顶部绘制主图像destination-in- 这将进行剪切

如果要减小图案的大小,可以使用较小版本的图像,绘制较小尺寸的临时画布并将其用作图案,或者在图案本身上使用新的变换方法.

演示

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.com/8WqH9v4.png";       // sofa
img2.src = "//i.stack.imgur.com/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 composition mode
  ctx.globalCompositeOperation = "destination-in";
  
  // draw to cut-out sofa
  ctx.drawImage(img1, 0, 0, img1.width*.5, img1.height*.5);
}
Run Code Online (Sandbox Code Playgroud)
<canvas id="canvas" width=600 height=400></canvas>
Run Code Online (Sandbox Code Playgroud)

如果您愿意,还可以反转绘制图像的顺序等.这只是一种方式的例子.

如果您需要精确的纹理,那么无法拍摄照片或使用3D软件,或手绘纹理.

注意:IE不支持multiply - 为此,您需要手动迭代像素并将每个组件相互相乘.

您可以通过以下方式测试支持:

ctx.globalCompositeOperation = "multiply";
if (ctx.globalCompositeOperation === "multiply") {
    // blend as above
}
else {
    // iterate and blend manually
}
Run Code Online (Sandbox Code Playgroud)

luminosity评论中提到了混合模式,当然也可以使用.我只想指出一些要考虑的事情.首先,这是一种不可分离的混合模式,这意味着它在通过HSL颜色模型时依赖于所有组件.这使得计算密集程度更高.

第二个问题是,如果您最终必须手动执行此操作(例如IE),则代码模拟起来会有点复杂,而且速度会明显变慢.