8

我想为一个元素设置动画,就好像你在俯视地球一样。元素跳向你,到达它的顶点,然后稍微往回落。轨迹的侧视图如下所示:

     _
   /   \
  /     |
 |
 |

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

    /\
   /  \
  /
 /
/

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;
}

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

4

3 回答 3

9

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


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

m = 100 / (1 + sqrt(s-1))

或者

s = (100/m - 1)^2 + 1

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

或者,对于 1.2 的最大比例s,您需要在m = 69.0983... %


现在,要使转换正确地为抛物线,您需要使用抛物线animation-timing-function设置。你想有效地使用 ease-out当你的对象射出时一样的东西,就像 ease-in它开始回落时一样……但是与这两个关键字相关的三次贝塞尔曲线并不完全是抛物线。

相反,使用:

animation-timing-function: cubic-bezier(0.33333, 0.66667, 0.66667, 1)

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

animation-timing-function: cubic-bezier(0.33333, 0, 0.66667, 0.33333)

对于“下降”部分。这些确实给了你精确的抛物线。(请参阅此处了解这些值的推导背后的数学;请注意,理想情况下,您将使用 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) }
}

...如果我的计算正确,那应该会给你一个完美的抛物线动画轨迹!

(注意:我将动画填充模式更改为“无”,因为动画结束后似乎没有必要继续执行transform: scale(1.0)。如果出于某种原因确实有必要,请将此值更改回“转发”)。

于 2013-06-02T14:03:50.007 回答
8

I think that you can do it using bezier curves.

in you case, it could be something like that:

-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 */

I haven't done it by myself, check this link:

css easing animation tool

I have made an example in a JSFiddle.

I put an outer div to make the hover stable:

<div class="container">
    <div class="moving"></div>
</div>

and the CSS is as follows:

.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;
}

Editing

Just an image of what can you get with a bezier curve (from the ease animation tool page) to show that the object speed doesn't need to be constant (and can be almost parabolic)

bezier curve

于 2013-03-15T08:19:16.957 回答
1

Adobe 提供了一个很好的例子,它只使用标准的缓入/缓出计时功能。即使它可能不是完全“物理的”(即,不是抛物线的),它对于许多情况可能仍然足够好。如果您向下滚动到“物理是您的朋友”部分,页面上有一个演示。

div {
    width:140px;
    height:140px;
    border-radius: 70px;
    background:red;
    position:relative;
    animation: jump 1s infinite;
}

@keyframes jump {
    0% {top: 0;animation-timing-function: ease-in;}
    50% {top: 140px;height: 140px;animation-timing-function: ease-out;}
    55% {top: 160px; height: 120px;border-radius: 70px / 60px;animation-timing-function: ease-in;}
    65% {top: 120px; height: 140px;border-radius: 70px;animation-timing-function: ease-out;}
    95% {top: 0;animation-timing-function: ease-in;}
    100% {top: 0;animation-timing-function: ease-in;}
}

资料来源: http: //www.adobe.com/inspire/2013/04/animating-interactive-experiences-css.html

于 2013-10-24T20:47:18.323 回答