È possibile uso CSS-only, ma vi permetterà di trascorrere un sacco di tempo per capire i numeri per il Bezier, le posizioni dei fotogrammi chiave, scala e così via, e per di più: un leggero cambiamento nel layout, "gravità", dimensioni, distanza e devi iniziare "all over" (almeno per la parte sopra).
animazioni CSS sono belle, ma si otterrà un risultato migliore con un po 'di codice JavaScript, per non parlare di avere molta più flessibilità se è necessario cambiare qualcosa -
- definire un vettore per la palla
- Definire un peso arbitrario
- calcolare il vettore e rimbalzo
- Bind valori risultanti per DOM elemento di trasformazioni (spedisce liscia risultato rispetto alla posizione).
- Animate usando
requestAnimationFrame
che si sincronizza per monitorare e fornisce animazioni altrettanto semplici come le animazioni CSS.
Esempio
Questo esempio mostra la base, non comprende l'ombra, ma ciò che rimane come esercizio per il lettore.
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>
Se si desidera un rimbalzo più accurata del piano, è possibile utilizzare il diff di posizione effettiva a riflettere che così:
if (pos.y > bottom) {
var diff = pos.y - bottom;
pos.y = bottom - diff;
...
E se avete bisogno di questo per più elementi, basta creare un oggetto istanziabile che incorpori un riferimento all'elemento da animare, i calcoli ecc.
Se ora desideri cambiare direzione, punto di partenza, gravità e così via, devi solo aggiornare i rispettivi valori e tutto funziona senza problemi durante la riproduzione.
Esempio passo intermedio per la produzione di CSS chiave fotogrammi
È possibile modificare il codice qui sopra per sgranocchiare i numeri per un CSS-animazione.
Utilizzare il numero di frame e normalizzare l'intervallo di sequenza, eseguire i calcoli contando i frame. Quindi estrarre i valori per, diciamo ogni 10 fotogrammi e ogni rimbalzo, infine formattare i numeri come fotogrammi chiave.
Idealmente includerai sempre la posizione superiore e inferiore: puoi rilevarlo monitorando la direzione del valore y del vettore (il segno), non mostrato qui.
Ciò funzionerà come passo intermedio per produrre il CSS-regola che useremo in seguito:
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>");
Se ci afferra il risultato da quello e lo utilizza come CSS per il nostro ultima pagina, otteniamo questo risultato (mi dispiace, versione non prefissata solo in questa demo):
(Dovrai ovviamente modificarlo e ottimizzarlo, ma otterrai il succo.)
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>
Personalmente mi sento di raccomandare il supporto JavaScript anche se, come è più preciso per questo tipo di animazioni, e come già detto, si può facilmente adottare per nuove esigenze.
CSS per la fisica? – Downgoat
Hai due opzioni: puoi implementare regole fisiche reali con lo script java oppure puoi utilizzare una funzione matematica per modellare il bouncing. In realtà una palla dovrebbe seguire un arco parabolico e dovrebbe avere un'accelerazione costante. Penso che dovresti provare a giocare con un'animazione quadratica – steve
@ vihan1086 quello che voglio è simulare eventi fisici "reali" con css, ad esempio una palla che cade –