探索神奇的运动路径动画MotionPath
时间:2023-03-20 12:54:39
科技观察
CSS有一个很有意思的模块——CSSMotionPathModuleLevel1[1],翻译过来就是运动路径。本文将仔细研究运动路径。通过本文,您可以了解到:什么是CSS运动路径使用CSS运动路径制作简单路径动画使用CSS运动路径制作复杂路径动画什么是CSSMotionPath运动路径?什么是CSSMotionPath运动路径?通过使用本规范规定的属性,我们可以控制元素按照特定路径进行位置变换的动画。此外,这条道路可能非常复杂。在深入探讨CSSMotionPath之前,让我们先看看如何使用传统CSS的功能来实现路径动画。CSS实现直线路径动画的传统方式之前我们想把一个物体从A点直线移动到B点。一般来说,我们可以使用transform:translate(),top|左|底部|right或margin可以改变对象位置的属性。一个简单的Demo:
div{width:60px;height:60px;background:#000;animation:moveinfinite1salternatelinear;}@keyframesmove{100%{transform:translate(100px,100px);}}对于简单的来自A的效果点直线移动到B点如下:CSS传统方式实现曲线路径动画当然,CSS也可以实现一些简单的曲线路径动画。如果我们想从A点移动到B点而不是直线,而是曲线怎么办?对于一些简单的圆弧路径,我们还是可以使用一些巧妙的方法来实现的。看看下面的例子。这次,我们使用了两个元素。子元素是一个小球,想要曲线移动,但实际上我们设置父元素的transform-origin,让父元素进行一次变换:rotate()movement驱动子元素的小球:
.g-container{position:relative;width:10vmin;height:70vmin;transform-origin:center0;动画:rotate1.5sinfinitealternate;}.g-ball{position:absolute;width:10vmin;height:10vmin;border-radius:50%;background:radial-gradient(circle,#fff,#000);bottom:0;left:0;}@keyframesrotate{100%{transform:rotate(90deg);}}为了便于理解,在移动的过程中,我让父元素的轮廓出现:这样,我们就勉强得到了一个非-直线路径运动动画,其实际运动轨迹是一条曲线。不过,这基本上是以前CSS所能做到的极限了。使用纯CSS的方法,是没有办法实现更复杂的路径动画的,比如下面的路径动画:直到现在,我们有了更强大的专门做这件事的规范,这就是本文的主角——CSSMotionPath。CSSMotionPath实现直线路径动画CSSMotionPath规范主要包括以下属性:offset-path:接收一个SVG路径(类似于CSS中的SVGpath和clip-path),指定运动的几何路径offset-distance:根据offset-path移动控制当前元素的距离offset-position:指定offset-path的初始位置offset-anchor:定义元素沿offset-path定位的锚点。这也很好理解。移动的元素可能不是一个点,所以需要指定元素中的哪个点附加到路径上进行移动。offset-rotate:定义沿offset-path定位时元素的方向。用人的话说就是运动过程中元素的角度是朝下的,我们使用MotionPath来实现一个简单的线性位移动画。
div{width:60px;height:60px;background:linear-gradient(#fc0,#f0c);offset-path:path("M00L100100");offset-rotate:0deg;animation:move2000msinfinitealternateease-in-out;}@keyframesmove{0%{offset-distance:0%;}100%{offset-distance:100%;}}offset-path接收一个SVG路径,这里我们的路径内容是自定义路径path("M00L100100"),翻译过来就是从00点移动到100px100px点。offset-path采用SVG路径,指定运动的几何路径。类似于CSS中的SVG路径和clip-path,如果你对这个SVG路径不是很了解,可以点这里先了解一下SVG路径的内容:SVG路径[2]我们会得到如下结果:通过控制元素的偏移距离动画元素的路径从0%到100%。当然,上面的动画是最基本的。我可以充分利用路径的特性,添加多个中间关键帧,稍微修改一下上面的代码:div{//只改变运动路径,其他保持一致;animation:move2000msinfinitealternatelinear;}@keyframesmove{0%{offset-distance:0%;}100%{offset-distance:100%;}}这里最重要的是在路径命令中使用LPicturesuchastraightpath:image最终效果如下,类似于使用transform:translate()添加多个关键帧:完整demo可以点这里:CodePenDemo--CSSMotionPathDemo[3]CSSMotionPath实现curves路径动画上面的运动轨迹是由直线组成的,我们来看看如何使用CSSMotionPath来实现曲线路径动画。其实原理还是一模一样的,只是在offset-path:path()中加入曲线相关的路径即可。在SVG的Path中,我们采用其中一种绘制曲线的方法——贝塞尔曲线,比如下面的路径,其中路径为d="M1080C8010,13010,19080S300150,36080":
对应这样一条连续的贝塞尔曲线:将对应的路径应用到offset-path:path:div:nth-child(2){width:40px;height:40px;background:linear-gradient(#fc0,#f0c);offset-path:path('M1080C8010,13010,19080S300150,36080');}@keyframesmove{0%{offset-distance:0%;}100%{offset-distance:100%;}}可以得到如下运动效果:可以看出元素是沿着贝塞尔曲线的路径运动的,而且,正因为如此,死角偏移没有限制——旋转,元素的方向也随着路径的方向而改变。(可以想象,在开车的时候,车头总是会随着道路而变化,带动整个车身的角度发生变化)完整的demo可以点这里:CodePenDemo--CSSMotionPathDemo[4】理解offset-anchor运动锚点好了,那么接下来,我们看看offset-anchor是怎么理解的。还是上面的DEMO,我们把小方块换成三角形,在页面上绘制运动曲线,像这样:其中,三角形是通过clip-path实现的:width:40px;height:40px;clip-path:多边形(00,100%50%,0100%);背景:线性渐变(#fc0,#f0c);一般来说,物体的中心点是沿着曲线移动的(类比于transform-origin),这里,我们可以通过offset-anchor来改变移动的锚点。比如我们想让三角形的底部沿着曲线移动:.ball{width:40px;height:40px;clip-path:polygon(00,100%50%,0100%);offset-path:path('M1080C8010,13010,19080S300150,36080');offset-anchor:0100%;background:linear-gradient(#fc0,#f0c);动画:move3000msinfinitealternatelinear;}@keyframesmove{0%{offset-distance:0%;}100%{offset-distance:100%;}}经过实测,Caniuse说offset-anchor属性的兼容性是Chrome79+,Firefox72+,但是实际只有Firefox支持,会Chrome下暂时不生效。完整的demo可以点击这里:CodePenDemo--CSSMotionPathoffset-anthorDemo[5]使用MotionPath制作动画效果就OK了。上面的原理我们已经基本给出了。让我们来看看如何在实践中使用MotionPath。使用运动路径制作按钮效果使用运动路径,我们可以制作一些简单的按钮点击效果。之前在CodePen上看到过这样一个按钮点击效果:原理是利用background-radial来生成每一个小圆点,通过控制background-position来控制小圆点的位移。详细的Demo代码你可以点这里:CodePenDemo--Bubblybutton(DesignbyGalShir)[6]但是小圆点的运动路径基本上是一条直线。使用本文中的MotionPath,我们也可以实现一些类似的效果。核心代码如下,HTML这里使用Pug模板,CSS使用SASS:.btn-for(vari=0;i<60;i++)span.dot.btn{position:relative;padding:1.5rem4.5rem;}.btn。点{position:absolute;width:4px;height:4px;@for$ifrom1through$count{&:nth-child(#{$i}){top:50%;left:50%;transform:translate3d(-50%,-50%,0)旋转(#{360/$count*$i}deg);}}&::before{content:"";position:absolute;top:0;left:0;width:4px;高度:4px;边框半径:50%;偏移路径:路径(“M01c7.1010.7214.34s7.1414.3410.7-214.3-47.2-414.3-410.7214.347.1414.3410.7-214.3-47.1-4104.714.34.3410.7-214.3-47.1-414.3-410.7214.347.1414.34");offset-distance:0;}}.btn.is-animating:active.dot:nth-child(4n+1)::before{动画:dotvar(--animation-time)var(--animation-timing-function);}.btn.is-动画:active.dot:nth-child(4n+2)::before{border:1pxsolidvar(--color-primary);背景:透明;动画:dotvar(--animation-time)var(--animation-计时函数)0.1s;}.btn.is-animating:active.dot:nth-child(4n+3)::before{animation:dotvar(--animation-time)var(--animation-timging-function)0.2s;}.btn.is-animating:active.dot:nth-child(4n)::before{border:1pxsolidvar(--color-primary);background:transparent;animation:dotvar(--animation-time)var(--animation-timging-function)0.3s;}@keyframesdot{0%{offset-distance:0%;opacity:1;}90%{offset-distance:60%;opacity:.5;}100%{offset-distance:100%;opacity:0;}}虽然代码稍微复杂了点,但不难理解。本质是给每个子元素设置相同的offset-path:path(),给不同组下的子元素设置不同的旋转角度,并使用动画延迟animation-delay设置4组动画起始于同一时间这里我们的轨迹路径不是直线,效果如下:完整代码可以点这里:CodePenDemo--ButtonAnimationwithCSSOffsetPaths[7]使用Motion-Path绘制地图路径寻路动画是也很实用,现在我们可以完全使用CSSMotion-Path来实现地图上的寻路动画:这个Demo来自AhmadEmran,完整代码可以点这里:CodePenDemo--CodePenHomeAnimationwithoffset-路径|OnlyUsingCSS&HTML[8]使用Motion-Path绘制路径动画或者,我们可以利用Path的特性来绘制任意路径来实现我们想要的各种路径,比如给购物车添加一条抛物线,或者各种运动轨迹.Demo:CodePenDemo--CSSMotionPathoffset-pathanimation[9]能否使用-Motion-Path查看Motion-Path目前的兼容性如何?截至2021-04-27。CaniUse-Motion-Path[10]:目前除IE浏览器外,等待Safari何时兼容。是否使用取决于目标群体的浏览器使用情况。最后,本文到此结束。引入了运动路径动画MotionPath,用它实现了一些以往无法轻易实现的路径动画效果。希望对你有所帮助:更多精彩的CSS技术文章汇总在我的Github--iCSS[11]。参考资料[1]CSSMotionPathModuleLevel1:https://drafts.fxtf.org/motion-1/[2]SVG路径:https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Paths[3]CodePenDemo--CSSMotionPathDemo:https://codepen.io/Chokcoco/pen/gOgqoem[4]CodePenDemo--CSSMotionPathDemo:https://codepen.io/Chokcoco/pen/gOgqoem[5]CodePenDemo--CSSMotionPathoffset-anthorDemo:https://codepen.io/Chokcoco/pen/poRGZeE[6]CodePenDemo--Bubblybutton(DesignbyGalShir):https://codepen.io/Chokcoco/pen/poRGZeE[6]://codepen.io/Chokcoco/pen/bGGMLdd[7]CodePenDemo--使用CSS偏移路径的按钮动画:https://codepen.io/Chokcoco/pen/xxgMPzJ[8]CodePenDemo--CodePenHomeAnimationwith偏移路径|仅使用CSS&HTML:https://codepen.io/ahmadbassamemran/pen/bXByBv[9]CodePen演示--CSS运动路径偏移路径动画:https://codepen.io/Chokcoco/pen/dyNaZea[10]我可以使用-运动路径:https://caniuse.com/?search=motion%20path[11]Github--iCSS:https://github.com/chokcoco/iCSS