神奇的 CSS MASK

396 阅读4分钟

前言

最近在仙逆的时候,发现一个号神奇的功能,刚开始以为很简单,但是当我深入了解后发现,这个属性很不简单,在这里记录一个学习的过程。

简单的一个截图例子: caae4416021d0248ae03b1001a899caf_720.png

一、CSS mask 属性基础概念

mask 属性允许通过遮罩层或裁剪区域,隐藏元素的部分或全部可见区域。其本质是通过透明度映射来控制元素显示范围:遮罩层中白色区域(透明值为 1)显示元素内容,黑色区域(透明值为 0)隐藏内容,灰色区域则根据亮度比例半透明显示。

1.2 与 clip-path 的核心区别

特性mask 属性clip-path 属性
作用原理基于透明度映射隐藏内容基于路径裁剪显示区域
视觉效果可实现半透明渐变遮罩仅支持硬边缘裁剪
兼容性需注意浏览器前缀(如 -webkit-mask现代浏览器支持较好

二、mask 属性语法与核心属性详解

2.1 复合属性与简写语法

mask 是以下属性的简写形式,可通过单一属性快速配置多重效果: css

mask: [mask-image] [mask-mode] [mask-repeat] [mask-position]  
      [mask-clip] [mask-origin] [mask-size] [mask-composite];  

2.2 核心属性分拆解析

2.2 核心属性分拆解析

(1)mask-image:定义遮罩图像

  • 位图 / 矢量图

    css

    mask-image: url(mask.png);        /* 位图遮罩 */  
    mask-image: url(masks.svg#star);  /* SVG路径遮罩 */  
    
  • 渐变效果

    css

    mask-image: linear-gradient(to bottom, black 50%, transparent 50%);  
    mask-image: radial-gradient(circle, black 60%, transparent 60%);  
    
  • 渐变与图像混合

    css

    mask-image: linear-gradient(90deg, transparent, black), url(pattern.png);  
    

(2)mask-mode:定义遮罩层类型

  • alpha:使用图像的透明度通道作为遮罩(默认值)。
  • luminance:使用图像的亮度值作为遮罩(白色区域显示,黑色区域隐藏)。

(3)mask-size & mask-position:控制遮罩尺寸与位置

css

mask-size: 50% 50%;        /* 遮罩尺寸为元素的50% */  
mask-position: center;     /* 遮罩居中 */  
mask: url(mask.png) 20px 30px / 80% no-repeat;  /* 简写组合 */  

(4)mask-composite:定义多遮罩层混合模式

css

mask-composite: add;       /* 叠加遮罩 */  
mask-composite: exclude;   /* 排除遮罩区域 */  

三、基础案例:从静态遮罩到渐变效果

3.1 位图与 SVG 遮罩实战

html

预览

<div class="mask-demo">
  <img src="target.jpg" alt="目标图像" />
</div>

<style>
.mask-demo {
  width: 300px;
  height: 200px;
  -webkit-mask: url(star.svg) no-repeat center; /* 兼容webkit内核 */
  mask: url(star.svg) no-repeat center;
}
</style>

效果说明:通过 SVG 路径(如星形)作为遮罩,图像将仅显示为星形区域。

3.2 渐变遮罩实现动态视觉效果

css

/* 从上到下渐隐效果 */
.gradient-mask {
  background: url(bg.jpg);
  mask: linear-gradient(to bottom, black 80%, transparent 100%);
}

/* 圆形径向渐变遮罩 */
.circle-mask {
  mask: radial-gradient(circle at 50% 50%, black 70%, transparent 70%);
}

效果演示:渐变遮罩可实现元素内容的平滑过渡隐藏,常用于图片焦点突出或文本渐隐效果。 最基本,使用 mask 的方式是借助图片,类似这样:

mask: url(mask.png); /* 使用位图来做遮罩 */ 
mask: url(masks.svg#star); /* 使用 SVG 图形中的形状来做遮罩 */
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>css mask</title>
    <style>
      .mask1 {
        width: 200px;
        height: 200px;
        mask: url(./w3.png) no-repeat 50% 50%;
      }
      img {
        width: 300px;
        height: 300px;
      }
    </style>
  </head>
  <body>
    <div class="mask1">
      <img src="logo.jpg" alt="" />
    </div>
  </body>
</html>

image.png 使用线性渐变和径向渐变为图像创建不同的遮罩层:

 mask: linear-gradient(#000, transparent);
 mask: radial-gradient(circle, black 50%, rgba(0, 0, 0, 0.5) 50%);

示例

  .mask1 {
        background: url(psc.jpg) no-repeat left left;
        mask: linear-gradient(180deg, transparent, #000);
      }

psc.jpg 使用mask效果

image.png 通过上面的案例,了解mark基本用法。

四.使用mask实现人像防遮挡功能

了解了mask 的使用方法后,接下来,我们运用 mask,简单实现视频弹幕中,弹幕碰到人物,自动被隐藏过滤的例子。 首先,我简单的模拟了一个视频,以及一些基本的弹幕:

image.png

     <!-- 背景 -->
<div class="video"> </div>
<!-- <div class="g-yasuo"></div> -->
<!-- 包裹所有弹幕的容器 -->
  <div class="bulletChatAll">
      <!-- 所有弹幕 -->
      <div class="bulletChat">6666</div>
      ...
      <div class="bulletChat">777</div>
  </div>
  </div>

接来,我来添加一个人物,并且用 animation 模拟了简单的运动,在运动的过程中,人物是被弹幕给遮挡住的。

image.png 我利用 mask 制作一个 radial-gradient ,使得人物附近为 transparent,并且根据人物运动的 animation,给 mask 的 mask-position 也添加上相同的 animation 即可。最终可以得到这样的效果:

.bulletChatAll {
    position: absolute;
    mask: radial-gradient(circle at 100px 100px, transparent 60px, #fff 80px, #fff 100%);
    animation: mask 10s infinite alternate;
}

@keyframes mask {
    100% {
        mask-position: 85vw 0;
    }
}

五.实际生产环境中的运用

上面只是一个demo,利用 mask 实现弹幕遮罩过滤的效果。但是实际情况比上述的场景复制的多,因为人物英雄的位置是不确定的,每一刻都在变化。所以在实际生产环境中,mask 图片的参数,其实是由后端实时对视频进行处理计算出来的,然后传给前端,前端再进行渲染。