Javascript 画布图像遮罩/重叠

Javascript 画布图像遮罩/重叠,javascript,canvas,html5-canvas,composition,Javascript,Canvas,Html5 Canvas,Composition,在我的项目中,我必须使用画布在另一个相同大小和图案的图像上实现一个不同的颜色图像,并且图像不是圆形或矩形。所有图像均为波浪形,并将应用于单个主背景图像,以便在每个onclick功能上显示多个图形 重叠图像应更改为另一种选定颜色。我的问题是,使用canvas有什么方法,我们可以更改canvas绘制的图像颜色,或者我们需要始终使用不同的图像并应用CSS/jQuery 我读过关于画布图像掩蔽和重叠的文章。但我无法理解我的图像,因为它们不是正方形或圆形的,那么首先我要做的是如何在一张图像上绘制多个波形。

在我的项目中,我必须使用画布在另一个相同大小和图案的图像上实现一个不同的颜色图像,并且图像不是圆形或矩形。所有图像均为波浪形,并将应用于单个主背景图像,以便在每个
onclick
功能上显示多个图形

重叠图像应更改为另一种选定颜色。我的问题是,使用canvas有什么方法,我们可以更改canvas绘制的图像颜色,或者我们需要始终使用不同的图像并应用CSS/jQuery

我读过关于画布图像掩蔽和重叠的文章。但我无法理解我的图像,因为它们不是正方形或圆形的,那么首先我要做的是如何在一张图像上绘制多个波形。我不知道我搜索了什么,但没有找到完美的解决方案


我需要的只是在画布上绘制一个波浪图像,并从单击功能更改其颜色,同时设置另一个div和背景图像,并且两个以上的画布将重叠。这可能吗


(这意味着:此功能用于在汽车上创建或设置多个图形,每个图形图像需要在画布中设置,另一个图形需要在div和第一个画布上重叠)

目前的问题在我看来有点不清楚。要给出一个更一般的答案,即你可以应用于需要剪辑的场景,你可以使用(至少)两种方法:

方法1-使用复合模式剪裁 合成模式是最简单的方式,但也是最不灵活的方式,因为您需要将剪切遮罩预定义为具有透明背景(通常为PNG)的图像

可以使用图像的实体部分剪裁下一个绘制的对象,也可以使用透明区域进行填充

下面是一种使用实体零件剪裁下一个绘制的形状/图像的方法:

/// draw the shape we want to use for clipping
ctx1.drawImage(imgClip, 0, 0);

/// change composite mode to use that shape
ctx1.globalCompositeOperation = 'source-in';

/// draw the image to be clipped
ctx1.drawImage(img, 0, 0);
此处,
globalCompositeOperation
更改为
source in
,这意味着源图像(我们将在目标旁边绘制的图像)将在现有实体数据中绘制。不会将任何内容绘制到透明区域

如果我们的剪辑蒙版看起来像这样(来自网络的随机合理使用):

我们的形象是这样的:

结果将是:

方法2-使用路径进行剪裁 还可以定义剪裁的路径。这是非常灵活的,因为如果需要,可以调整路径或设置其动画

注释:请记住,使用路径的剪辑目前在浏览器中有点“易碎”,因此在浏览器设置和使用剪辑路径之前和之后,您应该考虑使用<代码> SAVE()/<代码>和<代码>恢复/(<代码>),因为浏览器暂时无法重新设置剪辑(<代码>恢复< /代码>将恢复默认剪辑=完整画布); 让我们定义一个简单的之字形路径(在您的情况下,这将是您的波浪):

现在,我们已经使用
clip
设置了剪裁遮罩,接下来绘制到画布上的任何内容都将被剪裁以适合该形状(请注意,我们确保该形状可以在开始处结束):


您可以使用上下文合成来替换图像的一部分。

例如,如果此蓝色徽标已作为图像显示:

如果您希望徽标顶部颜色为紫色:

您可以使用合成重新着色图像的顶部。

首先,使用您喜爱的图像编辑器裁剪掉您不想重新着色的任何部分

剩下的部分称为覆盖层

图像的这个覆盖部分是我们将通过编程重新调用的

此叠加可以编程重新着色为任何颜色

如何通过编程重新存储覆盖:

  • 在空画布上绘制覆盖图
  • 将合成模式设置为“源输入”
  • 效果:仅替换现有像素透明像素保持透明
  • 现在画一个覆盖画布的任意颜色的矩形
  • (请记住,只有现有覆盖将替换为新颜色)
  • 如何使用更改的覆盖颜色完成徽标

  • 将合成模式设置为“目的地顶部”
  • 效果:仅替换透明像素现有像素保持不变
  • 现在绘制原始徽标
  • (请记住,现有的彩色覆盖层不会被替换)
  • 这种“目的地顶部”合成效果有时称为“下绘制”

    这个叠加甚至可以用纹理替换

    下面是代码和小提琴:

    
    正文{背景色:象牙色;填充:20px;}
    #画布{边框:1px纯红;}
    $(函数(){
    var canvas=document.getElementById(“canvas”);
    var ctx=canvas.getContext(“2d”);
    var卡车,标志,覆盖;
    var newColor=“红色”;
    var-imageurl=[];
    var-imagesOK=0;
    var-imgs=[];
    imageURLs.push(“https://dl.dropboxusercontent.com/u/139992952/stackoverflow/boxTruck.png");
    imageURLs.push(“https://dl.dropboxusercontent.com/u/139992952/stackoverflow/TVlogoSmall.png");
    imageURLs.push(“https://dl.dropboxusercontent.com/u/139992952/stackoverflow/TVlogoSmallOverlay.png");
    加载图像();
    函数loadAllImages(){
    对于(var i=0;i/// use save when using clip Path
    ctx2.save();
    
    ctx2.beginPath();
    ctx2.moveTo(0, 20);
    ctx2.lineTo(50,0);
    /// ... more here - see demo
    ctx2.lineTo(400, 20);
    ctx2.lineTo(400, 100);
    ctx2.lineTo(0, 100);
    ctx2.closePath();
    
    /// define this Path as clipping mask
    ctx2.clip();
    
    /// draw the image
    ctx2.drawImage(img, 0, 0);
    
    /// reset clip to default
    ctx2.restore();
    
    <!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; padding:20px; }
        #canvas{border:1px solid red;}
    </style>
    
    <script>
    $(function(){
    
        var canvas=document.getElementById("canvas");
        var ctx=canvas.getContext("2d");
    
        var truck,logo,overlay;
        var newColor="red";
    
        var imageURLs=[];
        var imagesOK=0;
        var imgs=[];
        imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/boxTruck.png");
        imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/TVlogoSmall.png");
        imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/TVlogoSmallOverlay.png");
        loadAllImages();
    
        function loadAllImages(){
            for (var i = 0; i < imageURLs.length; i++) {
              var img = new Image();
              imgs.push(img);
              img.onload = function(){ imagesOK++; imagesAllLoaded(); };
              img.src = imageURLs[i];
            }      
        }
    
        var imagesAllLoaded = function() {
          if (imagesOK==imageURLs.length ) {
             // all images are fully loaded an ready to use
             truck=imgs[0];
             logo=imgs[1];
             overlay=imgs[2];
             start();
          }
        };
    
    
        function start(){
    
            // save the context state
            ctx.save();
    
            // draw the overlay
            ctx.drawImage(overlay,150,35);
    
            // change composite mode to source-in
            // any new drawing will only overwrite existing pixels
            ctx.globalCompositeOperation="source-in";
    
            // draw a purple rectangle the size of the canvas
            // Only the overlay will become purple
            ctx.fillStyle=newColor;
            ctx.fillRect(0,0,canvas.width,canvas.height);
    
            // change the composite mode to destination-atop
            // any new drawing will not overwrite any existing pixels
            ctx.globalCompositeOperation="destination-atop";
    
            // draw the full logo
            // This will NOT overwrite any existing purple overlay pixels
            ctx.drawImage(logo,150,35);
    
            // draw the truck
            // This will NOT replace any existing pixels
            // The purple overlay will not be overwritten
            // The blue logo will not be overwritten
            ctx.drawImage(truck,0,0);
    
            // restore the context to it's original state
            ctx.restore();
    
        }
    
    
    }); // end $(function(){});
    </script>
    
    </head>
    
    <body>
        <canvas id="canvas" width=500 height=253></canvas>
    </body>
    </html>