暗黑模式
裁剪和遮罩
前端教程SVG
裁剪(clipping)
<svg>
的内容如果超过了视口,超出的部分就不会被绘制(当 overflow=hidden 时),这就是一种 clipping,裁剪区域是一个矩形。 SVG 通过<clipPath>
元素达成任意形状的裁剪,而不局限于矩形。
<clipPath>
基本语法和示例
xml
<clipPath id="clipId" clipPathUnits="userSpaceOnUse">
...childElement
</clipPath>
<xx clip-path="url(#clipId)" />
1
2
3
4
2
3
4
chipPathUnits="userSpaceOnUse|objectBoundingBox"
子元素所使用的坐标系统,与前面学过 *Units 类似,默认 userSpaceOnUse- userSpaceOnUse:相对于整个 SVG
- objectBoundingBox:
<clipPath>
是一个 1×1 的方形,因此<clipPath>
内的元素使用的数值介于 0~1
- childElement 可以是:
- 形状元素,
<rect>
<circle>
<ellipse>
<polygon>
<path>
- 文本元素,
<text>
<use>
元素
- 形状元素,
下面的 codepen 列举了2个例子:
- 左图使用了
<polygon>
为三角形的<clipPath>
- 右图使用了
<text>
为“上海”的<clipPath>
裁剪函数
除了定义 <clipPath>
元素并通过 url()
来引用裁剪之外,SVG 也支持许多简写的裁剪函数:
circle()
圆形ellipse()
椭圆inset()
矩形polygon()
多边形path()
自定义路径
直接使用 CSS 的 property 来引用这些函数:
css
.someShape {
clip-path: path(...);
}
1
2
3
2
3
path()
函数只接受用户单位的坐标(不能是 cm/mm 这样的长度,也不能是百分比),其他函数没有此限制。circle()
和ellipse()
这两个函数不常用,因为我们可以使用border-radius
和overflow: hidden
来达成相同的果效
下面的 codepen 中示范了 polygon()
的用法:
- 上部分中:HTML的
<header>
,<header>:before
,<h1>
都应用了裁剪,所以可以看到3个重叠的裁剪区域; - 下部分中:SVG的
<image>
应用了同样的裁剪。 polygon(...)
使用了 CSScalc()
函数,因此可以实现响应式calc(100% -30px) 0
即 X 坐标是 100% width 减去 30,Y 坐标是 0;100% calc(100% -30px)
即 X 坐标是 100% width,Y 坐标是 100% height 减去 30;
遮罩(masking)
<clipPath>
的一个限制是:要么让某个区域显示、要么完全不显示,无法做到让某个区域按照需求透明化; opacity``fill-opacity
可以实现透明化,但是也有限制:只能对整个图形透明化,无法精确到细节; 此时我们需要用 <mask>
元素来达成按需透明化图形的效果:可以把 <mask>
元素当成一个灰度图来看,图中纯黑色 #000000
代表完全透明,纯白色 #FFFFFF
代表完全不透明。
基本语法和示例
xml
<mask id="myMask" maskUnits="" maskContentUnits="" x="" y="" width="" height="">
...childElement
</mask>
1
2
3
2
3
maskUnits="userSpaceOnUse | objectBoundingBox"
定义了x
y
width
height
所使用的坐标系统,默认 objectBoundingBox- objectBoundingBox 定义
<mask>
为 1×1 的方形 - userSpaceOnUse 相对于整个 SVG
- objectBoundingBox 定义
maskContentUnits="userSpaceOnUse | objectBoundingBox"
定义了<mask>
内部元素所使用的坐标系统,默认 userSpaceOnUse- objectBoundingBox 定义
<mask>
为 1×1 的方形 - userSpaceOnUse 相对于整个 SVG
- objectBoundingBox 定义
x
y
定义了<mask>
元素的左上角坐标,默认(-10%, -10%)width
height
定义了<mask>
元素的宽高,默认都是 120%
通过下面的 codepen 来实际感受一下:
- 左图:原始图片
- 中间图:背景色为径向渐变的矩形,中间区域完全白色,代表完全不透明,向外逐渐变为黑色,代表逐渐透明直至完全不显示;此例中的
<mask>
就用这个矩形来作为灰度图使用; - 右图:原始图片 +
<mask>
合成的图片
双色调图片
什么是双色调(或多色调)?大家可以参考这个教程了解一下,我们使用 SVG <mask>
实现与教程里类似的效果:
你也可以通过以下的 codepen 来交互操作、感受<mask>
实现双色调图片的原理:
CSS mask
CSS Masking 模块引入了更加精简的遮罩语法:mask
mask-image
mask-mode
mask-size
mask-composite
,然而目前主流浏览器尚未支持~~;
更多请参考 MDN - mask
小结
本节我们讲解了 SVG 中如何实现裁剪和遮罩,下一节我们介绍 filters(滤镜) 和 blend(混合)。