当前位置: 首页 > 知识库问答 >
问题:

画布图像遮罩/重叠

谭繁
2023-03-14

在我的项目中,我必须使用画布在另一个相同大小和图案的图像上实现一个不同的颜色图像,并且图像不是圆形或矩形形状。所有这些都是波浪形状,它将应用于单个主背景图像,用于在每个onClick函数上显示多个图形。

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

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

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

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

共有2个答案

索令
2023-03-14

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

例如,如果您已经将此蓝色徽标用作图像:

任何您希望徽标的顶部为紫色的:

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

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

剩下的被称为覆盖层。

图像的这个覆盖部分是我们将通过编程重新绘制的。

此覆盖可以通过编程重新着色为任何颜色。

如何通过编程重新绘制覆盖图:

  1. 在空画布上绘制覆盖图

如何使用更改的叠加颜色完成徽标

  1. 将合成模式设置为“目标-顶部”
  2. 效果:仅替换透明像素-现有像素保持不变
  3. 现在画出原始标志
  4. (记住,现有的彩色叠加不会被替换)

这种“目的地顶部”的合成效果有时被称为“下方绘制”。

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

这是代码和小提琴:http://jsfiddle.net/m1erickson/bfUPr/

<!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>
黄俊誉
2023-03-14

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

复合模式是最简单的方法,但也是最不灵活的,因为您需要将剪辑蒙版预先定义为具有透明背景(通常是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);

在这里,globalCompositeAction更改为source-in,这意味着源图像(我们要在目标旁边绘制的图像)将在现有的实体数据中绘制。不会将任何东西绘制到透明区域。

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

我们的形象是这样的:

结果将是:

您还可以为剪辑定义路径。这非常灵活,因为您可以根据需要调整路径或对其进行动画处理。

注意:请记住,使用路径进行剪辑目前在浏览器中有点“脆弱”,因此您应该考虑在设置前后使用保存()恢复()并使用剪辑路径,因为浏览器目前无法重置剪辑(恢复将恢复默认剪辑=完整画布);

让我们定义一个简单的之字形路径(在您的情况下,这将是您的波浪):

/// 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();

现在我们已经使用剪辑设置了剪辑蒙版,接下来绘制到画布上的任何东西都将被剪辑以适合该形状(请注意,我们确保形状可以在开始的地方结束):

 类似资料:
  • 定义 用于弹层等需要遮挡底部内容。 图片展示 代码演示 import Mask from 'pile/dist/components/mask' <Mask transparent={true} /> 属性 参数 描述 数据类型 默认值 transparent 是否透明(true:是,false:否) bool false hidden 是否隐藏(true:是,false:否) bool

  • 介绍 创建一个遮罩层,用于强调特定的页面元素,并阻止用户进行其他操作。 引入 import { createApp } from 'vue'; import { Overlay } from 'vant'; const app = createApp(); app.use(Overlay); 代码演示 基础用法 <van-button type="primary" text="显示遮罩层" @

  • 在popover、侧滑菜单等界面,经常会用到蒙版遮罩;比如popover弹出后,除popover控件外的其它区域都会遮罩一层蒙版,用户点击蒙版不会触发蒙版下方的逻辑,而会关闭popover同时关闭蒙版;再比如侧滑菜单界面,菜单划出后,除侧滑菜单之外的其它区域都会遮罩一层蒙版,用户点击蒙版会关闭侧滑菜单同时关闭蒙版。 遮罩蒙版常用的操作包括:创建、显示、关闭,如下代码: var mask = mui

  • Mask 遮罩层 平台差异说明 App H5 微信小程序 支付宝小程序 百度小程序 头条小程序 QQ小程序 √ √ √ √ √ √ √ 基本使用 通过show参数配置是否显示遮罩 遮罩被点击时,会发送一个click事件,如不需要此事件,请设置mask-click-able参数为false <template> <u-mask :show="show" @click="show = false">

  • iOS 7+ 允许创建全屏应用,但是当状态栏覆盖你的应用时,会有这样的问题: 不好! 好! Framework7帮助你解决这个问题。它自动检测你的应用是否是全屏模式,如果是的话,自动添加"with-statusbar-overlay"类到<html>(如果不是的话,移除这个类)。通过"with-statusbar-overlay"类(应用处于全屏模式的时候),<html>在顶部拥有额外的paddi

  • 本文向大家介绍在8085中需要遮罩,包括了在8085中需要遮罩的使用技巧和注意事项,需要的朋友参考一下  假设8085由于RST6.5引脚而中断,并且已经分支到ISS的RST6.5引脚。然后,除了此ISS开头的DI指令外,除TRAP之外的所有中断均被禁止。因此,即使在执行RST6.5 ISS的过程中RST7.5引脚处于激活状态,也不会由于RST7.5而发生8085中断。实际上,较高优先级的中断是R