Вы может использовать CSS-только, но вы будете тратить много времени на выяснение того, номер для Безье, ключевой кадр позиции, масштаба и так далее, и на вершине, что: небольшое изменение в вашем макете, «гравитация», размеры, расстояние, и вы должны начать «повсюду» (по крайней мере, для вышеуказанной части).
CSS анимации хороши, но вы получите лучший результат с небольшим количеством кода JavaScript, не говоря уже имеют гораздо большую гибкость, если вам нужно что-то изменить -
- Определение вектора для шара
- Определить произвольную гравитацию
- Вычислить вектор и отказы
- Bind полученных значения для элементов DOM с помощью преобразований (дает гладкий результат по сравнению с положением).
- Анимация с использованием
requestAnimationFrame
, которая синхронизирует монитор и дает ровную плавную анимацию, как это делает анимация CSS.
Пример
Этот пример показывает основной, не включает в себя тень, но остается в качестве упражнения для читателя.
var div = document.querySelector("div"),
v = {x: 2.3, y: 1}, // some vector
pos = {x: 100, y: 20}, // some position
g = 0.5, // some gravity
absorption = 0.7, // friction/absorption
bottom = 150, // floor collision
frames = 0; // to reset animation (for demo)
// main calculation of the animation using a particle and a vector
function calc() {
pos.x += v.x; // update position with vector
pos.y += v.y;
v.y += g; // update vector with gravity
if (pos.y > bottom) { // hit da floor, bounce
pos.y = bottom; // force position = max bottom
v.y = -v.y * absorption; // reduce power with absorption
}
if (pos.x < 0 || pos.x > 620) v.x = -v.x;
}
// animate
(function loop() {
calc();
move(div, pos);
if (++frames > 220) { // tweak, use other techniques - just to reset bounce
frames = 0; pos.y = 20;
}
requestAnimationFrame(loop)
})();
function move(el, p) {
el.style.transform = el.style.webkitTransform = "translate("+p.x+"px,"+p.y+"px)";
}
div {
width:20px;
height:20px;
background:rgb(0, 135, 222);
border-radius:50%;
position:fixed;
}
<div></div>
Если вы хотите получить более точный отскок пола, вы можете использовать дифференциал фактического положения, чтобы отразить это, а также:
if (pos.y > bottom) {
var diff = pos.y - bottom;
pos.y = bottom - diff;
...
И если вам это нужно для нескольких элементов просто создайте объект, способный к созданию экземпляра, который включает ссылку на элемент для анимации, вычисления и т. д.
Если вы хотите изменить направление, начальную точку, гравитацию и т. Д., Вы просто обновляете соответствующие значения, и при повторном воспроизведении все будет работать плавно.
Пример промежуточный шаг для создания CSS ключевые кадры
Вы можете изменить код, чтобы грызть числа для CSS-анимации.
Использовать количество кадров и нормализовать диапазон последовательности, выполнить вычисления путем подсчета кадров. Затем извлекайте значения per, скажем, каждые 10 кадров, а также каждый отскок, наконец, цифры формата в виде ключевых кадров.
В идеале вы всегда будете включать верхнее и нижнее положение - вы можете обнаружить это, контролируя направление y-значения вектора (знак), не показанного здесь.
Это будет работать в качестве промежуточного шага для создания CSS-правила, которые мы будем использовать позже:
var v = {x: 2.3, y: 1}, // some vector
pos = {x: 100, y: 20}, // some position
g = 0.5, // some gravity
absorption = 0.7, // friction/absorption
bottom = 150, // floor collision
frames = 0, // to reset animation (for demo)
maxFrames = 220, // so we can normalize
step = 10, // grab every nth + bounce
heights = [], // collect in an array as step 1
css = ""; // build CSS animation
// calc CSS-frames
for(var i = 0; i <= maxFrames; i++) {
var t = i/maxFrames;
pos.x += v.x; // update position with vector
pos.y += v.y;
v.y += g; // update vector with gravity
if (pos.y > bottom) {
pos.y = bottom;
v.y = -v.y * absorption;
heights.push({pst: t * 100, y: pos.y});
}
else if (!(i % step)) {heights.push({pst: t * 100, y: pos.y})}
}
// step 2: format height-array into CSS
css += "@keyframes demo {\n";
for(i = 0; i < heights.length; i++) {
var e = heights[i];
css += " " + e.pst.toFixed(3) + "% {transform: translateY(" + e.y.toFixed(3) + "px)}\n";
}
css += "}";
document.write("<pre>" + css + "</pre>");
Если мы захватываем результат от этого и использует его в качестве CSS для нашего окончательная страница, мы получаем этот результат (извините, но не префиксная версия только в этой демонстрации):
(Вам, конечно, придется подстроить и настроить его, но вы получите суть.)
div {
animation: demo 3s linear infinite;
width:20px;
height:20px;
border-radius:50%;
background:rgb(0, 148, 243);
position:fixed;
left:100px;
}
@keyframes demo {
0.000% {transform: translateY(21.000px)}
4.545% {transform: translateY(58.500px)}
9.091% {transform: translateY(146.000px)}
9.545% {transform: translateY(150.000px)}
13.636% {transform: translateY(92.400px)}
18.182% {transform: translateY(75.900px)}
22.727% {transform: translateY(109.400px)}
25.455% {transform: translateY(150.000px)}
27.273% {transform: translateY(127.520px)}
31.818% {transform: translateY(106.320px)}
36.364% {transform: translateY(135.120px)}
37.727% {transform: translateY(150.000px)}
40.909% {transform: translateY(125.563px)}
45.455% {transform: translateY(133.153px)}
47.273% {transform: translateY(150.000px)}
50.000% {transform: translateY(134.362px)}
54.545% {transform: translateY(148.299px)}
55.000% {transform: translateY(150.000px)}
59.091% {transform: translateY(138.745px)}
61.818% {transform: translateY(150.000px)}
63.636% {transform: translateY(141.102px)}
67.727% {transform: translateY(150.000px)}
68.182% {transform: translateY(147.532px)}
72.727% {transform: translateY(150.000px)}
77.273% {transform: translateY(150.000px)}
81.818% {transform: translateY(150.000px)}
86.364% {transform: translateY(150.000px)}
90.909% {transform: translateY(150.000px)}
95.455% {transform: translateY(150.000px)}
100.000% {transform: translateY(150.000px)}
}
<div></div>
Лично я бы рекомендовал поддержку JavaScript, хотя, как он является более точным для этих типов анимации, и, как уже упоминалось, он может легко адаптироваться к новым требованиям.
CSS для физики? – Downgoat
У вас есть два варианта: вы можете либо реализовать реальные правила физики с помощью java-скрипта, либо использовать математическую функцию для моделирования подпрыгивания. В действительности шар должен следовать параболической дуге и должен иметь постоянное ускорение. Я думаю, вы должны попробовать играть с квадратичной анимацией – steve
@ vihan1086, что я хочу, чтобы имитировать «как можно более реальные» физические события с помощью css, например, падающий мяч –