当前位置: 首页 > Web前端 > HTML

如何在CSS中反转贝塞尔曲线

时间:2023-04-02 22:40:36 HTML

首先,我们来看一下我之前写的一个CSS轮播动画效果。为了让切换时动画过渡更平滑,我没有在animation-timing-function属性中包含使用CSS提供的各种关键字,使用了cubic-bezier(贝塞尔)函数。贝塞尔函数乍一看可能会令人困惑和迷惑,但如果使用得当,它们可以为动画的用户体验增添更棒的感觉。在构建这个轮播动画时,我意识到当我在一页上添加一个显示的贝塞尔曲线时,前一页上的隐藏贝塞尔曲线被反转了。我认为分享我们在本文中的内容非常值得,因为创建贝塞尔曲线并反转它可能看起来很棘手,但实际上非常简单。理解easing的基础知识首先,easing这个词用来描述元素动画在时间轴上的加速和减速节奏。我们可以将其绘制为图表,其中x轴是时间,y轴是动画的进度。Linear是没有加速或减速的图形(一直以相同的速度移动),在图形上表现为一条直线:Non-linearEasing会让动画更加自然逼真。我们可以在CSS中对过渡和动画应用各种缓动,我们可以在transition-timing-function或animation-timing-function属性上设置这些值。一共有五个关键字可以设置:linear-ease-in上面已经介绍过-动画开始的时候很慢,然后随着它的进行而加速。ease-out-动画开始快,结束时慢。ease-in-out——动画开始缓慢,中间加速,最后减速。ease-默认值,与ease-in-out动画过程相反。理解cubic-bezier如果上面介绍的关键字值都不适合我们的动画,我们可以使用cubic-bezier贝塞尔函数来创建自定义曲线。这是一个例子:.my-element{animation-name:slide;动画持续时间:3s;animation-timing-function:cubic-bezier(0.45,0.25,0.60,0.95);}我们可以将这些属性缩写为a,如下所示:.my-element{animation:slide3scubic-bezier(0.45,0.25,0.60,0.95);您会注意到cubic-bezier函数有四个值。这四个值就是绘制曲线所需要的两对坐标。这些坐标代表什么?如果您使用过Illustrator,控制曲线大小和方向的矢量点对您来说会很熟悉。这些是我们需要用三次贝塞尔贝塞尔函数绘制曲线的点。我们不需要了解贝塞尔曲线背后的所有数学知识。因为有大佬给我们制作了方便的工具,比如LeaVerou的cubic-bezier.com,在这个网站上我们可以直观的制作贝塞尔曲线,并复制它的坐标点值。我的轮播效果的贝塞尔曲线是用这个工具创建的,它看起来像这样:在这里,你可以看到我们需要的两个点:cubic-bezier(x1,y1,x2,y2)。在正向和负向应用缓动上面的轮播在正向和负向都应用动画——当左箭头被点击时,当前项目向右滑出视图,下一个项目向左滑入;如果单击向右箭头,则会发生相反的情况。我最初的假设是动画可以简单地反转以使项目沿相反方向滑出,如下所示:.my-element--reversed{animation:slide3scubic-bezier(0.45,0.25,0.60,0.95)reverse;}这里有一个问题:向动画添加reverse也会反转缓动曲线!所以,现在我的动画在一个方向上看起来不错,但在另一个方向上是错误的。下面的demo中,第一个方框展示的是正向的动画,第二个方框展示的是添加反向后的情况。可以看到两个动画给人的感觉完全不一样。随着动画的进行,第一个盒子开始加速并慢慢减速,而第二个盒子开始相当缓慢,然后在停止之前稍微加速。我们有两种方法来解决这个问题:创建一个新的关键帧动画来显示动画,然后设置为相同的缓动。简单的动画这样设置没有错,但是遇到复杂的动画怎么办呢?反向创建动画需要更多工作并且容易出错。我们可以使用相同的关键帧动画(并设置animation-direction:reverse),反转贝塞尔曲线,达到两个方向使用相同缓动的效果。这个方法并不难。反转贝塞尔曲线对应于将整个图形在坐标轴上旋转180度:通过简单的数学计算,即可得到反转后的点坐标。具体方法是:交换两个坐标点,改变每个值都减1。比如正方向的坐标为:x1,y1,x2,y2,那么反方向的坐标通过下面的公式:(1-x2),(1-y2),(1-x1),(1-y1)在下面的demo中,第三个方框就是我们需要的效果:元素向相反的方向滑动,但是它具有与正方向相同的动画曲线。让我们看看如何计算反向贝塞尔曲线。使用CSS自定义属性计算反向曲线我们可以使用CSS自定义属性来计算新曲线!首先将每个值分配给一个变量::root{--x1:0.45;--y1:0.25;--x2:0.6;--y2:0.95;--originalCurve:cubic-bezier(var(--x1),var(--y1),var(--x2),var(--y2));}然后我们可以使用这些变量来计算新值::root{--reversedCurve:cubic-bezier(calc(1-var(--x2)),calc(1-var(--y2)),calc(1-var(--x1)),calc(1-var(--y1)));}现在,如果我们对第一组变量进行任何更改,将自动计算反向曲线点。为了在检查和调试代码时更容易发现问题,我喜欢将这些新值赋给它们自己的变量::root{/*forwardoriginalvalue*/--x1:0.45;--y1:0.25;---x2:0.6;--y2:0.95;--originalCurve:cubic-bezier(var(--x1),var(--y1),var(--x2),var(--y2));/*反向计算值*/--x1-r:calc(1-var(--x2));--y1-r:计算(1-var(--y2));--x2-r:计算(1-var(--x1));--y2-r:计算(1-var(--y1));--reversedCurve:cubic-bezier(var(--x1-r),var(--y1-r),var(--x2-r),var(--y2-r));}剩下的现在是将新曲线应用于反转动画:.my-element--reversed{animation:slide3svar(--reversedCurve)reverse;}为了更直观和直观地做到这一点,我创建了一个小工具来计算贝塞尔曲线的反向值。输入原始坐标值自动获取反向曲线的值:Reversecubic-beziertool