分享一个 offset-path 新特性
大家有使用过offset-path吗?没用过不要紧,相信大家都见过这种酷炫的路径动画,这种就可以用offset-path来实现。
随着 CSS的不断发展,最近在Chrome 116中,offset-path也支持基本形状了,也就是常见的inset、circle、polygon等等,有了这些形状的支持,路径动画写起来更加方便了,一起了解一下吧。
一、过去仅支持 path
先简单介绍一下offset-path的用法。offset-path是用来实现路径动画的,所以前提是需要准备好路径。这里的路径可以在支持 SVG的设计软件中绘制,比如Figma。
这是我用钢笔工具随便勾勒的一条路径,先准备好放在一边。
现在来一点布局。
我们用伪元素来作为偏移路径的元素。
.con{
position: relative;
width: 300px;
height: 200px;
background-color: #FFEFC5;
border-radius: 8px;
flex-shrink: 0;
}
.con::before{
position: absolute;
content: '😁';
width: 40px;
height: 40px;
border-radius: 8px;
display: grid;
place-content: center;
background-color: #3E65FF;
color: #fff;
z-index: 2;
}
现在效果如下:
没什么特别的,我们现在加上offset-path,如何添加呢?我们需要一段path路径,刚才我们在Figma上绘制的图形,可以直接导出SVG。
可以得到这样一段代码。
我们只需要将path里面的d属性值拿出来就行了,就像这样。
.path::before{
offset-path: path("M16 39.567C36.479 34.0777 82.9341 33.7783 104.922 76.4954C132.407 129.892 117.317 157.339 192.766 154.844C253.126 152.848 280.072 87.1417 286 54.5383")
}
现在效果如下:
为啥是歪的呢?这是因为路径的起始位置就是这样,我们可以把这个 SVG 也放到 html 中,顺便改一下描边。
刚好位于起点处。
现在我们给个动画,让它从起点运动到终点,只需要改变offset-distance就行了。
.con::before{
animation: offset 3s linear infinite;
}
@keyframes offset {
to {
offset-distance: 100%;
}
}
这样就得到了一个最基础的路径动画了。
是不是非常简单呢?
二、path 的局限性
前面的path虽然灵活,但是不好维护,而且一些基本形状也必须要转成path才行。
比如,要沿着一个圆形来运动,我们可以在Figma中绘制一个圆。
如果我们直接复制这个SVG会得到这样一段代码。
Figma还是挺聪明的,自动识别到了这是一个圆,所以得到了circle这个标签。但这种结构之前是无法使用的,我们需要的是path,因此要转一下。
在Figma中,可以用Flatten将图形“扁平化”,也就是让这个形状失去基本形状特性,变成一个普通的路径。
这样我们就能得到带path的SVG代码了。
然后用在offset-path中。
.path::before{
offset-path: path("M200 100C200 155.228 155.228 200 100 200C44.7715 200 0 155.228 0 100C0 44.7715 44.7715 0 100 0C155.228 0 200 44.7715 200 100Z")
}
虽然也能实现,但是一眼看上去,完全不知道是什么形状。
其次,path还有一个问题,就是不支持自适应尺寸,因为里面的值都是固定的,无法动态去改变,比如我们希望这个圆能尽可能大的撑满整个容器,path就无法实现这样的效果。
因此,为了解决这样的问题,现在也支持基本形状了。
三、现在支持基本形状了
所谓基本形状,就是一种表现基础图形的 CSS 数据类型,适用于clip-path、shape-outside和offset-path。
https://developer.mozilla.org/en-US/docs/Web/CSS/basic-shape
其实就是这几类
- 圆 circle()
- 椭圆 ellipse()
- 矩形 inset()、rect()、xywh()
- 多边形 polygon()
这里面有些大家可能已经在clip-path中用到过了,所以这里不会详细介绍每个语法的详细用法,有兴趣可以在官网自行查看。
1. circle
首先来看圆。语法很简单。
circle( ? [ at ]? )
前面的shape-radius是圆的半径,可以是长度单位或者百分比,还支持closest-side和farthest-side关键词,后面的position表示圆心位置(默认居中)。
offset-path: circle(50px);
offset-path: circle(20% at right center);
offset-path: circle(closest-side);
offset-path: circle(farthest-side);
其中,closest-side表示距离边缘「最近」时的半径,farthest-side表示距离边缘「最远」时的半径,这一点和径向渐变中是类似的。
实际使用来看看,还是上面的结构。
给伪元素一个offset-path。
.circle::before{
offset-path: circle();
animation: offset 3s linear infinite;
}
效果如下:
而且这个路径是自适应的,可以自动跟随外部容器的变化而变化,比如将这个高度改小一些。
是不是比path实现要灵活很多呢?
2. ellipse
椭圆和圆比较类似,只是多了一个半径,就不赘述了。
ellipse( [ {2} ]? [ at ]? )
我们直接看代码。
.ellipse::before{
offset-path: ellipse();
animation: offset 3s linear infinite;
}
效果如下:
3.inset
inset表示矩形,并且支持圆角。
inset( {1,4} [ round <`border-radius`> ]? )
前面有 4 个值,分别表示距离上、右、下、左的距离,如下:
并且支持圆角,这样要实现一个圆角矩形的路径动画就很方便了。
.inset::before{
offset-path: inset(20px round 16px);
}
效果如下:
还有两个函数,rect()和xywh()也能实现矩形,只是方式不一样,这个以后再做介绍。
4. polygon
这个相信大家都很熟悉了,用来绘制多边形的。
比如我们要绘制一个三角形,只需要指定三个点就行了,如下:
在offset-path中也是如此。
.polygon::before{
offset-path: polygon( 50% 0,100% 100%, 0 100%);
}
效果如下:
5.其实也还支持 url
顺便介绍一下,和基本形状同时推出的还有 url()支持(和 clip-path 一样)。 可以直接用一段 svg作为路径偏移,更加直观。比如在 Figma 中绘制一个五角星。
我们直接复制出SVG放到页面上。
给这段 path 一个 id为svgPath,然后可以直接这么使用。
.url::before{
offset-path: url('#svgPath');
}
这样一来,SVG既可以用于展示,又可以用于offset-path了,效果如下:
以上所有demo可以查看以下链接
- CSS offset-path (codepen.io)[1]
- CSS offset-path (juejin.cn)[2]
几个基本形状就这些了,接下来看一个实际应用
四、圆弧菜单展开效果
有了基本形状的支持,可以很方便的实现一些有意思的效果,比如这样的菜单展开
其实就是一个圆形路径动画。首先来看结构。
这里是通过 popover 来控制打开和收起的,不清楚popover的可以参考之前这篇文章:原生 popover 终于来了!
我们给每个子菜单加上路径偏移 offset-path。
.item {
offset-path: circle(80px);
}
效果如下:
为啥只有一个子菜单呢?这是因为所有的菜单都重叠在了一起,我们需要分散开来。
由于圆形路径动画是顺时针方向的,就像这样。
所以我们需要将 5 个子元素平均分配到半个圆弧上,如下:
用代码实现就是。
.item:nth-child(1) {
offset-distance: 100%;
}
.item:nth-child(2) {
offset-distance: 87.5%;
}
.item:nth-child(3) {
offset-distance: 75%;
}
.item:nth-child(4) {
offset-distance: 62.5%;
}
.item:nth-child(5) {
offset-distance: 50%;
}
给每个元素分别设置不同的offset-distance后,就变成了这样。
最后,只要在打开菜单时设置不同的延时,如下:
.menu-items:not(:popover-open) {
.item:nth-child(1) {
--delay: 0s;
}
.item:nth-child(2) {
--delay: 0.1s;
}
.item:nth-child(3) {
--delay: 0.2s;
}
.item:nth-child(4) {
--delay: 0.3s;
}
.item:nth-child(5) {
--delay: 0.4s;
}
就能得到我们想要的展开效果了。
完整代码可以查看:Radial Menu Popover remix using offset-path: circle() (codepen.io)[3]。
五、兼容性和总结
这个是 Chrome 116推出的新特性,目前还不是特别好,尤其是Safari拖了后腿,兼容性如下:
所以大规模使用还是需要等待一段时间,下面总结一下本文要点。
- 酷炫的路径动画可以用offset-path来实现。
- 之前仅支持 path(),虽然灵活,但是不好维护,不直观,而且一些基本形状也必须要转成path才行。
- path()不支持自适应尺寸。
- 基本形状是一种表现基础图形的 CSS 数据类型,适用于clip-path、shape-outside和offset-path,语法都是通用的。
- 基本形状主要有 circle()、ellipse()、inset()、polygon()。
- 现在还在支持 url(),可以直接用一段 svg作为路径偏移,更加直观。
[1]CSS offset-path (codepen.io): https://codepen.io/xboxyan/pen/rNgaxNR。
[2]CSS offset-path (juejin.cn): https://code.juejin.cn/pen/7367709756003516457。
[3]Radial Menu Popover remix using offset-path: circle() (codepen.io): https://codepen.io/cssgrid/pen/zYmeLam。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
软考中级精品资料免费领
- 历年真题答案解析
- 备考技巧名师总结
- 高频考点精准押题
- 资料下载
- 历年真题
193.9 KB下载数265
191.63 KB下载数245
143.91 KB下载数1148
183.71 KB下载数642
644.84 KB下载数2756
相关文章
发现更多好内容- Java 中带参方法和无参方法的差异究竟体现在哪些方面?(java有参和无参的区别是什么)
- 如何在 Java 中创建 Date 对象?(java怎么创建date对象)
- 如何利用 Java Milo 开展网络编程?(如何使用Java Milo进行网络编程)
- 如何高效使用Redis客户端进行故障排查
- 如何使用 getresources 获取文件系统资源?(getresources如何获取文件系统资源)
- 如何利用 Java 的多线程提升效率?(Java的多线程如何提高效率 )
- Java 中 file.exists 方法在不同操作系统下的表现及差异(java file.exists在不同操作系统下)
- 在 Java 中,究竟什么是线程安全?(java中什么是线程安全)
- Java 中 toString 方法该如何使用呢?(java中tostring方法如何使用)
- JavaScript函数式编程有哪些实用技巧?(JavaScript函数式编程有啥技巧)
猜你喜欢
AI推送时光机 咦!没有更多了?去看看其它编程学习网 内容吧