CSS 镂空效果:利用 `mask-composite: exclude` 实现复杂的遮罩减法

好的,我们开始。

CSS 镂空效果:利用 mask-composite: exclude 实现复杂的遮罩减法

大家好!今天我们来深入探讨 CSS 遮罩技术中一个非常强大的属性:mask-composite,特别是它的 exclude 值。 mask-composite允许我们组合多个遮罩层,实现比单一遮罩更复杂的视觉效果,而 exclude 则允许我们从一个遮罩中减去另一个遮罩,从而创建镂空效果。

1. 遮罩的基本概念

在深入 mask-composite 之前,我们先回顾一下 CSS 遮罩的基本概念。遮罩允许我们隐藏或显示元素的某些部分,根据遮罩图像或渐变来决定哪些部分可见。 CSS 中有几种方式应用遮罩:

  • mask-image: 使用图像或渐变作为遮罩。
  • mask-mode: 定义如何解释遮罩图像的亮度。
  • mask-size: 控制遮罩图像的大小。
  • mask-position: 控制遮罩图像的位置。
  • mask-repeat: 控制遮罩图像的重复方式。
  • mask-origin: 指定遮罩原点。
  • mask-clip: 指定遮罩裁剪区域。
  • mask: 简写属性,可以一次性设置上述所有属性。

2. mask-composite: 组合遮罩

mask-composite 属性定义了如何将多个遮罩层组合在一起。 它接受以下几个值:

  • add: 将所有遮罩层加在一起。
  • subtract: 从后续遮罩层中减去第一个遮罩层。 (已被废弃)
  • intersect: 只显示所有遮罩层都覆盖的区域。
  • exclude: 显示所有遮罩层都覆盖的区域,以及只被部分遮罩层覆盖的区域。这是我们要重点讲解的值。
  • source-over: 按照正常混合模式绘制遮罩。
  • source-in: 只显示源图像(被遮罩的元素)与遮罩图像重叠的部分,源图像的其他部分变为透明。
  • source-out: 只显示源图像(被遮罩的元素)与遮罩图像不重叠的部分,源图像的其他部分变为透明。
  • source-atop: 只在遮罩图像的上方显示源图像。
  • destination-over: 在目标图像(遮罩图像)的下方显示源图像。
  • destination-in: 只显示目标图像(遮罩图像)与源图像重叠的部分,目标图像的其他部分变为透明。
  • destination-out: 只显示目标图像(遮罩图像)与源图像不重叠的部分,目标图像的其他部分变为透明。
  • destination-atop: 只在源图像的上方显示目标图像。
  • lighter: 源图像和目标图像都显示,重叠部分会变亮。
  • copy: 只显示源图像。
  • xor: 只显示源图像和目标图像不重叠的部分。

3. mask-composite: exclude 的工作原理

mask-composite: exclude 的核心作用是创建一个镂空效果。 想象一下,你有一个矩形遮罩和一个圆形遮罩。 如果使用 exclude,最终效果是矩形中挖去了一个圆形。 只有矩形但没有圆形覆盖的区域,以及只有圆形但没有矩形覆盖的区域会显示出来。 重叠区域会被镂空。

更准确的描述是,对于每一个像素点,如果该点被奇数个遮罩层覆盖,则显示该点;如果被偶数个遮罩层覆盖(包括零个),则隐藏该点。

4. 代码示例:简单镂空

让我们通过一个简单的例子来演示 mask-composite: exclude 的用法。

<!DOCTYPE html>
<html>
<head>
<title>mask-composite: exclude Example</title>
<style>
  .container {
    width: 200px;
    height: 200px;
    background-color: lightblue;
    position: relative;
  }

  .masked {
    width: 100%;
    height: 100%;
    background-color: orange;
    -webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"><rect width="200" height="200" fill="black"/></svg>'),
                      url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"><circle cx="100" cy="100" r="50" fill="white"/></svg>');
    -webkit-mask-composite: exclude;
    mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"><rect width="200" height="200" fill="black"/></svg>'),
                url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"><circle cx="100" cy="100" r="50" fill="white"/></svg>');
    mask-composite: exclude;
    mask-size: 100%, auto;
    mask-position: center;
    mask-repeat: no-repeat;
    position: absolute;
    top: 0;
    left: 0;
  }
</style>
</head>
<body>

<div class="container">
  <div class="masked"></div>
</div>

</body>
</html>

在这个例子中,我们创建了一个 container div,背景色为浅蓝色。 然后,我们创建了一个 masked div,背景色为橙色,并应用了遮罩。

  • 第一个遮罩是 200×200 的黑色矩形。这意味着默认情况下,橙色的 masked div 是可见的。
  • 第二个遮罩是一个半径为 50 的白色圆形。
  • mask-composite: exclude 告诉浏览器从矩形遮罩中“减去”圆形遮罩。

结果是,我们会看到一个橙色的矩形,中间有一个浅蓝色的圆形镂空。

5. 使用渐变创建遮罩

mask-image 不仅可以接受图片,还可以接受 CSS 渐变。 这为创建复杂的遮罩效果提供了更大的灵活性。

<!DOCTYPE html>
<html>
<head>
<title>mask-composite: exclude with Gradients</title>
<style>
  .container {
    width: 300px;
    height: 300px;
    background-color: lightgreen;
    position: relative;
  }

  .masked {
    width: 100%;
    height: 100%;
    background-color: tomato;
    -webkit-mask-image: linear-gradient(to right, black 50%, transparent 50%),
                       radial-gradient(circle at center, white 25%, transparent 25%);
    -webkit-mask-composite: exclude;
    mask-image: linear-gradient(to right, black 50%, transparent 50%),
                radial-gradient(circle at center, white 25%, transparent 25%);
    mask-size: 200% 200%, auto;
    mask-position: center;
    mask-repeat: no-repeat;
    position: absolute;
    top: 0;
    left: 0;
  }
</style>
</head>
<body>

<div class="container">
  <div class="masked"></div>
</div>

</body>
</html>

在这个例子中:

  • 我们使用了一个线性渐变,从左到右,黑色占 50%,透明占 50%。
  • 我们使用了一个径向渐变,从中心向外,白色占 25%,透明占 25%。
  • mask-composite: exclude 将这两个遮罩组合在一起。

效果是,你会看到番茄色的背景,左半部分被一个圆形镂空,右半部分是完整的番茄色。由于线性渐变的黑色部分覆盖了整个左半部分,而径向渐变在其中心创建了一个白色圆形,exclude 的效果就是从左半部分“减去”了这个圆形。

6. 多个遮罩层的组合

mask-composite 的真正威力在于它可以组合多个遮罩层。 我们可以创建非常复杂的镂空效果。

<!DOCTYPE html>
<html>
<head>
<title>mask-composite: exclude with Multiple Masks</title>
<style>
  .container {
    width: 300px;
    height: 300px;
    background-color: gold;
    position: relative;
  }

  .masked {
    width: 100%;
    height: 100%;
    background-color: purple;
    -webkit-mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300"><rect width="300" height="300" fill="black"/></svg>'),
                       url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300"><circle cx="150" cy="150" r="75" fill="white"/></svg>'),
                       url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300"><rect x="50" y="50" width="200" height="200" fill="white"/></svg>');

    -webkit-mask-composite: source-over, exclude, exclude;
    mask-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300"><rect width="300" height="300" fill="black"/></svg>'),
                url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300"><circle cx="150" cy="150" r="75" fill="white"/></svg>'),
                url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300"><rect x="50" y="50" width="200" height="200" fill="white"/></svg>');
    mask-composite: source-over, exclude, exclude;

    mask-size: 100%, auto, auto;
    mask-position: center;
    mask-repeat: no-repeat;
    position: absolute;
    top: 0;
    left: 0;
  }
</style>
</head>
<body>

<div class="container">
  <div class="masked"></div>
</div>

</body>
</html>

在这个例子中,我们使用了三个遮罩层:

  1. 黑色矩形 (保证整个元素都被遮罩)。
  2. 白色圆形。
  3. 白色矩形。

关键在于 mask-composite: source-over, exclude, exclude; 的设置。

  • source-over 应用于第一个遮罩(黑色矩形),表示正常混合模式,保证基础遮罩的完整性。
  • 第一个 exclude 从黑色矩形中减去白色圆形。
  • 第二个 exclude 从结果中减去白色矩形。

最终效果是,你会看到一个紫色的背景,其中间有一个金色的圆形,圆形中间又有一个紫色的矩形。

7. 兼容性问题

虽然 mask-composite 提供了强大的功能,但需要注意浏览器的兼容性。 你需要使用 -webkit- 前缀来支持一些旧版本的浏览器。 同时,建议使用 Autoprefixer 等工具来自动添加必要的浏览器前缀。

你可以在 caniuse.com 上查看 mask-composite 的最新兼容性信息。 通常来说,现代浏览器都提供了良好的支持。

8. mask-mode 的影响

mask-mode 属性定义了如何解释遮罩图像的亮度。 它接受以下值:

  • luminance: 遮罩图像的亮度值决定了透明度。 白色是完全不透明,黑色是完全透明。
  • alpha: 遮罩图像的 alpha 值决定了透明度。

默认值是 luminance。 在使用 mask-composite: exclude 时,理解 mask-mode 非常重要,因为它可以影响镂空效果的呈现。

例如,如果你的遮罩图像包含半透明的区域,luminancealpha 会产生不同的结果。luminance 会根据亮度值来调整透明度,而 alpha 会直接使用 alpha 值。

9. 性能考虑

使用遮罩可能会对性能产生影响,特别是当遮罩图像很大或很复杂时。 为了优化性能,可以考虑以下几点:

  • 尽量使用矢量图像(SVG)作为遮罩,而不是位图图像。 SVG 图像通常体积更小,渲染速度更快。
  • 避免使用过于复杂的遮罩。 如果可能,将复杂的遮罩分解为多个简单的遮罩。
  • 使用硬件加速。 确保你的 CSS 代码能够触发硬件加速。

10. 一些有用的技巧

  • 使用开发者工具来调试遮罩效果。 Chrome 和 Firefox 的开发者工具都提供了强大的 CSS 调试功能,可以帮助你理解遮罩的工作原理。
  • 尝试不同的 mask-composite 值,看看它们如何影响最终效果。
  • 利用 CSS 变量来动态控制遮罩的属性。

表格:mask-composite 属性值总结

属性值 描述
add 将所有遮罩层加在一起。
subtract 从后续遮罩层中减去第一个遮罩层。(已废弃)
intersect 只显示所有遮罩层都覆盖的区域。
exclude 显示所有遮罩层都覆盖的区域,以及只被部分遮罩层覆盖的区域。
source-over 按照正常混合模式绘制遮罩。
source-in 只显示源图像(被遮罩的元素)与遮罩图像重叠的部分,源图像的其他部分变为透明。
source-out 只显示源图像(被遮罩的元素)与遮罩图像不重叠的部分,源图像的其他部分变为透明。
source-atop 只在遮罩图像的上方显示源图像。
destination-over 在目标图像(遮罩图像)的下方显示源图像。
destination-in 只显示目标图像(遮罩图像)与源图像重叠的部分,目标图像的其他部分变为透明。
destination-out 只显示目标图像(遮罩图像)与源图像不重叠的部分,目标图像的其他部分变为透明。
destination-atop 只在源图像的上方显示目标图像。
lighter 源图像和目标图像都显示,重叠部分会变亮。
copy 只显示源图像。
xor 只显示源图像和目标图像不重叠的部分。

11. 实际应用场景

mask-composite: exclude 在实际项目中有很多应用场景:

  • 创建复杂的按钮效果。
  • 实现独特的图片展示效果。
  • 制作自定义的进度条。
  • 构建交互式的信息图表。
  • 实现创意的文字排版。

一些思考

mask-composite: exclude 是 CSS 遮罩技术中一个强大且灵活的工具。 通过理解其工作原理和结合不同的遮罩图像和渐变,可以创造出令人惊叹的视觉效果。 虽然兼容性可能是一个挑战,但随着现代浏览器的不断发展,mask-composite 的应用前景将越来越广阔。

更多IT精英技术系列讲座,到智猿学院

发表回复

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