使用自定义属性和cubic-bezier()构建复杂的CSS过渡效果

301 阅读8分钟

我最近说明了 ,我们可以使用 "自定义属性 "来实现复杂的CSS动画。[cubic-bezier()](https://css-tricks.com/advanced-css-animation-using-cubic-bezier/)以及在涉及到CSS转换时如何做同样的事情。我能够在不使用关键帧的情况下创建复杂的悬停效果。在这篇文章中,我将向你展示如何创建复杂的CSS过渡。

这一次,让我们使用@property 功能。它暂时只支持基于Chrome的浏览器,但我们仍然可以玩玩它,并演示它如何,并可以用来构建复杂的动画。

我强烈建议阅读我之前的文章,因为我将参考我在那里详细解释的一些概念。另外,请注意,本文中的演示最好在基于Chromium的浏览器中观看,而@property 支持仍然有限。

让我们从一个演示开始。

CodePen嵌入回退

点击按钮(不止一次),看看我们得到的 "神奇 "曲线。乍一看,它可能看起来微不足道,因为我们可以通过一些复杂的关键帧来实现这样的效果。但诀窍在于,这里没有关键帧!这个动画只用了一个过渡帧。这个动画只用了一个过渡。

厉害吧?这仅仅是个开始,让我们深入了解一下吧

主要思路

前面的例子中的技巧依赖于这个代码。

@property --d1 {
  syntax: '<number>';
  inherits: false;
  initial-value: 0;
}
@property --d2 {
  syntax: '<number>';
  inherits: false;
  initial-value: 0;
}

.box {
  top: calc((var(--d1) + var(--d2)) * 1%);
  transition:
    --d1 1s cubic-bezier(0.7, 1200, 0.3, -1200),
    --d2 1s cubic-bezier(0.5, 1200, 0.5, -1200);
}
.box:hover {
  --d1: 0.2;
  --d1: -0.2;
}

我们定义了两个自定义属性,--d1--d2 。然后,我们使用这两个属性的总和在.box 元素上声明top 属性。还没有什么过于复杂的东西--只是将calc() 应用于两个变量。

这两个属性被定义为<number> ,我把这些值乘以1%来转换为百分比。我们可以立即将这些定义为<percentage> ,以避免乘法。但我选择了数字来代替,以利于以后更复杂的操作的灵活性。

请注意,我们对每个变量应用了不同的过渡--更准确地说,是一个具有相同持续时间的不同的timing-function 。这实际上是对两个变量采用了不同的正弦曲线,这是我在上一篇文章中深入探讨的问题。

从这里开始,当.box ,触发动画时,属性值会发生变化。但为什么我们会得到我们在演示中看到的结果?

这都是关于数学的。我们正在添加两个函数来创建第三个函数。对于--d1 ,我们有一个函数(我们叫它F1);对于--d2 ,我们有另一个函数(我们叫它F2)。这意味着top 的值是 F1 + F2。

一个例子可以更好地说明问题。

CodePen嵌入回退

前两个转折点分别说明了每个变量。第三个则是它们的总和。想象一下,在动画的每一步,我们采取两个变量的值,我们把它们加在一起,得到最终曲线上的每个点。

让我们尝试另一个例子。

CodePen嵌入回落

这一次,我们把两条抛物线结合起来,得到一条......嗯,我不知道它的名字,但它是另一条复杂的曲线

这个技巧不仅限于抛物线和正弦波曲线。它可以适用于任何类型的定时函数,即使其结果并不总是一条复杂的曲线。

CodePen嵌入回退

这一次

  • --d1 从 到 ,使用 定时函数0 30 ease-in
  • --d2 从 到 ,用一个 的定时函数。0 -20 ease-out

结果是什么?top 的值从010 (30-20) ,有一个自定义的定时函数(ease-inease-out 的总和)。

在这种情况下,我们并没有得到一个复杂的过渡--这更多的是为了说明一个事实,即这是一个通用的想法,不仅仅局限于cubic-bezier()

我想是时候进行互动演示了。

CodePen嵌入回退

你所要做的就是调整几个变量来建立你自己的复杂过渡。我知道cubic-bezier() 可能很棘手,所以考虑使用这个在线曲线生成器,也可以参考我之前的文章

下面是我做的一些例子。

正如你所看到的,我们可以结合两个不同的定时函数(用cubic-bezier() 创建)来创建第三个函数,复杂到足以实现花哨的过渡。组合(和可能性)是无限的!

在最后一个例子中,我想证明将两个相反的函数相加是如何导致一个恒定函数的逻辑结果的(没有过渡)。因此,这条平线。

让我们增加更多的变量!

你以为我们会止步于两个变量吗?当然不是!我们可以将逻辑扩展到N 变量。没有任何限制--我们用一个定时函数来定义每个变量,然后把它们加起来。

一个有三个变量的例子。

CodePen嵌入回退

在大多数情况下,两个变量就足以创造出一条花哨的曲线,但知道这一招可以扩展到更多的变量是很整洁的。

我们可以对变量进行减法、乘法和除法吗?

当然可以!我们还可以扩展同样的想法,考虑更多的操作。我们可以加、减、乘、除--甚至可以在变量之间进行复杂的公式运算。

在这里,我们是将数值相乘。

CodePen 嵌入回退

我们还可以使用一个变量,并将其与自身相乘,以获得一个二次函数!

CodePen 嵌入回退

让我们通过引入min()/max() 来模拟一个abs() 的函数,在那里添加更多的乐趣。

CodePen 嵌入回退

请注意,在第二个盒子里,我们永远不会得到高于y轴上的中心点,因为top 总是一个正值。(我添加了一个margin-top ,使盒子的中心成为0的参考。)

我不会去讨论所有的数学问题,但你可以想象我们有多少可能性来创建任何类型的定时函数。我们所要做的就是找到正确的公式,要么使用一个变量,要么结合多个变量。

我们的初始代码可以被泛化。

@property --d1 { /* we do the same for d2 .. dn */
  syntax: '<number>';
  inherits: false;
  initial-value: i1; /* the initial value can be different for each variable */
}

.box {
  --duration: 1s; /* the same duration for all */
  property: calc(f(var(--d1),var(--d2), .. ,var(--dn))*[1UNIT]);
  transition:
    --d1 var(--duration) cubic-bezier( ... ),
    --d2 var(--duration) cubic-bezier( ... ),
    /* .. */
    --dn var(--duration) cubic-bezier( ... );
}
.box:hover {
  --d1:f1;
  --d2:f2;
  /* .. */
  --dn:f3;
}

这是用来说明逻辑的伪代码。

  1. 我们使用@property 来定义数字自定义属性,每个都有一个初始值。
  2. 每个变量都有自己的定时函数,但持续时间相同。
  3. 我们定义一个f 函数,这是变量之间使用的公式。该函数提供了一个数字,我们用它来乘以相关单位。所有这些都是在calc() ,应用于属性的运行。
  4. 我们在悬停(或切换,或其他)时更新每个变量的值。

鉴于此,该属性通过一个自定义的计时函数从f(i1,i2,…,in) 过渡到f(f1,f2,..,fn)

链式计时函数

我们已经达到了能够通过组合基本函数来创建复杂的计时函数的程度。让我们尝试另一个想法,让我们有更复杂的定时函数:将定时函数串联起来

诀窍是使用transition-delay 属性连续地运行转换。让我们回顾一下交互式演示,并对其中一个变量应用延迟。

CodePen Embed Fallback

我们正在将计时功能连锁起来,而不是将它们加在一起,以获得另一种创建更复杂的计时功能的方法从数学上讲,它仍然是一个总和,但由于转换不是在同一时间运行,我们将用一个常数来求和一个函数,这就模拟了连锁的情况。

现在想象一下有N 变量的情况,我们是渐进式延迟的。我们不仅可以通过这种方式创建复杂的过渡,而且我们有足够的灵活性来构建复杂的时间线

这里是我用这种技术建立的一个有趣的悬停效果。

CodePen 嵌入回落

你会发现那里没有关键帧。一个小的动作场景完全用一个元素和一个CSS过渡来完成。

这里是一个使用同样想法的逼真的钟摆动画。

CodePen Embed Fallback

或者,一个自然弹跳的球怎么样。

CodePen Embed Fallback

或者是一个沿着曲线滚动的球。

CodePen Embed Fallback

看到了吗?我们刚刚创建了复杂的动画,代码中没有一个关键帧!

这就结束了!

我希望你从这篇文章和上一篇文章中得到三个关键点。

  1. 我们可以使用cubic-bezier() ,得到抛物线和正弦线的曲线,使我们可以在没有关键帧的情况下创造复杂的过渡。
  2. 我们可以通过使用自定义属性和calc() ,结合不同的定时函数来创建更多的曲线。
  3. 我们可以使用transition-delay ,将曲线连锁起来,建立一个复杂的时间线。

多亏了这三个功能,我们在创建复杂的动画时没有任何限制。

CodePen嵌入回退


The postBuild Complex CSS Transitions using Custom Properties and cubic-bezier()appeared first onCSS-Tricks.你可以通过成为MVP支持者来支持CSS-Tricks。