CSS `mask-composite` (`add`, `subtract`, `intersect`):组合多个遮罩层

各位朋友,大家好!今天咱们来聊聊CSS里一个挺有意思的家伙——mask-composite,这玩意儿能让你的遮罩效果玩出新花样,组合多个遮罩层,就像在PS里玩图层混合模式一样。准备好了吗?咱们这就开始!

一、什么是 mask-composite

简单来说,mask-composite就是用来控制多个遮罩图层之间如何相互作用的。想象一下,你有两张透明胶片,上面分别涂了黑色的图案,你想把它们叠在一起看效果。mask-composite就决定了这两张胶片叠在一起后,哪些部分是最终显示的,哪些部分被遮盖。

二、mask-composite 的取值

mask-composite 有几个常用的取值,每个取值代表一种不同的混合模式:

描述
add 默认值。将所有遮罩图层的效果叠加在一起。如果任何一个图层遮盖了某个区域,那么该区域就会被遮盖。可以理解为“并集”。
subtract 从前面的遮罩图层中减去后面的遮罩图层。后面的遮罩图层会将前面的遮罩图层中与其重叠的部分“挖掉”。可以理解为“差集”。
intersect 仅显示所有遮罩图层重叠的部分。只有所有图层都遮盖的区域才会最终被遮盖。可以理解为“交集”。
exclude 显示所有遮罩图层不重叠的部分。重叠的区域会被透明化。可以理解为“异或”。

三、基本用法示例

咱们先来个最简单的例子,用两个径向渐变来做遮罩,看看addsubtractintersect的效果:

<!DOCTYPE html>
<html>
<head>
<title>mask-composite Example</title>
<style>
.masked {
  width: 300px;
  height: 200px;
  background-color: lightblue;
  border: 1px solid black;
}

.masked-add {
  mask-image: radial-gradient(circle, black 50%, transparent 50%),
              radial-gradient(circle at 100% 100%, black 50%, transparent 50%);
  mask-size: 50% 50%;
  mask-repeat: no-repeat;
  mask-composite: add; /* 默认值,可以省略 */
}

.masked-subtract {
  mask-image: radial-gradient(circle, black 50%, transparent 50%),
              radial-gradient(circle at 100% 100%, black 50%, transparent 50%);
  mask-size: 50% 50%;
  mask-repeat: no-repeat;
  mask-composite: subtract;
}

.masked-intersect {
  mask-image: radial-gradient(circle, black 50%, transparent 50%),
              radial-gradient(circle at 100% 100%, black 50%, transparent 50%);
  mask-size: 50% 50%;
  mask-repeat: no-repeat;
  mask-composite: intersect;
}

.masked-exclude {
  mask-image: radial-gradient(circle, black 50%, transparent 50%),
              radial-gradient(circle at 100% 100%, black 50%, transparent 50%);
  mask-size: 50% 50%;
  mask-repeat: no-repeat;
  mask-composite: exclude;
}

</style>
</head>
<body>

<h1>mask-composite Examples</h1>

<h2>mask-composite: add</h2>
<div class="masked masked-add">This is some text.  The mask is applied here.</div>

<h2>mask-composite: subtract</h2>
<div class="masked masked-subtract">This is some text.  The mask is applied here.</div>

<h2>mask-composite: intersect</h2>
<div class="masked masked-intersect">This is some text. The mask is applied here.</div>

<h2>mask-composite: exclude</h2>
<div class="masked masked-exclude">This is some text. The mask is applied here.</div>

</body>
</html>

在这个例子里,我们用了两个圆形渐变来做遮罩,分别位于元素的左上角和右下角。

  • add:两个圆形的遮罩区域都生效,所以四个角都被遮住了。
  • subtract:右下角的圆形从左上角的圆形里“挖”了一个洞。
  • intersect:只有两个圆形重叠的部分才会被遮住,形成一个小的遮罩区域。
  • exclude: 只有两个圆形不重叠的部分会被遮住,重叠部分透明。

四、进阶用法:更复杂的遮罩组合

mask-composite真正的强大之处在于它可以组合多个遮罩图层,创造出复杂的遮罩效果。 比如,我们可以用它来做一个镂空文字的效果:

<!DOCTYPE html>
<html>
<head>
<title>mask-composite Advanced Example</title>
<style>
.masked-text {
  width: 400px;
  height: 200px;
  background-image: url('https://via.placeholder.com/400x200'); /* 随便找张图 */
  color: white;
  font-size: 60px;
  font-weight: bold;
  text-align: center;
  line-height: 200px; /* 垂直居中 */
  mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 200"><text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-size="60" font-weight="bold" fill="white">HELLO</text></svg>'),
               linear-gradient(to right, black 20%, transparent 80%);
  mask-size: 100%, 100%;
  mask-repeat: no-repeat;
  mask-composite: subtract; /* 关键:用文字遮罩来“挖”掉渐变遮罩 */
}
</style>
</head>
<body>

<div class="masked-text"></div>

</body>
</html>

这个例子里,我们用了两个遮罩:

  1. 一个SVG文字,用来定义镂空的形状。
  2. 一个线性渐变,从左到右,黑色到透明。

通过mask-composite: subtract,我们将文字遮罩从渐变遮罩中减去,最终效果就是文字是镂空的,并且从左到右有一个渐变的遮罩效果。

五、mask-compositeclip-path 的区别

你可能会问,mask-compositeclip-path有什么区别?它们都能用来做裁剪,但它们的工作方式不太一样:

  • clip-path:定义一个裁剪区域,超出这个区域的部分会被隐藏。它就像一把剪刀,直接把多余的部分剪掉。裁剪区域可以是圆形、矩形、多边形等等。
  • mask-image + mask-composite: 使用图像或者渐变作为遮罩,控制元素的透明度。黑色区域完全遮盖,白色区域完全透明,灰色区域半透明。mask-composite可以组合多个遮罩,创造更复杂的效果。

简单来说,clip-path是“非黑即白”,要么显示,要么隐藏;而mask-image+mask-composite 可以有半透明的效果,更加灵活。

六、mask-composite 的兼容性

mask-composite的兼容性还算不错,主流浏览器都支持。但是,为了更好的兼容性,建议加上-webkit-前缀。

七、一些使用技巧和注意事项

  • 性能问题:复杂的遮罩效果可能会影响性能,尤其是在移动设备上。尽量避免使用过多的遮罩图层,或者使用简单的遮罩形状。
  • 矢量图 vs 位图:矢量图(比如SVG)作为遮罩通常比位图(比如PNG)性能更好,因为矢量图可以缩放而不失真。
  • 调试技巧:如果遮罩效果不符合预期,可以尝试改变遮罩图层的顺序,或者调整mask-sizemask-position属性。
  • 结合CSS变量:可以结合CSS变量来动态改变遮罩效果,比如通过JavaScript来控制遮罩的位置、大小或者颜色。

八、更高级的例子:多重遮罩动画

咱们再来一个稍微复杂一点的例子,做一个多重遮罩动画,让大家感受一下mask-composite的威力:

<!DOCTYPE html>
<html>
<head>
<title>mask-composite Animation Example</title>
<style>
.masked-animation {
  width: 400px;
  height: 300px;
  background-image: url('https://via.placeholder.com/400x300'); /* 随便找张图 */
  position: relative;
  overflow: hidden; /* 隐藏超出容器的部分 */
}

.mask-layer {
  position: absolute;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5); /* 半透明黑色背景 */
}

.circle-mask {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background-color: white;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  animation: moveCircle 5s linear infinite;
}

@keyframes moveCircle {
  0% {
    transform: translate(-50%, -50%) scale(0.1);
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  80% {
    opacity: 1;
  }
  100% {
    transform: translate(-50%, -50%) scale(5);
    opacity: 0;
  }
}

.masked-animation {
  mask-image: radial-gradient(circle, black 20%, transparent 80%),
               radial-gradient(circle at 100% 0, black 20%, transparent 80%),
               radial-gradient(circle at 0 100%, black 20%, transparent 80%),
               radial-gradient(circle at 100% 100%, black 20%, transparent 80%);
  mask-size: 50px 50px;
  mask-position: 0 0, 100% 0, 0 100%, 100% 100%;
  mask-repeat: no-repeat;
  mask-composite: subtract;
}

</style>
</head>
<body>

<div class="masked-animation">
  <div class="mask-layer">
    <div class="circle-mask"></div>
  </div>
</div>

</body>
</html>

这个例子看起来复杂,但其实原理很简单:

  1. 我们有一个容器.masked-animation,里面放了一张背景图。
  2. 容器里有一个半透明的黑色背景.mask-layer,用来降低图片的亮度。
  3. .mask-layer里有一个白色圆形.circle-mask,它会不断地放大并淡出,形成一个动态的光圈效果。
  4. 我们使用mask-image定义了四个角的遮罩,让图片四个角变暗。
  5. 关键在于mask-composite: subtract,它将四个角的遮罩从.masked-animation中减去,形成一个边缘变暗的效果。

这个例子展示了如何利用mask-composite和动画,创造出一些有趣的光影效果。

九、mask-modemask-origin

除了mask-composite之外,还有两个与遮罩相关的属性也值得了解:

  • mask-mode:指定如何将遮罩应用到元素上。它的取值有luminance(亮度,默认值)和alpha(透明度)。luminance表示遮罩的亮度决定元素的透明度,黑色完全遮盖,白色完全透明。alpha表示遮罩的透明度决定元素的透明度,完全透明的遮罩区域会完全遮盖元素。通常情况下,我们使用默认的luminance就足够了。
  • mask-origin:指定遮罩的起始位置。它的取值和background-origin类似,可以是border-boxpadding-box或者content-box

十、总结

好了,今天的讲座就到这里。希望通过这些例子,大家对mask-composite有了一个更深入的了解。记住,mask-composite是一个强大的工具,可以让你创造出各种各样炫酷的遮罩效果。只要你敢于尝试,就能玩出不一样的花样!

记住,编程的乐趣在于探索和实践,所以别光看不练,赶紧动手试试吧!如果遇到什么问题,欢迎随时提问。 祝大家编程愉快!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注