用纹理/图案填充图像

时间:2015-02-16 16:15:30

标签: javascript canvas html5-canvas drawing mask

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

此刻我有:

  1. 背景为enter image description here
  2. 的沙发的.png图片
  3. 纹理{.0}}
  4. 的.png图片

    使用以下代码:

    <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);
    }
    

    `

    我得到了这个结果:enter image description here

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

    我已经能够改变沙发的颜色: enter image description here

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

    任何帮助都将受到赞赏,我已经非常抱歉我的英语不好。

1 个答案:

答案 0 :(得分:8)

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

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

Demo result

主要步骤:

  1. 绘制图案
  2. 使用混合模式multiply
  3. 在顶部绘制主图像
  4. 使用合成模式destination-in在顶部绘制主图像 - 这将进行剪切
  5. 如果要减小图案的大小,可以使用较小版本的图像,绘制较小尺寸的临时画布并将其用作图案,或者使用新的转换方法。模式本身。

    <强>演示

    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);
    }
    <canvas id="canvas" width=600 height=400></canvas>

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

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

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

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

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

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

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