如何在CSS动画中获得重力效果?

Pwn*_*ner 7 css physics

我想为一个元素设置动画,就好像你在俯视地球一样.元素向你跳跃,击中它的顶点,然后向下跌落一点.轨迹的侧视图如下:

     _
   /   \
  /     |
 |
 |
Run Code Online (Sandbox Code Playgroud)

我无法通过关键帧动画获得逼真的效果.我看起来像这样人造:

    /\
   /  \
  /
 /
/
Run Code Online (Sandbox Code Playgroud)

CSS

@keyframes springIn {
    0% {
        transform: scale(0.0);
    }
    80% {
        transform: scale(1.2);
    }
    100% {
        transform: scale(1.0);
    }
}

.someElement {
    animation: springIn 1s linear 1s 1 forwards;
}
Run Code Online (Sandbox Code Playgroud)

如何在动画上放置抛物线函数以获得重力效果?我以为我可以使用Bezier曲线,但CSS标准不允许[0,0]之外的点.

Doi*_*oin 9

animation-timing-function 在关键帧中使用以使两个过渡(上升然后下降)抛物线.


要正确执行此操作(即根据物理原理),首先需要确保"峰值"点的刻度和时间正确对应.你的动画从0%到100%运行,抛物线的顶部(最大比例点)介于两者之间,我们称之为m%.比例从0开始(0%),结束于1(100%),峰值出现在s(m%)处.然后使用一些基本数学,这两个变量之间的关系是:

m = 100 / (1 + sqrt(s-1))
Run Code Online (Sandbox Code Playgroud)

要么

s = (100/m - 1)^2 + 1
Run Code Online (Sandbox Code Playgroud)

...所以要达到80%的峰值,你需要s = 17/16 = 1.0625

或者,对于最大尺度s为1.2,您需要在m = 69.0983 处达到峰值...%


现在,要使转换正确抛物线,您需要使用抛物线animation-timing-function设置.你想要有效地使用 ease-out你的物体一样射击的东西,就像 ease-in它开始倒下一样 ......但是与这两个关键词相关的三次贝塞尔曲线并不完全是抛物线.

相反,使用:

animation-timing-function: cubic-bezier(0.33333, 0.66667, 0.66667, 1)
Run Code Online (Sandbox Code Playgroud)

对于动画的"上升"部分,以及:

animation-timing-function: cubic-bezier(0.33333, 0, 0.66667, 0.33333)
Run Code Online (Sandbox Code Playgroud)

对于"秋天"部分.这些确实给你精确的抛物线.(请参阅此处获取这些值的推导背后的数学;请注意,理想情况下,您使用1/3而不是0.33333和2/3而不是0.66667,但CSS不允许分数).

把所有这些放在一起给你这个CSS:

.someElement { animation: springIn 1s linear 1s 1 none }

@keyframes springIn
{
  0% { transform: scale(0.0); animation-timing-function: cubic-bezier(0.33333, 0.66667, 0.66667, 1) }
  69.0983% { transform: scale(1.2); animation-timing-function: cubic-bezier(0.33333, 0, 0.66667, 0.33333) }
  100% { transform: scale(1.0) }
}
Run Code Online (Sandbox Code Playgroud)

...如果我已经完成了我的总和,那应该会给你一个完美的抛物线动画轨迹!

(注意:我将动画填充模式更改为"无",因为动画transform: scale(1.0)在结束后似乎没有必要继续强制执行.如果由于某种原因这实际上是必要的,请将此值更改回"转发").


val*_*als 7

我认为你可以使用贝塞尔曲线来做到这一点.

在你的情况下,它可能是这样的:

-webkit-transition: all 500ms cubic-bezier(0.310, 0.440, 0.445, 1.650); 
-moz-transition: all 500ms cubic-bezier(0.310, 0.440, 0.445, 1.650); 
-ms-transition: all 500ms cubic-bezier(0.310, 0.440, 0.445, 1.650); 
-o-transition: all 500ms cubic-bezier(0.310, 0.440, 0.445, 1.650); 
transition: all 500ms cubic-bezier(0.310, 0.440, 0.445, 1.650); /* custom */

-webkit-transition-timing-function: cubic-bezier(0.310, 0.440, 0.445, 1.650); 
-moz-transition-timing-function: cubic-bezier(0.310, 0.440, 0.445, 1.650); 
-ms-transition-timing-function: cubic-bezier(0.310, 0.440, 0.445, 1.650); 
-o-transition-timing-function: cubic-bezier(0.310, 0.440, 0.445, 1.650); 
transition-timing-function: cubic-bezier(0.310, 0.440, 0.445, 1.650); /* custom */
Run Code Online (Sandbox Code Playgroud)

我没有亲自完成,请查看此链接:

简化动画工具

在JSFiddle中做了一个例子.

我放了一个外部div来使悬停稳定:

<div class="container">
    <div class="moving"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

CSS如下:

.moving {
    position: absolute; width: 200px; height: 150px; top: 50px;  left: 50px;
    background-color: green;
    -webkit-transition: all 5s cubic-bezier(0.310, 0.440, 0.445, 1.650); 
}

.container:hover .moving {
    zoom: 1.5;
}
Run Code Online (Sandbox Code Playgroud)

编辑

只是通过贝松曲线(从简易动画工具页面)获得的图像,以显示对象速度不需要是恒定的(并且几乎是抛物线的)

贝塞尔曲线