CSS的mask
(遮罩),有时也称CSS的蒙层,最早是苹果公司2008年提出的,并且添加到webkit
引擎当中。遮罩提供一种基于像素级别的,可以控制元素透明度的能力,类型于png24
位或png32
位中的alpha
透明通道的效果。2012年被纳入到W3C的草案中,但这个版本与苹果公司提出的版本是不同的。时至今日,该规范已经有多个版本,现在是CSS Masking Module Level1版本,属于TR阶段。据Caniuse.com统计来讲,该属性得到的支持度还是有一定的限制,仅部分属性被浏览器支持。虽然如此,但该属性还是非常的有意思,值得大家花点时间去探究,比如今天要聊的mask-composite
属性就是非常有意思的一个属性。
mask
原理和语法
文章开头也提到过,mask
提供一种基于像素级别的,可以控制元素透明度的能力,类似于png24
位或png32
位中alpha
透明通道的效果。
图像是由RGB
三个通道以及在每个像素上定义的颜色组成的。但是在他们之上还有第四个通道,即alpha
通道。通过高度定义每个像素上的透明度。白色意味着不透明,黑色意味着透明,介于黑白之间的灰色表示半透明。比如下图:
给一个HTML元素使用CSS的mask
属性,就会这样处理。不用给图片应用一个alpha
通道,只需要给一个图片运用一个mask-image
或mask-border-source
的样式:
mask-image: url(mouse.png)
他从图片遮罩里读出图片的透明信息,然后应用到HTML元素上,比如下图这个效果:
遮罩可以让头像按照特定形状显示。
CSS遮罩可以使得图片按照任意的形状显示。或者你可能有很长的文本需要滚动显示,那么可以使用遮罩让他从不透明到透明的渐变显示。
在使用mask
的时候,其中有一个不可或缺的部分就是遮罩(也被称为蒙板),该遮罩可以是半透明的PNG图片、CSS的渐变或SVG元素,遮罩元素的alpha
值为0
的时候会覆盖下面的元素,为1
的时候会完全显示下面的内容。如下图所示:
而使用CSS的mask
也并不太复杂,其语法规则和background
非常的类似。在W3C官网上提供了两者相关属性的对照表:
mask 属性 | background 属性 |
---|---|
mask-clip | background-clip |
mask-image | background-image |
mask-origin | background-origin |
mask-position | background-position |
mask-repeat | background-repeat |
mask-size | background-size |
mask-mode | |
mask-composite | |
background-attachment | |
background-color |
具体的语法规则:
mask: <mask-layer>
其<mask-layer>
对应的值:
<mask-layer> = <mask-reference> <masking-mode>? || <position> [ / <bg-size> ]? ||
<repeat-style> || <geometry-box> || [ <geometry-box> | no-clip ] || <compositing-operator>
即:
mask: [mask-image] [mask-repeat] [mask-position] / [ mask-size]
和background
属性类似,建议mask-size
单独写出来:
mask: [mask-image] [mask-repeat] [mask-position]
mask-size: [mask-size]
上面我们列出的的仅是mask
部分属性,在规范中还提供了其他的属性,这几个属性有点类似于CSS中的border
属性,比如mask-border-source
、mask-border-mode
、mask-border-slice
、mask-border-width
、mask-border-outset
、mask-border-repeat
、mask-border
等。另外还可以用于SVG,比如mask-type
。
上面简单的介绍了CSS中mask
的基本原理和使用规则,但我们今天的重点并不是来了解所有的属性,而是针对性的学习其属性之一,即mask-composite
属性。如果你想了解更多有关于mask
相关的知识,建议你花点时间阅读下列文章:
- 如何在CSS中使用遮罩
- CSS遮罩CSS3 mask/masks详细介绍
- CSS3 Mask 安利报告
- A Comprehensive Guide to Clipping and Masking in SVG
- CSS中的剪裁和遮罩
- 打破盒子模式的限制,使用Clip-Path创建响应式图形
mask-composite
mask-composite
仅是CSS的mask
的子属性之一。该属性的工作原理是什么?它有什么用?使用它的价值是什么?
如果将上述问题一一答出来之后,可以彻底让我们掌握mask-composite
的原理和使用方式。@Ana Tudor新出的博文《Mask Compositing: The Crash Course》就详细介绍了这些,也称得上是mask-composite
速成记。
特别声明,接下来的内容和图片资源来自于@Ana Tudor的《Mask Compositing: The Crash Course》一文!在此特别感谢@Ana Tudor为我们提供这么优秀的教程。
什么是遮罩合成
遮罩合成指的是我们可以使用不同的操作将多个不同的遮罩层合并成一个独立的遮罩层。那么问题来了?多个遮罩层是如何合并成一个呢?比如我们有两个遮罩层,在这两个遮罩层中取每对对应的像素,在它们的通道上应用特定的合成操作(具体合成的操作细节,后面会介绍),并为最终层获得第三个像素。如下图所示:
上图中左上图和左下图合层起来成了右侧的层。而左上图被称为源(Source),左下图被称为目标层(Destination),这对地我们来说没有多大的意义,因为给我的感觉一个是输入源,一个是输出结果(事实上,这两个都是输入),但是,就上图的结果而言,这两个层(源和目标层)却做了一个合层的操作(也被称为合层计算),从而得到最终的结果(上图右侧的合并层)。
上面演示的是仅有两个层合并,而事实上呢?我们可能会有两个以上的层合并,当有这种情形时,合层是分阶段完成的,从底部开始。
在第一阶段,从底部开始的第二层是源,从底部开始的第一层是目标,这两层被合层,结果成为第二阶段的目标,接着和从底部开始的第三层(源)合并。通过合成前两层的结果合成第三层,我们就得到了第三阶的目标,接着再从底部的第四层源合并。如下图这样的一个合并过程:
以此类推,直到我们达到最后一个阶段,在这里,最顶层由下面所有层的合成结果组成。
遮罩合成有什么用?
CSS和SVG的遮罩都有各自的局限性和优缺点。我们可以通过使用CSS遮罩来绕过SVG遮罩的限制,但是,由于CSS的遮罩和SVG遮罩的工作方式不同,采用CSS遮罩我们无法在不进行合成的情况下实现某些结果。
为了更好地理解这一切,让我们来看看下面这张令人敬畏的西伯利亚小老虎的图片:
假设我们使用遮罩期望得到的效果如下图所示:
这个特殊的mask
保持了菱形的可见性,而分隔它们的线被遮罩,我们可以通过图像看到后面的元素。
我们希望这种遮罩效果是灵活的。我们不希望与图像的尺寸或长宽比绑定,我们希望能够轻松地随图像缩放和不缩放的mask
之间进行切换(只需要将%
值更改为px
)。
为了做到这一点,我们首先需要了解SVG和CSS的遮罩是如何工作,以及我们可以和不可以使用它们做什么。
SVG遮罩
SVG遮罩默认情况下是亮度(luminance
)遮罩。这意味着遮罩元素上白色像素部分是完全不透明,而黑色像素部分是完全透明的,而遮罩元素白色和黑色像素之间的亮度(grey
、pink
和lime
)是半透明的。
给定RGB值对应亮度的计算公式为:
.2126·R + .7152·G + .0722·B
。
对于我们这个示例,这意味着我们需要将菱形区域变成白色,分隔线是黑色,如下图所示:
为了得到上图的效果,使用SVG的rect
绘制一个纯白色的矩形,然后使用path
在这个矩形中添加两条黑色的对角线(确保stroke
的值为black
)。
先创建第一条对角线(从左上角到右下角),在左上角使用M
命令,然后在右下角使用L
命令;接着创建第二条对角线(从右上角到左下角),在右上角使用M
命令,然后在左下角使用L
命令。对应的SVG代码如下:
<svg viewBox="0 0 837 551" width="837" height="551">
<rect width="837" height="551" fill="#fff"></rect>
<path d="M0 0 L837 551 M837 0 L0 551" stroke="#000"></path>
</svg>
得到的效果如下图所示,但离我们想要的菱形图案的效果还相差很远。
我们可以使用stroke-width
来改变线条的粗细,然后使用stroke-dasharray
属性来改变线条之间的间距:
<svg viewBox="0 0 837 551" width="837" height="551">
<rect width="837" height="551" fill="#fff"></rect>
<path d="M0 0 L837 551 M837 0 L0 551" stroke="#000" stroke-width="15%" stroke-dasharray="1% 4%"></path>
</svg>
我们可以继续增大stroke-width
的值到150%
,最终效果会覆盖整个矩形,而且离我们想要的效果越来越近了:
现在,我们可以将rect
和path
元素封装在一个mask
元素中,并将这个遮罩应用于我们想要的任何元素上,比如我们这个示例中,就是小老虎的img
。
<svg viewBox="0 0 837 551">
<mask id="m">
<rect width="837" height="551" fill="#fff"></rect>
<path d="M0 0 L837 551 M837 0 L0 551" stroke="#000" stroke-width="15%" stroke-dasharray="1% 7%"></path>
</mask>
</svg>
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/2017/amur_tiger_cub_buffalo_zoo.jpg" width="837"/>
img {
mask: url(#m)
}
上述方法应该是有效的。但遗憾的是,效果并不是我们期许的一样。在Firefox中得么的效果是我们期望的,而在Chrome中并不是我们想要的效果,甚至应用该遮罩之后(mask
添加-webkit
前缀),元素(img
)消失了。
如果我们希望在Chrome浏览器中也能得到我们期望的效果,最简单的做法就是把img
元素放在SVG中,使用image
元素来替代:
<svg viewBox="0 0 837 551" width="837">
<mask id="m">
<rect width="837" height="551" fill="#fff"></rect>
<path d="M0 0 L837 551 M837 0 L0 551" stroke="#000" stroke-width="150%" stroke-dasharray="1% 7%"></path>
</mask>
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/2017/amur_tiger_cub_buffalo_zoo.jpg" width="837" mask="url(#m)"></image>
</svg>
得到的效果和我们期望的很相似了:
虽然得到我们想要的效果,但如果我们想屏蔽另一个HTML元素,而不是img
元素,事情就会变得有点复杂,因为我们需要将它放在SVG的foreignObject
中。
更糟糕的是,使用这个解决方案,我们要对维度进行硬编码,这令人非常恶心心。我们可以尝试通过maskContentUnits
切换到objectBoundingBox
:
<svg viewBox="0 0 837 551" width="837">
<mask id="m" maskContentUnits="objectBoundingBox">
<rect width="1" height="1" fill="#fff"></rect>
<path d="M0 0 L1 1 M1 0 L0 1" stroke="#000" stroke-width="1.5" stroke-dasharray=".01 .07"></path>
</mask>
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/2017/amur_tiger_cub_buffalo_zoo.jpg" width="100%" mask="url(#m)"></image>
</svg>
但我们仍然在viewBox
中硬编码尺寸大小,虽然它们的实际值并不重要,但它们的长宽比很重要。此外,我们的遮罩模式现在是在1x1
正方形内创建的,然后拉伸到覆盖mask
元素。形状拉伸意味着形状的扭曲,这就是为什么我们的菱形不再像以前那样了。
我们可以尝试调整path
的起点和终点:
<svg viewBox="0 0 837 551" width="837">
<mask id="m" maskContentUnits="objectBoundingBox">
<rect width="1" height="1" fill="#fff"></rect>
<path d="M-.75 0 L1.75 1 M1.75 0 L-.75 1" stroke="#000" stroke-width="1.5" stroke-dasharray=".01 .07"></path>
</mask>
<image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/2017/amur_tiger_cub_buffalo_zoo.jpg" width="100%" mask="url(#m)"></image>
</svg>
也就是说,要得到一个特定的菱形图案,就需要知道菱形的角度,也就需要知道图像的长宽比。
上面我们看了SVG中遮罩是如何工作的,我们接着来看看CSS中的遮罩是怎么做的。
CSS遮罩
CSS遮罩默认情况下是alpha
遮罩。这意味着,完全不透明遮罩像素对应的是遮罩元素像素完全不透明,完全透明遮罩像素对应的是遮罩元素像素完全透明,半透明遮罩像素对应的是遮罩元素的像素是半透明的。简单地说,遮罩元素的每个像素将获得对应遮罩元素像素的alpha
通道。
就我们示例而言,菱形区域是不透明的,而分隔它们的线是透明的。在SVG中使用path
绘制菱形,而在CSS中,我们可以使用CSS渐变来绘制菱形。为了得到白色菱形区域和黑色分隔线的图案,可以使用两个repating-linear-gradient
来绘制:
关键代码如下:
repeating-linear-gradient(-60deg, #000 0, #000 5px, transparent 0, transparent 35px),
repeating-linear-gradient(60deg, #000 0, #000 5px, #fff 0, #fff 35px)
如果我们也想要一个亮度(luminance
)的遮罩,那么这个模式就会起作用。
但在alpha
遮罩的例子中,并不是黑色的像素给了我们完全的透明度,而是透明的像素;并不是白色像素让我们完全不透明,而是完全不透明的像素。其中red
、black
和white
都做同样的事情,但我从此人更倾向于使用red
或tan
,因为这意味着只需要输入三个字母,输入的字母更少,出错的机会也就更少。
首先想到的是使用同样的技术得到不透明的菱形区域和透明的分隔红玫瑰。但是这样做的时候,我们遇到了一个问题:第二层渐变层的不透明部分覆盖了第一层部分,但我们希望仍然要保持透明,反之亦然。
我最初的想法是使用带有白色菱形区域和黑色分隔线的模式,结合设置mask-mode
的值为luminance
,让CSS遮罩像SVG遮罩一样工作来解决。
div {
background: repeating-linear-gradient(60deg, #000 0, #000 0.5em, transparent 0, transparent 1.5em), repeating-linear-gradient(-60deg, #000 0, #000 0.5em, #fff 0, #fff 1.5em);
}
div:nth-child(2) {
background: repeating-linear-gradient(60deg, #fff 0, #fff 0.5em, transparent 0, transparent 1.5em), repeating-linear-gradient(-60deg, #fff 0, #fff 0.5em, #000 0, #000 1.5em);
}
div:nth-child(n + 3) {
background: linear-gradient(white, dimgrey);
--m: repeating-linear-gradient(60deg, #000 0, #000 0.5em, transparent 0, transparent 1.5em), repeating-linear-gradient(-60deg, #000 0, #000 0.5em, #fff 0, #fff 1.5em);
-webkit-mask: var(--m);
mask: var(--m);
mask-mode: luminance;
mask-source-type: luminance;
}
div:nth-child(4) {
--m: repeating-linear-gradient(60deg, #fff 0, #fff 0.5em, transparent 0, transparent 1.5em), repeating-linear-gradient(-60deg, #fff 0, #fff 0.5em, #000 0, #000 1.5em);
}
此属性仅得到Firefox的支持,下图是Firefox和Chrome两个浏览器的效果:
幸运的是,mask-composite
可以实现我们想要的效果。接下来我们来看看这个属性可以取什么值以及它们各自有什么效果?
mask-composite
的值及其作用
首先为mask
提供了两个渐变的遮罩层(好比文章最开始展示的左侧图)和一张图片(比如小老虎图片)。接下来使用这两个渐变遮罩层来说明mask-composite
属性有哪些值,每个值是如何工作的,如下:
--l0: repeating-linear-gradient(90deg, red, red 1em, transparent 0, transparent 4em);
--l1: linear-gradient(red, transparent);
mask: var(--l1) /* 顶部层(源) */,
var(--l0) /* 底部层(目标) */
这两个渐变层的效果如下所示:
--l1
是源,--l0
是目标。我们将这个遮罩运用在下面这张老虎图上。
接下来看看mask-composite
值带来的效果。
add
add
是mask-composite
的初始值(initial
),和mask-composite
不显式设置值起到的效果相同。在本例中所发生的是将渐变添加到另一个渐变之上,并生成新的遮罩层。
注意,在半透明遮罩层的情况下,不只是简单地添加alpha
,不管值的名称是什么。相反,使用下列公式,α₁
是顶部层(源),α₀
是底部层(目标):
α₁ + α₀ – α₁·α₀
如果至少有一个遮罩层是完全不透明的(它的alpha
值是1
),那么得到的遮罩就是完全不透明的,并爱理不理遮罩元素的相应像素显示为完全不透明(alpha
值为1
)。
如果顶层(源)是完全不透明的,即α₁
的值是1
,如果把该值替换到上面的公式中:
1 + α₀ - 1·α₀ = 1 + α₀ - α₀ = 1
相应的,底层(目标)也是完全不透明的,即α₀
的值是1
,同样把该值替换到上面的公式中:
α₁ + 1 – α₁·1 = α₁ + 1 – α₁ = 1
当两个遮罩层都是完全透明的(它的alpha
的值为0
),得到的遮罩就是完全透明的,因此遮罩元素的相应像素也是完全透明的(alpha
值为0
)。
0 + 0 – 0·0 = 0 + 0 + 0 = 0
下图中,我们可以看到这对于我们正在使用的遮罩图层意味着什么 —— 通过合成得到的图层是什么样子的,以及将它应用到老虎图片上最图得到的效果:
subtract
该值的意思即是从源(顶层)中减去目标(底层)。mask-composite
取值为subtract
时,两个遮罩层合成在一起的计算公式是:
α₁·(1 – α₀)
上面的公式可以得知,任何与0
相乘的结果都是0
。无论源(顶层)是完全透明的,还是目标层(底层)是完全不透明的,得到的遮罩层也是完全透明的,遮罩元素的相应像素也是完全透明的。
如果源(顶层)是完全透明的,则将公式中的α₁
替换为0
,得到的值为:
0·(1 – α₀) = 0
如果目标(底层)是完全不透明的,则将公式中的α₀
替换为1
,得到的值为:
α₁·(1 – 1) = α₁·0 = 0
得到的效果如下:
注意,在本例中,这个价值观式不是对称的,除非α₁
和α₀
是相等的。另外α₁·(1 – α₀)
和α₀·(1 – α₁)
不相同,如果我们交换两个遮罩层,得到的效果将会不一样。
intersect
mask-composite
取值为intersect
时,对应的公式是两个alpha
值相乘:
α₁·α₀
上面公式得到的结果是,无论哪个遮罩层是完全透明的(alpha
值为0
),计算出来的遮罩层也是完全透明的,遮罩元素的相应像素也是完全透明的。
如果源(顶层)是完全透明的,那么α₁
的值为0
,将该值替换到上面的公式中,得到的结果是:
0·α₀ = 0
如果目标(底层)是完全透明的,那么α₀
的值为0
,将该值替换到上面的公式中,得到的结果同样也是0
:
α₁·0 = 0
另外,如果两个遮罩层都是完全不透明的(它们的alpha
值为1
),那么计算出来的遮罩层就是完全不透明的,遮罩元素的相应像素也是完全不透明的。这是因为α₁
和α₀
的值都是1
,将这两值运用到上面的公式中,得到的结果是1
:
1·1 = 1
mask-composite:intersect
得到的效果如下图所示:
exclude
mask-composite
取值为exclude
时,两个遮罩层是互斥的,合并遮罩层对应的公式为:
α₁·(1 – α₀) + α₀·(1 – α₁)
实际上,这个公式意味着,无论两个遮罩层都是完全透明的(alpha
的值是0
)或完全不透明(alpha
的值是1
),计算出来的遮罩都是完全透明的。遮罩元素的相应像素也是完全透明的。
如果两个遮罩层都是完全透明的,那么α₁
和α₀
的值都是0
,将该值相应替换到上面的公式中得到的结果是0
:
0·(1 – 0) + 0·(1 – 0) = 0·1 + 0·1 = 0 + 0 = 0
如果两个遮罩层都是完全不透明的,那么α₁
和α₀
的值都是1
,将该值相应替换到上面的公式中得到的结果也是0
:
1·(1 – 1) + 1·(1 – 1) = 1·0 + 1·0 = 0 + 0 = 0
它也意味着,只要有一个层是完全透明(alpha
值为0
),而另一层是完全不透明(alpha
值为1
),那么计算出来的遮罩层就是完全不透明的,遮罩元素的相应像素也是完全不透明的。
如果源(顶层)完全透明,而目标(底层)完全不透明,那么α₁
和α₀
对应的值分别是0
和1
:
0·(1 – 1) + 1·(1 – 0) = 0·0 + 1·1 = 0 + 1 = 1
如果源(顶层)完全不透明,而目标(底层)完全透明,那么α₁
和α₀
对应的值分别是1
和0
:
1·(1 – 0) + 0·(1 – 1) = 1·1 + 0·0 = 1 + 0 = 1
mask-composite:exclude
对应的效果如下:
实例
回到上面,采用两个渐变绘制出来想要的菱形图形:
--l1: repeating-linear-gradient(-60deg, transparent 0, transparent 5px, tan 0, tan 35px);
--l0: repeating-linear-gradient(60deg, transparent 0, transparent 5px, tan 0, tan 35px)
如果我们将完全不透明(示例中tan
)的部分设置为半透明(rgba(tan, .5)
),那么视觉效果就会告诉我们如何进行合成:
$c: rgba(tan, .5);
$sw: 5px;
--l1: repeating-linear-gradient(-60deg, transparent 0, transparent #{$sw}, #{$c} 0, #{$c} #{7*$sw});
--l0: repeating-linear-gradient(60deg, transparent 0, transparent #{$sw}, #{$c} 0, #{$c} #{7*$sw})
html {
height: 100vh;
background: var(--l1), var(--l0);
}
得到的效果如下:
我们要研究的菱形区域是在半透明条带的交点处形成的。这意味着使用mask-composite:intersect
可以达到我们想要的效果:
$sw: 5px;
--l1: repeating-linear-gradient(-60deg, transparent 0, transparent #{$sw}, tan 0, tan #{7*$sw});
--l0: repeating-linear-gradient(60deg, transparent 0, transparent #{$sw}, tan 0, tan #{7*$sw});
mask: var(--l1) intersect, var(--l0)
这不仅给了我们想要的结果,而且,将透明宽度存储到一个变量中,那么将这个值更改为%
值(假设$sw:.05%
)将使遮罩和图像一起缩放。
如果透明条的宽度是px
值,那么菱形和分隔线的大小都保持不变,因为图像会随着视窗进行缩放。
如果透明条宽度是%
值,那么菱形和分隔红玫瑰的大小都与图像相关,因此可以随着图像大小进行缩放。
到目前为止,只有Firefox只支mask-composite
。但值得庆幸的是,webkit
内核提供了一个可替代方案。
扩展支持
webkit
内核浏览器使用mask-composite
需要添加相应的前缀,而且它需要不同的值才能正常工作:
source-over
等价于add
source-out
等价于subtract
source-in
等价于intersect
xor
等价于exclude
大家可能会想,只需要额外添加一个webkit
版本即可,对吧?事实并没那么简单。首先,我们不能在-webkit-mask
简写中使用这个值,比如说,下面的方法是不会起作用的:
-webkit-mask: var(--l1) source-in, var(--l0)
如果要它们起作用,需要把mask-composite
单独拿出来,如下:
-webkit-mask: var(--l1), var(--l0);
-webkit-mask-composite: source-in;
mask: var(--l1) intersect, var(--l0)
整个图像完全消失了!
如果你觉得这很奇怪,请检查一下,使用其他三种操作的任何一种,在Webkit内核的浏览器和Firefox中都能得到预期的结果,只有source-in
才会破坏Webkit内核浏览器中的东西:
add
/source-over
subtract
/source-out
exclude
/xor
我们也可以把α₀
取值为0
,可以得到上面三个值得到的最终值是α₁
:
add
/source-over
:α₁ + 0 – α₁·0 = α₁ + 0 - 0 = α₁
subtract
/source-out
:α₁·(1 – 0) = α₁·1 = α₁
exclude
/xor
:α₁·(1 – 0) + 0·(1 – α₁) = α₁·1 + 0 = α₁
然而,与空无一物相交则是另一回事。与虚无相交就是虚无!这也说明 intersect
或source-in
操作中可以将α₀
设置为0
:
α₁·0 = 0
在这种情况之下,结果层的alpha
值是0
,这也就是图像完全被遮上的原因所在。针对这个现象,想到的第一个修复是使用另一种操作来合成底部的层:
-webkit-mask: var(--l1), var(--l0);
-webkit-mask-composite: source-in, xor;
mask: var(--l1) intersect, var(--l0)
这种方法确实有效。最终我们示例的结果如下:
有关于mask-composite
的Demo效果除了上面文章中提到的案例之外,在Codepen上还有很多类似的案例,如果感兴趣的话可以猛击这里。
最后再次感谢@Ana Tudor为我们提代这么优秀的教程:《Mask Compositing: The Crash Course》!
小结
这篇文章简单的介绍了CSS中mask
的基本原理和使用方法,但是大部分内容介绍了mask-composite
属性的使用。通过该文的学习,可以深入的了解到该属性的每个值,以及每个值的计算公式。而且每个属性值所起的效果不同之处。感兴趣的同学,可以自己动手撸几个Demo,如果您在这方面有更好的建议或经验,欢迎在下面的评论中与我们一起分享。文章中有关于mask-composite
的原理和公式来自于@Ana Tudor的《Mask Compositing: The Crash Course》一文。最后再次感谢@Ana Tudor为我们提供这么优秀的教程。