问题
I want to animate an element as if you're looking down at the Earth. The element jumps towards you, hits its apex, and falls back down a little. A side view of the trajectory would be like this:
_
/ \
/ |
|
|
I wasn't able to attain a realistic effect with keyframe animations. Mine looks artificial like this:
/\
/ \
/
/
/
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;
}
How do you put parabolic function on the animation to get the gravity effect? I thought I could use Bezier Curves, but the CSS standard does not allow points outside of [0, 0].
回答1:
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)
回答2:
Use animation-timing-function
in your keyframes to make the two transitions (rise followed by fall) parabolic.
To do this correctly (i.e. according to physics), you need firstly make sure that the 'peak' point scale and time correspond properly. Your animation runs from 0% to 100%, and the top of the parabola (point of maximum scale) is somewhere between the two, let's call it m%. The scale starts at 0 (at 0%), ends at 1 (at 100%) and peaks at let's say s (at m%). Then using a bit of basic math, the relationship between these two variables is:
m = 100 / (1 + sqrt(s-1))
or
s = (100/m - 1)^2 + 1
...so for the peak to be reached at 80%, you need s = 17/16 = 1.0625
alternatively, for a max scale s of 1.2, you need to peak at m = 69.0983... %
Now, to make the transitions properly parabolic, you need to use parabolic animation-timing-function
settings. You want to effectively use something like ease-out
as your object shoots up, and like ease-in
as it starts falling back down... but the cubic bezier curves associated with these two keywords are not exactly parabolas.
Instead, use:
animation-timing-function: cubic-bezier(0.33333, 0.66667, 0.66667, 1)
for the "rise" part of the animation, and:
animation-timing-function: cubic-bezier(0.33333, 0, 0.66667, 0.33333)
for the "fall" part. These do give you exact parabolas. (See here for the maths behind the derivation of these values; note that ideally you'd use 1/3 rather than 0.33333 and 2/3 rather than 0.66667, but CSS doesn't allow fractions).
Putting all this together gives you this 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) }
}
...and if I've done my sums right, that should give you a perfectly parabolic animation trajectory!
(Note: I changed the animation-fill-mode to "none" because it did not seem necessary for the animation to continue enforcing transform: scale(1.0)
after it ends. If this is actually necessary for some reason, change this value back to "forwards").
回答3:
Adobe has provided a nice example which only uses standard ease-in/ease-out timing functions. Even though it might not be completely "physical" (i e, not parabolic), it might still be good enough for many situations. There is a demo on the page if you scroll down to the section Physics is your friend.
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;}
}
Source: http://www.adobe.com/inspire/2013/04/animating-interactive-experiences-css.html
来源:https://stackoverflow.com/questions/15423736/how-to-get-a-gravity-effect-in-a-css-animation