Как получить эффект гравитации в анимации CSS?

Я хочу оживить элемент, как будто вы смотрите на Землю. Элемент прыгает к вам, ударяется о свою вершину и немного падает вниз. Вид сбоку траектории был бы таким:

     _
   /   
  /     |
 |
 |

Я не смог достичь реалистичного эффекта с ключевой кадр анимации. Мой выглядит искусственным вот так:

    /
   /  
  /
 /
/

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

как вы ставите параболическую функцию на анимацию, чтобы получить эффект гравитации? Я думал Я мог бы использовать Кривые Безье, но стандарт CSS не допускает точек за пределами [0, 0].

3 ответов


Я думаю, что вы можете сделать это с помощью кривых Безье.

в вашем случае это может быть что-то вроде этого:

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

Я не делал этого сам, проверьте эту ссылку:

css ослабление анимации инструмент

Я сделал пример в JSFiddle.

Я поставил внешний div, чтобы сделать парение стабильным:

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

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

редактирование

просто изображение того, что вы можете получить с кривой Безье (со страницы инструмента анимации легкости), чтобы показать, что скорость объекта не должна быть постоянной (и может быть почти параболической)

bezier curve


использовать animation-timing-function в ваших кадров сделать два перехода (подъем с последующим падением) параболические.


чтобы сделать это правильно (т. е. в соответствии с физикой), вам нужно сначала убедиться, что шкала и время точки "пика" соответствуют должным образом. Ваша анимация работает от 0% до 100%, а верхняя часть параболы (точка максимального масштаба) находится где-то между ними, назовем это m%. Шкала начинается с 0 (на 0%), заканчивается на 1 (на 100%) и пики, скажем s (at m%). Затем, используя немного базовой математики, связь между этими двумя переменными:

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

или

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

...так для пика, который нужно достигнуть на 80%, вам нужно s = 17/16 = 1,0625

кроме того, для максимальной шкалы s 1.2, вы должны пик на m = 69.0983... %


теперь, чтобы сделать переходы правильно parabolic, вам нужно использовать parabolic 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)

для "осенней" части. Эти do дайте вам точные параболы. (См.здесь для математики за выводом этих значений; обратите внимание, что в идеале вы бы использовали 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) после его окончания. Если это действительно необходимо по какой-то причине, измените это значение обратно на "Вперед").


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