clip-path

发现我的有道云笔记会过滤clip-path这个属性。所以迁移到到这里,并做了一些补充,毕竟blog不是note嘛。
裁剪元素,类似canvas的clip函数(不过canvas的简单些,只支持path)。
对于SVG中的表现恕在下才疏学浅,后续再研究。

语法

一共分为三种
<clip-source> | [ <basic-shape> || <geometry-box> ] | none

clip-source 提供一个url指向svg

新建一个svg的clipPath对象,他是一个心形的path(这里设置size为0)。当然你也可以提供一个外部的Url

1
2
3
4
5
6
<svg style="width:0;height:0;">
<clipPath stroke="blue" id="custom-demo-myPath" clipPathUnits="objectBoundingBox">
<path d="M0.5,1 C 0.5,1,0,0.7,0,0.3 A 0.25,0.25,1,1,1,0.5,0.3 A 0.25,0.25,1,1,1,1,0.3 C 1,0.7,0.5,1,0.5,1 Z" />
</clipPath>
</svg>
<div style="clip-path:url(#custom-demo-myPath);"></div>

使用一个形状以特定的盒子模型去裁剪

形状

矩形

语法:inset( <length-percentage>{1,4} [ round <'border-radius'> ]? )

以从(上5px, 右30px, 下0px, 左40px)开始的一个圆角为(上左10px, 上右25px, 下右50px, 下左200px)的一个圆角矩形进行clip(这里如果对比一下Firefox,你会发现Firefox有BUG,border-radius溢出,哈哈哈)

1
<div style="clip-path:inset(5px 30px 0 40px round 10px 25px 50px 200px);"></div>

语法:circle( [ <shape-radius> ]? [ at <position> ]? )

以半径为50%,圆心在(0px, 100px) 的一个做clip

1
<div style="clip-path:circle(25% at 0px 100px);"></div>
椭圆

语法:ellipse( [ <shape-radius>{2} ]? [ at <position> ]? )

以X半径为20%,Y半径为40%,圆中心为(50%, 75%)的一个椭圆进行clip

1
<div style="clip-path:ellipse(20% 40% at 50% 75%);"></div>
多边形与路径

语法(这个就和canvas的表现一致):polygon( <fill-rule>? , [ <length-percentage> <length-percentage> ]# )
fill-rule:非零环绕原则(nonzero)与奇偶环绕原则(evenodd)(投一波当初做分享做的demo,nonzero evenodd

以(20%, 0), (120%, 50%), (10%, 100%)三个点组成的多边形进行clip

1
2
<div style="clip-path:polygon(20% 0, 120% 50%, 10% 100%);"></div>
这里记得要这些点能组成多边形,所以至少需要3个

盒子模型 (这一部分请使用Firefox体验)

语法:<shape-box> | fill-box | stroke-box | view-box
其中shape-box<box> | margin-box
boxborder-box | padding-box | content-box
咱们这些后生仔对shape-box可能比较比较熟悉,其他三个是啥?

针对 HTML 元素的shape-box

针对shape-box部分使用一下css与html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.custom-demo-wrap_margin {
display: block;
border: 1px solid red;
font-size: 0;
width: 242px;
margin: 0 auto;
overflow: hidden;
}
.custom-demo-inner_margin {
display: inline-block;
width: 200px;
height: 200px;
margin: 20px;
padding: 15px;
border: 10px solid teal;
font-size: 24px;
word-wrap: break-word;
background: #eee;
}
1
<div class="custom-demo-wrap_margin"><!-- 将实例代码放置此处并内置1111111111111111111文本 --></div>

来个正常的<div class="custom-demo-inner_margin" style="clip-path:circle(50% at 50% 50%);"></div>
可以看到从border开始作为clip的图层范围

1111111111111111111
margin-box

包括margin,及把margin和考虑在clip图层的范围中,可以看到这个圆是从外部margin开始的。

1
<div class="custom-demo-inner_margin" style="clip-path:margin-box circle(50% at 50% 50%);"></div>
1111111111111111111
border-box

从border开始作为clip的图层范围,这也就是默认的模式

1
<div class="custom-demo-inner_margin" style="clip-path:border-box circle(50% at 50% 50%);"></div>
1111111111111111111
padding-box

从padding开始作为clip的图层范围,可以看到teal颜色的border已经没了

1
<div class="custom-demo-inner_margin" style="clip-path:padding-box circle(50% at 50% 50%);"></div>
1111111111111111111
content-box

从content开始作为clip的图层范围,可以看到Padding的空白也没了

1
<div class="custom-demo-inner_margin" style="clip-path:content-box circle(50% at 50% 50%);"></div>
1111111111111111111
针对svg对象

针对svg我们使用以下css与svg

1
2
3
4
5
6
7
8
.custom-demo-wrap_svg {
display: block;
border: 1px solid red;
font-size: 0;
width: 242px;
margin: 0 auto;
overflow: hidden;
}
1
2
3
4
5
6
7
<div class="custom-demo-wrap_svg">
<svg viewBox="0 0 240 240"> <!-- 让viewBox比实际大小多出上下左右各20px -->
<g class="<!-- 这里填入所用的clip-path的classname -->">
<rect stroke-width="15" stroke="rgba(37, 0, 128, 0.3)" fill="#eee" x="20" y="20" width="200" height="200"></rect>
</g>
</svg>
</div>

稍微注意一点就是,svg和canvas的stroke都是以画笔的中心定位的

fill-box

可以看到是从fill的#eee开始clip的

1
2
3
.custom-demo-wrap_svg_fill {
clip-path:fill-box circle(50% at 50% 50%);
}
stroke-box

可以看到是从stroke的rgba(37, 0, 128, 0.3)开始clip的

1
2
3
.custom-demo-wrap_svg_stroke {
clip-path:stroke-box circle(50% at 50% 50%);
}
view-box

可以看到是从view的240px开始clip的

1
2
3
.custom-demo-wrap_svg_view {
clip-path:view-box circle(50% at 50% 50%);
}

好了基本用法就到这里结束了。

花里胡哨

配上transition 就可以完成一些形状的过渡
注意哟:被剪切的是不会被hover的!

最简单的常用图形变换

1
2
.custom-demo-circle-animate-1 .custom-demo-inner{clip-path:circle(120%);transition: clip-path 0.3s}
.custom-demo-circle-animate-1:hover .custom-demo-inner{clip-path:circle(25%);}

高级一点的多边形变换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.custom-demo-circle-animate-2 .custom-demo-inner{
clip-path:polygon(
0 0, 0 100%, 30% 100%, 30% 70%, 30% 70%, 30% 0, 0 0,
30% 70%, 70% 70%, 70% 100%, 100% 100%, 100% 100%, 100% 50%, 100% 0,
100% 0%, 70% 0%, 70% 30%, 30% 30%
);
transition: clip-path 0.3s
}
.custom-demo-circle-animate-2:hover .custom-demo-inner{
clip-path:polygon(
0 0, 0 100%, 50% 100%, 50% 70%, 30% 70%, 30% 0, 0 0,
70% 100%, 100% 100%, 100% 30%, 70% 30%, 70% 100%,
70% 0, 100% 0, 100% 20%, 70% 20%, 70% 0, 70% 100%
);
}

引用

Author: PaulHan
Link: https://www.paulhan.cn/blog/2019/01/05/clip-path/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.