2015-06-06 19 views
12

Sto solo facendo un po 'di caricamento usando css e voglio che abbiano un comportamento reale, sto provando con lo animation-timing-function: cubic-bezier(1, 0, 1, 1), sembra buono ma non così reale come voglio, in un primo momento perché non so come fare cubic-bezier i parametri funzionano davvero, ho trovato il sito this e ho giocato con loro fino a quando non ho ottenuto qualcosa di carino.Come aggiungere fisica alle animazioni CSS?

Per riassumere, come aggiungere un reale comportamento fisico alla mia animazione?

SOLO PER FAVORE CSS, se non possibile, una soluzione JS è la benvenuta.

Ecco un esempio di FIDDLE.

Solo un suggerimento per guidare

Qualcosa come uno SCSS meno o con variabili fisiche costanti definite, o valori che è possibile aggiungere alla funzione e sumule il comportamento fisico può anche avere già mixins che simula un certo comportamento , Non so qualcosa di semplice e solo CSS.

Thx in anticipo

+0

CSS per la fisica? – Downgoat

+4

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

+0

@ vihan1086 quello che voglio è simulare eventi fisici "reali" con css, ad esempio una palla che cade –

risposta

10

È 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.

+0

Ottima risposta, sicuramente, seguirò il tuo consiglio. Molto apprezzato –

Problemi correlati