探索CSS Masking模块:Masking

发布于 大漠

探索CSS Masking模块主要分为ClippingMasking两个部分,在上一节中,花了很大的篇幅介绍了Clipping相关的特性,今天接着来学习或者聊聊Masking相关的知识点。

从上一节中我们知道,在Masking中有一个遮罩层,这个遮罩层是一个图像,该层也被称为遮罩模式,主要有高亮Alpha两种模式。其中Alpha模式带有alpha通道的图像,alpha通道包含在每个像素数据中的透明信息。最简单的示例就是带有黑色和透明区域的PNG图像,其中黑色部分将会显示,透明区域内容将会被隐藏。

高亮模式使用图像的亮度值作为遮罩值,如下图所示,遮罩层白色区域将会显示出来,透明区域将会被隐藏:

最终的效果如下:

接下来,一起来探探Masking相关的特性和使用。

CSS mask

CSS中的mask分成两大部分,其中第一部分类似于background,而另一部分类似于border-image。先来看maskbackground属性的对照表:

mask属性 background属性 备注
mask-image background-image 设置遮罩图片的路径
mask-position background-position 设置遮罩图片的位置
mask-size background-size 设置遮罩的大小
mask-repeat background-repeat 设置遮罩图片的重复性
mask-origin background-origin 遮罩图像原点位置
mask-clip background-clip 遮罩图像裁切方式
mask-mode   设置遮罩的模式
mask-composite   设置遮罩图层的合成方式
  background-attachment  
  background-color  

从上表中可以看出mask中有属性和background相似,而且和使用方式都相似。接着再来看另一部分mask-borderborder-image的对照:

mask-border属性 border-image属性 备注
mask-border-source border-image-source 遮罩边框图像
mask-border-slice border-image-slice 遮罩图像切割位置
mask-border-width border-image-width 遮罩边框宽度
mask-border-repeat border-image-repeat 遮罩边框平铺方式;
mask-border-outset border-image-outset 遮罩边框距离边框的距离
mask-border-mode   遮罩边框模式

同样的,mask-borderborder-image在语法上是非常相似的,也就是说,只要你理解了border-image的使用对于mask-border的使用也不会有任何的难度。

mask的使用

先从语法规则开始,mask的语法规则很简单:

mask: <mask-reference> <masking-mode>? || <position> [ / <bg-size> ]? || <repeat-style> || <geometry-box> || [ <geometry-box> | no-clip ] || <compositing-operator>

简单的解释一下:

<mask-reference>

<mask-reference>用来指定遮罩图像源,主要值有none<image><mask-source>。简单地说,用来指定遮罩图片的路径,即mask-image

如果取值为none时,表示作为透明的黑色图像层计算。如果计算的值不是none,就会创建一个叠加上下文(Stacking Context),这与CSS的opacity取值为非1所起的效果相似。

注意<mask-reference>取值为none时可能会影响mask的操作,具体取决于mask-composite指定合成值。

<image>在CSS中可以用于很多属性中,比如background-imagelist-style-imagecursor等。在某些情况下,图像是无效的,例如<url>指向的资源不是有效的图像格式。无效的图像被渲染为没有内在维度的纯色“透明”图像。然而,无效图像在某些上下文中具有特殊的行为,例如image()函数。

<mask-source>等于<url>。他可以指向的是SVG中的<mask>元素,比如url(commonmasks.svg#mask)或者是url()指向的图像。

看上去感觉好复杂,其实没有这么复杂,你可以将其当作是background-image。比如可以是一个png格式的图片:

body {
    mask-image: url(mask.png);
}

也可以是一个使用渐变绘制的图像:

body {
    mask-image: linear-gradient(to right, black 0%, transparent 100%);
}

还可以是.svg中某一个带id<mask>元素:

body {
    mask-image: url(resources.svg#maskEleId);
}

当然也可以是一个none值:

body {
    mask-image: none;
}

当取值为none时,就好比没有使用任何遮罩图一样,但有时还是取值于mask-composite的值(合成)

更简单地说,mask-image可以通过下面的方式引用图像:

<url> | <image()> | <image-set()> | <element()> | <cross-fade()> | <gradient>

<mask-mode>

<mask-mode>对应的就是mask-mode属性,用来设置遮罩图像的模式,主要有高亮(Luminance)和透明通道(Alpha)两种模式。其取值主要有:alphaluminanceauto

高亮模式(Luminance)

还是用一张图来描述,这样描述会更清晰一些,假设我们有一张下面这样的遮罩图像:

如果使用上图作为遮罩图,那么**白色区域(高亮)**可见,透明区域不可见。也就是说, mask-mode取值为luminance时,将会运图遮罩图像的亮度值,而不是使用图像的透明通道值作为遮罩值

当使用亮度遮罩模式时,会先计算颜色通道的亮度,然后计算出的亮度值乘以相应的alpha值,从颜色通道值中计算出给定的遮罩模式的值。

亮度遮罩模式可以包含任何颜色,而不仅仅是白色。亮度值然后由遮罩的RGB值和亮度系数,比如:luma = (0.2126 * R + 0.7152 * G + 0.0722 * B)。确定对象的透明度,然后乘以alpha通道对象的亮度值和遮罩的alpha通道值。

所以,如果你有一个彩色的图像,它有一些完全透明的区域,元素不会显示图像在哪里是透明的,但是当图像的alpha值为1时,遮罩的值取决于使用的颜色(每个像素)。比如下面这个示例:

目前只有在Firefox Nightly能看到mask-mode效果,比如下图是mask-mode取值为luminance的效果:

如上例所示,mask-image通过不同的颜色以不同的方式显示。来看一个录屏,可能体感会更强一些:

如果上面录屏效果不佳,可以将示例在Firefox Nightly浏览器查看,并且通过调试器修改mask-imagelinear-gradient()中的颜色

Alpha模式

Alpha遮罩模式是采用具有alpha通道的图像,其中alpha值用来遮罩的值。同样拿张图来描述:

上图是一张带有黑色和透明区域的PNG图像。遮罩图像黑色部分将会显示(alpha的值是1),透明区域alpha的值为0)内容将会隐藏。

在图形学中,alpha通道是每个像素数据的一部分,用于透明信息。alpha通道在遮罩中被广泛使用。它指定两个像素重叠时,一个像素的颜色应该如何与另一个像素全并。图像的不同部分将具有不同的透明度级别,这取决于你希望遮罩元素显示的透明度。

就上图而言,黑色区域的alpha值为1,透明区域的alpha值为0

当使用带有alpha通道的图像作为alpha的遮罩模式时,图像为黑色(完全不透明)的区域将是元素的可见区域,而图像的透明区域将是元素不可见的区域。半透明区域将显示具有一定透明的元素。

显示具有不同alpha值的图像如何影响运用了Alpha遮罩模式的元素的最佳方案是使用一个渐变图像。一个从#000transprent的渐变。这个遮罩所应用的元素在渐变为不透明的地方是完全可见的,在alpha通道范围为01的地方是半透明的,在渐变为透明的地方是不可见的。

支持mask-mode的浏览器将看到的效果如下图所示:

无论通道模式(mask-mode)使用哪种方式alpha,还是luminance,计算遮罩值的过程都先假定遮罩的内容是一个**四通道RGBA**图形对象。对于其他类型的图形对象,需要进行如下特殊处理:

  • 对于遮罩中使用的三通道RGB图形对象,效果就好像该对象被转换成一个四通道RGBA图像,其alpha通道被设置为1
  • 对于遮罩中使用的一通道图像,效果就好像该对象被转换成一个四通道RGBA图像,只不过用于计算三个颜色通道和阿尔法通道都被设置为1
auto

mask-mode取值为auto时得到的效果和mask-image是什么类型有一定的关系。

  • 如果是<mask-source>类型,那么mask-mode采用的模式将是高亮(luminance)模式
  • 如果是<image>类型,那么mask-mode采用的模式将是alpha模式

另外,如果遮罩图形中使用了mask-type给元素设置了遮罩模式为alpha(比如<mask>元素中设置了mask-type="alpha"),而在引用该遮罩图形时显式的将mask-mode设置了luminance。那么mask-mode将会替代元素中mask-type设置的遮罩模式:

<mask id="SVGMask" mask-type="alpha" maskContentUnits="objectBoundingBox">
    <radialGradient id="radialFill">
        <stop stop-color="white" offset="0"/>
        <stop stop-color="black" offset="1"/>
    </radialGradient>
    <circle fill="url(#radialFill)" cx="0.5" cy="0.5" r="0.5"/>
</mask>

<style>
    rect {
        mask-image: url(#SVGMask);
        mask-mode: luminance;
    }
</style>

<rect width="200" height="200" fill="green"/>

<position>

<position>对应的即是mask-position属性,其使用和CSS中的background-position相似,主要用于设置遮罩图像(mask-image)在元素中的位置。而mask-position设置遮罩图像位置是相对于mask-origin的初始位置的。

来看一个示例,mask-position采用不同的值得到的效果将不一样:

上面我们看到的是CSS中background-position中关键词的一些使用,其实除了使用toprightbottomleft这样的关键词之外,还可以使用百分比或者其他的任何长度单位。另外,mask-position也可以相对于左上角的其他角。比如,相对底部10px,右侧3em,我们可以这样来写:

mask-position: right 3em bottom 10px;

对于mask-position取值为百分比的时候,其计算相对而言还是较为复杂的,可以看看background-position取值为百分比单位的计算原理

<bg-size>

<bg-size>指的是mask-size,用于设置遮罩图像的尺寸大小,具体的使用和background-size相似。取值可以是:

<bg-size> = [ <length-percentage> | auto ]{1,2} | cover | contain

有关于background-size更详细的介绍可以点击这里

<repeat-style>

<repeat-style>指的是mask-repeat,用于设置遮罩图像的平铺方式,具体使用和background-repeat相似。其取值可以是:

<repeat-style> = repeat-x | repeat-y | [ repeat | space | round | no-repeat ]{1,2}

有关于background-repeat更详细的介绍可以点击这里

<geometry-box>

<geometry-box>主要被用于mask-origin(和background-origin相似)和mask-clip(和background-clip)两个属性之中。如果在mask中同时存在两个<geometry-box>,那么前一个指的是mask-origin,后一个指的是mask-clip

  • mask-origin用来设置遮罩图像的原点位置
  • mask-clip用来设置遮罩图像的显示区域

往往mask-originmask-clip可以结合在一起使用,得到一些不同的效果。

<geometry-box>的值和上一节中Clipping中一样:

如果是一个HTML元素被剪切,可以使用margin-boxborder-boxpadding-boxcontent-box框盒模式;如果运用于一个SVG元素上,可以使用fill-boxstroke-boxview-box

有关于background-originbackground-clip相关的介绍可以点击这里(background-origin)这里(background-clip)

<compositing-operator>

<compositing-operator>指的是合成操作。即mask-composite

@Ana Tudor在《Mask Compositing: The Crash Course》一文中详细的介绍了mask-composite

什么是遮罩合成

遮罩合成指的是我们可以使用不同的操作将多个不同的遮罩层合并成一个独立的遮罩层。那么问题来了?多个遮罩层是如何合并成一个呢?比如我们有两个遮罩层,在这两个遮罩层中取每对对应的像素,在它们的通道上应用特定的合成操作(具体合成的操作细节,后面会介绍),并为最终层获得第三个像素。如下图所示:

上图中左上图和左下图合层起来成了右侧的层。而左上图被称为源(Source),左下图被称为目标层(Destination),这对地我们来说没有多大的意义,因为给我的感觉一个是输入源,一个是输出结果(事实上,这两个都是输入),但是,就上图的结果而言,这两个层(源和目标层)却做了一个合层的操作(也被称为合层计算),从而得到最终的结果(上图右侧的合并层)。

上面演示的是仅有两个层合并,而事实上呢?我们可能会有两个以上的层合并,当有这种情形时,合层是分阶段完成的,从底部开始。

在第一阶段,从底部开始的第二层是源,从底部开始的第一层是目标,这两层被合层,结果成为第二阶段的目标,接着和从底部开始的第三层(源)合并。通过合成前两层的结果合成第三层,我们就得到了第三阶的目标,接着再从底部的第四层源合并。如下图这样的一个合并过程:

以此类推,直到我们达到最后一个阶段,在这里,最顶层由下面所有层的合成结果组成

mask中可以显式的通过mask-composite来设置合成的计算方式,其值主要有addsubtractintersectexclude

有关于mask-composite更详细的介绍可以阅读前段时间整理的《CSS的mask-composite》一文。

mask简写

上面分开介绍了mask属性中的每一个子属性,或许很多同学对规范不了解看起来会一脸的蒙逼,你也可以这样的去理解mask

mask: <mask-image> <mask-mode> ? <mask-position> [ / <mask-size>]? || <mask-repeat> || <mask-origin> || [<mask-clip> | no-clip] || <mask-composite>

更简单的使用,或者更好的记忆,那就是你只要记住了background即可

  • background属性用于元素背景
  • mask属性用于元素遮罩(哪些可见,哪些不可见)

也就是说,mask可以简写,但也可以分开来写:

mask-image: url(mask.svg);
mask-mode: alpha;
mask-position: center;
mask-size: 100%;
mask-repeat: no-repeat;
mask-origin: border-box;
mask-clip: border-box;
mask-composite: add;

具体的使用前面也一一介绍了。如果不清楚,那还可以阅读background相关的系列属性:

多个遮罩

在CSS中我们可以同一个元素中使用多个背景(简称多背景)来实现一些效果,比如下图这样的一个效果:

使用方式非常的简单:

background-image: url(bg1), url(bg2);

使用,进行分隔。上面只演示了background-image引用背景图片的示例,其实像background-sizebackground-repeat等属性也可以按上述的方式使用。

而在使用mask的时候,我们同样可以使用多个遮罩。而且它的使用方法和多背景的使用是相同的。我们来看一个示例,假设我们要实现一个类似下图的效果:

简单的来看看mask(这里会用到多个mask)是怎么实现一个优惠卷UI效果。

:root {
    --bg: linear-gradient(to bottom, #FF2655 0%, #FF4F26 100%), linear-gradient(to right, #fff, #fff);
    --mask: radial-gradient(circle at calc(100% - 10vw) 0, transparent, transparent 2vw,#000 2vw, #000 100%), radial-gradient(circle at calc(100% - 10vw) 100%, transparent, transparent 2vw,#000 2vw, #000 100%);
}
.coupons {
    background-image:var(--bg);
    background-size: 10vw 100%, cover;
    background-repeat: no-repeat;
    background-position:right center;
    mask-image: var(--mask);
    mask-size: 100% 51%;
    mask-repeat: no-repeat;
    mask-position: 0 0, 0 100%;
}

这里既用了多背景,也用了多遮罩。如果将其每个过程拆分一下:

实际效果如下:

是不是很简单,如果你感兴趣的话,可以使用该技术实现上图中其他的优惠卷的效果,或者下图这种带有切口的效果:

其实早在《使用Vue制作切口盒子组件》和《CSS如何实现内凹角效果》教程中或多或少都有mask的身影。

上面的示例图片主要使用的是CSS渐变来完成的。如果想了解CSS渐变怎么绘制图形,可以阅读《使用CSS渐变绘图》一文。

不知道大家有没有注意到,我们上面的示例中使用了两个遮罩图像:

--mask: radial-gradient(circle at calc(100% - 10vw) 0, transparent, transparent 2vw,#000 2vw, #000 100%), radial-gradient(circle at calc(100% - 10vw) 100%, transparent, transparent 2vw,#000 2vw, #000 100%);

并且配合了mask-size

mask-size: 100% 51%;

这样做的目的是,不让两个图形相互遮罩半圆。来模拟一下,如果我们把mask-size去掉,效果就不是我们想要的效果:

为什么会这样?简单的分解一下。先回到我们的--mask自定义属性设置的值中:

 --mask: radial-gradient(circle at calc(100% - 10vw) 0, transparent, transparent 2vw,#000 2vw, #000 100%), radial-gradient(circle at calc(100% - 10vw) 100%, transparent, transparent 2vw,#000 2vw, #000 100%);

其实他是两张图片(遮罩图)叠加在一起:

所以设置mask-size100% 51%是为了不让其相互填充半圆:

除了通过mask-size来处理之外,还有另外一种方式,就是采用mask自身独有的能力遮罩合成(mask-composite,把上面的示例修改一下,得到的效果将会是一样的:

.coupons {
    background-image:var(--bg);
    background-size: 10vw 100%, cover;
    background-repeat: no-repeat;
    background-position:right center;
    mask-image: var(--mask);
    mask-repeat: no-repeat;
    mask-composite: add;
    mask-composite: source-in;
}

mask-border的使用

前面我们看到的是类似于backgroundmask的使用,但在Masking系列中还有另外一部分,那就是mask-border的使用,它和border-image的使用非常的相似。如果你从未接触过,可以先对border-image进行了解,这有助于你更好的理解mask-border

border-image中有一个非常重要的概念,即九宫格切图。在mask-border中同样的有这样的一个概念,将用于mask-border的图像分割成九个部分:四个角四个边中间部分,如下图所示:

简单地说,我们可以对一个用于mask-border的图片进行四刀切,从而将该图分成九个部分。而每个部分都被称为切片,和border-image类似,它可以被缩放、拉伸以适应整个遮罩区域。

先来看mask-border语法:

mask-border: <'mask-border-source'> || <'mask-border-slice'> [ / <'mask-border-width'>? [ / <'mask-border-outset'> ]? ]? || <'mask-border-repeat'> || <'mask-border-mode'>

mask类似,接下来花点时间来看看mask-border中包含的每个部分具体使用规则。

mask-border-source

mask-border-source类似于border-image-source,即mask-border-image。它的使用和mask-image类似,引用遮罩图片,或者使用渐变来绘制图片:

mask-border-image: url(border-mask.png);
mask-border-image: none;
mask-border-image: linear-gradient(black, transparent); 

mask-border-slice

mask-border-slice类似于border-image-slice,指定你在mask-border-image引用的遮罩图片切分位置:

mask-border-slice: 	[<number> | <percentage>]{1,4} fill?

mask-border-slice会指定遮罩图像上、右、下和左边缘的内偏移量,会将图像分割成九个区域。

如果未显式设置fill关键词,那么切分出来的图像的正中间部分将会被丢弃,并作为完全不透明的白色处理,即中间部分覆盖的内容不会被遮罩图像遮盖(也就是可见)

使用mask-border-slice可以设置{1,4}个值(可以是1234):

/* 四边切分的位置相同 */
mask-border-slice: 30%;

/* 第一个值表示上下切分位置,第二个值表示左右切分位置 */
mask-border-slice: 10% 30%;

/* 第一个值表示上边切分位置,第二个值表示左右切分位置,第三个值表示下边切分位置 */
mask-border-slice: 30 30% 45;

/* 第一个值表示上边切分位置,第二个值表示右边切分位置,第三个值表示底边切分位置,第四个值表示左侧切分位置 */
mask-border-slice: 7 12 14 5; 

/* 显式使用了fill关键词 */
mask-border-slice: 10% fill 7 12;

mask-border-width

mask-border-widthborder-image-width类似,简单点说就是用来设置遮罩边框的可见区域,也就是说这个区域内的元素内容是不可见的。更有点类似border-width,其具体的使用如下:

mask-border-width: [ <length> | <percentage> | <number> | auto ]{1,4}

代码示例:

/* Keyword value */
mask-border-width: auto;

/* <length> value */
mask-border-width: 1rem;

/* <percentage> value */
mask-border-width: 25%;

/* <number> value */
mask-border-width: 3;

/* vertical | horizontal */
mask-border-width: 2em 3em;

/* top | horizontal | bottom */
mask-border-width: 5% 15% 10%;

/* top | right | bottom | left */
mask-border-width: 5% 2em 10% auto;

mask-border-outset

mask-border-outset是用来指定遮罩图像超出边框的区域。它同样接受{1,4}值:

mask-border-outset: [ <length> | <number> ]{1,4}

mask-border-repeat

mask-border-repeatborder-image-repeat类似,用于设置遮罩图像的一次铺方式,它可以接受stretchrepeatroundspace四个关键词,可以接受{1, 2}值:

  • 如果只指定一个值,表示四边平铺方式相同
  • 如果指定了两个值,第一个值将会用在顶边和底边;第二个值会用于左边和右边

为了更好的理解四个值不同的效果,我用一张图来向大家展示:

mask-border-mode

mask-border-modemask-mode类似,用来设置遮罩图片的遮罩模式。

mask-border-mode: luminance;
mask-border-mode: alpha;

简单地说,把border-image搞明白了,那么mask-border就不会有什么难度。

前面我们使用mask做了一个优惠卷的小示例,接下来同样的,咱们使用mask-border来做一个优惠卷的效果:

SVG中的<mask>

在介绍mask-image的时候,我们提到过,引用的遮罩图片的资源,可以是SVG的<mask>元素。有关于<mask>更详细的介绍,可以点击这里查阅。接下来,我们来看看在mask中怎么来引用<mask>元素定义的遮罩图像。

假设我们有一个使用SVG绘制的图形:

<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1558366503019" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1154" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M427.108713 450.712766c0-59.45269-48.368861-107.821551-107.824614-107.821551s-107.824614 48.368861-107.824614 107.821551 48.368861 107.824614 107.824614 107.824614 107.824614-48.368861 107.824614-107.824614z m-165.39682 0c0-31.744649 25.824494-57.569144 57.572206-57.569143s57.572206 25.824494 57.572206 57.569143c0 31.747712-25.824494 57.572206-57.572206 57.572207s-57.572206-25.824494-57.572206-57.572207z" p-id="1155"></path><path d="M971.934487 202.743106v595.846914c0 66.208956-52.065513 120.354026-116.381734 122.990991v-137.183437-114.737077c0-166.73521-135.946116-302.393434-302.681326-302.393434-1.822293 0-3.788532 0.024501-5.610824 0.076567-5.770084-17.481762-13.638102-34.063096-23.141589-49.471425 70.052616-3.666025 125.872971-61.807889 125.87297-132.760932 0-73.308242-59.664015-132.947755-132.969193-132.947755S384.059722 111.803032 384.059722 185.111273c0 10.131336 1.169943 19.983969 3.326068 29.46908a234.530633 234.530633 0 0 0-63.715937-8.799071c-21.062031 0-41.483963 2.80235-60.925838 8.021151a132.822185 132.822185 0 0 0 3.151495-28.69116c0-73.308242-59.639513-132.947755-132.947755-132.947755S0 111.803032 0 185.111273c0 70.110807 55.262948 127.67995 124.148683 132.574109-22.15847 35.842511-34.265233 78.043141-34.265232 123.177814v233.5322H250.281982l0.003062 0.615599c3.341381 163.847105 137.664278 296.464091 302.292366 296.464091l302.972281 0.358333c91.880316-2.664529 168.447247-79.32334 168.447246-173.243399V202.743106h-52.06245zM516.995227 102.415926c45.597138 0 82.695347 37.098209 82.695347 82.695347 0 45.600201-37.098209 82.69841-82.695347 82.69841s-82.695347-37.098209-82.695348-82.69841c0-45.597138 37.098209-82.695347 82.695348-82.695347zM50.252408 185.111273c0-45.597138 37.095146-82.695347 82.695347-82.695347 45.597138 0 82.695347 37.098209 82.695347 82.695347 0 45.600201-37.098209 82.69841-82.695347 82.69841-45.600201 0-82.695347-37.098209-82.695347-82.69841z m88.633878 440.281288v-184.529365c0-101.910584 82.94955-184.826444 184.863197-184.826444 77.841004 0 144.616555 48.368861 171.80394 116.635936a183.420675 183.420675 0 0 1 12.042447 48.868078 186.057641 186.057641 0 0 1 1.010684 19.172359c0 101.910584-82.912797 184.679436-184.823382 184.679436H138.886286z m161.654229 49.976767c-0.003063-0.140883-0.003063-0.973931-0.009188-0.973932h23.248782c129.62475 0 235.078852-104.679244 235.078852-234.307057 0-7.864955-0.376709-15.120437-1.130128-22.783256 132.148396 2.713532 239.580987 107.714357 246.4812 238.815318-34.26217-36.574491-82.934236-59.428189-136.886358-59.428188-103.463362 0-187.637982 84.20831-187.637982 187.674734 0 53.982749 22.945578 102.431239 59.559883 136.696472-130.788568-6.845084-235.473937-114.008159-238.705061-245.694091z m502.946726 247.102922h-139.544762c-74.193355-3.062677-134.001316-63.066649-134.001316-137.688779 0-75.755321 61.08816-137.578523 136.846543-137.578523 73.874837 0 133.63992 58.420568 136.702598 131.584864v143.682438z" p-id="1156"></path></svg>

效果如一下:

将上面的代码做一下下调整,把<path>放到一个带id名称的<mask>元素中:

<svg>
    <mask id="mask">
        <path d="M427.108713 450.712766c0-59.45269-48.368861-107.821551-107.824614-107.821551s-107.824614 48.368861-107.824614 107.821551 48.368861 107.824614 107.824614 107.824614 107.824614-48.368861 107.824614-107.824614z m-165.39682 0c0-31.744649 25.824494-57.569144 57.572206-57.569143s57.572206 25.824494 57.572206 57.569143c0 31.747712-25.824494 57.572206-57.572206 57.572207s-57.572206-25.824494-57.572206-57.572207z" p-id="1155"></path>
        <path d="M971.934487 202.743106v595.846914c0 66.208956-52.065513 120.354026-116.381734 122.990991v-137.183437-114.737077c0-166.73521-135.946116-302.393434-302.681326-302.393434-1.822293 0-3.788532 0.024501-5.610824 0.076567-5.770084-17.481762-13.638102-34.063096-23.141589-49.471425 70.052616-3.666025 125.872971-61.807889 125.87297-132.760932 0-73.308242-59.664015-132.947755-132.969193-132.947755S384.059722 111.803032 384.059722 185.111273c0 10.131336 1.169943 19.983969 3.326068 29.46908a234.530633 234.530633 0 0 0-63.715937-8.799071c-21.062031 0-41.483963 2.80235-60.925838 8.021151a132.822185 132.822185 0 0 0 3.151495-28.69116c0-73.308242-59.639513-132.947755-132.947755-132.947755S0 111.803032 0 185.111273c0 70.110807 55.262948 127.67995 124.148683 132.574109-22.15847 35.842511-34.265233 78.043141-34.265232 123.177814v233.5322H250.281982l0.003062 0.615599c3.341381 163.847105 137.664278 296.464091 302.292366 296.464091l302.972281 0.358333c91.880316-2.664529 168.447247-79.32334 168.447246-173.243399V202.743106h-52.06245zM516.995227 102.415926c45.597138 0 82.695347 37.098209 82.695347 82.695347 0 45.600201-37.098209 82.69841-82.695347 82.69841s-82.695347-37.098209-82.695348-82.69841c0-45.597138 37.098209-82.695347 82.695348-82.695347zM50.252408 185.111273c0-45.597138 37.095146-82.695347 82.695347-82.695347 45.597138 0 82.695347 37.098209 82.695347 82.695347 0 45.600201-37.098209 82.69841-82.695347 82.69841-45.600201 0-82.695347-37.098209-82.695347-82.69841z m88.633878 440.281288v-184.529365c0-101.910584 82.94955-184.826444 184.863197-184.826444 77.841004 0 144.616555 48.368861 171.80394 116.635936a183.420675 183.420675 0 0 1 12.042447 48.868078 186.057641 186.057641 0 0 1 1.010684 19.172359c0 101.910584-82.912797 184.679436-184.823382 184.679436H138.886286z m161.654229 49.976767c-0.003063-0.140883-0.003063-0.973931-0.009188-0.973932h23.248782c129.62475 0 235.078852-104.679244 235.078852-234.307057 0-7.864955-0.376709-15.120437-1.130128-22.783256 132.148396 2.713532 239.580987 107.714357 246.4812 238.815318-34.26217-36.574491-82.934236-59.428189-136.886358-59.428188-103.463362 0-187.637982 84.20831-187.637982 187.674734 0 53.982749 22.945578 102.431239 59.559883 136.696472-130.788568-6.845084-235.473937-114.008159-238.705061-245.694091z m502.946726 247.102922h-139.544762c-74.193355-3.062677-134.001316-63.066649-134.001316-137.688779 0-75.755321 61.08816-137.578523 136.846543-137.578523 73.874837 0 133.63992 58.420568 136.702598 131.584864v143.682438z" p-id="1156"></path>
    </mask>
</svg>

在实际使用的时候,可以像下面这样使用:

.mouse {
    mask: url(#mask);
}

看到的效果如下:

目前为止,仅只有Firefox才支持<mask>

Demo效果并不完美,小老鼠没有全部展示出来,具体原因还没查明

小结

今天花了很长的篇幅介绍了Masking相关的知识点。那么有关于CSS Masking Module Level 1规范中的两部分内容,ClippingMasking都介绍完了。虽然文章中提供了一些示例来演示如何使用。但我们还是应该更进一步的去探计,Clipping和Masking应该在什么样的场景之下使用更合适,如果您感兴趣的话,欢迎关注下一部分的相关更新,将会和大家一起探讨论怎么使用更为合适。

扩展阅读

有关于Clipping和Masking更多的介绍,还可以阅读下面这几篇文章: