How to get gravity effect in CSS animation?

I want to animate the element, as if you were looking down at the Earth. The element jumps towards you, hits its top and falls a little. The side view of the trajectory will be as follows:

_ / \ / | | | 

I could not achieve a realistic effect with keyframe animation. 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 a parabolic function in an animation to get the effect of gravity? I thought I could use Bezier curves , but the CSS standard does not allow points outside of [0, 0].

+7
source share
3 answers

I think you can do this using Bezier curves.

in your case, it could be something like this:

 -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 did not do it myself, check this link:

css easing animation tool

I made an example in JSFiddle .

I put an external div to do stabilization of the hover:

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

and 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 you can get with a Bezier curve (using the animation simplification tool page) to show that the speed of the object does not have to be constant (and can be almost parabolic).

bezier curve

+6
source

Use animation-timing-function in your keyframes to make two transitions (rise with fall) parabolic.


To do this correctly (i.e., according to physics), you must first make sure that the scale and time of the “peak” point correspond correctly. Your animation works from 0% to 100%, and the upper part of the parabola (the point of maximum scale) is somewhere between the two, let it be called m%. The scale starts at 0 (at 0%), ends at 1 (at 100%) and peaks, let s say (at m%). Then, using a bit of basic math, the relationship between these two variables:

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

or

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

... so to reach a peak of 80% you need s = 17/16 = 1.0625

alternatively for max. scale s 1.2, you need to reach a peak at m = 69.0983 ...%


Now, to make the transitions right parabolic, you need to use the animation-timing-function parabolic settings. You want to effectively use something like ease-out as your object shoots up, and like ease-in when it starts to fall down ... but the toothless curves associated with these two keywords are not exactly parabolas.

Use instead:

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

to "lift" part of the animation and:

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

for the fall part. They give you exact parabolas. (See here for mathematics for the derivation of these values; note that ideally you would use 1/3 rather than 0.33333 and 2/3, rather than 0.66667, but CSS does not allow fractions).

Putting it all together, you get 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 correctly executed my sums, this should give you a completely parabolic animation trajectory!

(Note: I changed the animation mode-fill-mode to "none" because for the animation it did not seem necessary to continue the forced execution of transform: scale(1.0) after it was completed. If for some reason it is really necessary, change this value back "forward").

+7
source

Adobe provided a nice example that uses only standard time and time synchronization features. Although this may not be entirely “physical” (but not parabolic), it can be good enough for many situations. There is a demo on the page if you scroll down to the Physics - your friend section.

 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

+1
source

All Articles