Una mirada rápida a las matemáticas de las animaciones con JavaScript

 

 

 

  • Implemente rápidamente. Implementar inteligentemente
  • SmashingConf Friburgo 2024

  • Índice
    1. Pasar de 0 a 1 sin aburrirse
    2. No es un pecado, sólo un movimiento natural
    3. Círculos en la arena, vueltas y vueltas…
    4. Una rutina rápida de trazado DOM
      1. Resumen
    5. Otras lecturas

    Christian Heilmann nos ofrece una rápida introducción al uso de exponenciales y ondas sinusoidales y a trazar cosas en un círculo. Pruebe el código y juegue con los números. ¡Es sorprendente la cantidad de efectos interesantes que puedes crear con unos pocos cambios en el radio o multiplicando los ángulos!

     

    En la escuela odiaba las matemáticas. Era algo espantoso, seco y aburrido, con libros viejos y aburridos y problemas muy teóricos. Peor aún, muchas de las tareas eran repetitivas, con un simple cambio lógico en cada iteración (división de números a mano, diferenciales, etc.). Fue exactamente la razón por la que inventamos las computadoras. Basta decir que gran parte de mi tarea de matemáticas la hice mi confiable Commodore 64 y algunas líneas de Basic, y luego copié los resultados.

    Estas herramientas y las pocas lecciones de geometría que tuve me dieron el tiempo y la inspiración para hacer que las matemáticas fueran interesantes para mí. Lo hice ante todo creando efectos visuales que seguían reglas matemáticas en demostraciones, introducciones y otras cosas aparentemente sin sentido.

    Hay muchas matemáticas en las cosas visuales que hacemos, incluso si no nos damos cuenta. Si desea que algo parezca natural y se mueva naturalmente, debe agregarle un poco de física y redondeo. La naturaleza no funciona en ángulos rectos ni en aceleración lineal. Por eso los zombis en las películas dan tanto miedo. Esto se cubrió aquí antes en relación con la animación CSS , pero hoy profundicemos un poco más y veamos las matemáticas simples detrás de la apariencia suave.

    Pasar de 0 a 1 sin aburrirse

    Si acaba de comenzar a programar y se le pide que vaya de 0 a 1 con algunos pasos intermedios, probablemente realice un forbucle:

     

    for ( i = 0; i = 1; i += 0.1 ) { x = i; y = i;…}

    Esto daría como resultado una línea en un gráfico de 45 grados. Nada en la naturaleza se mueve con esta precisión:

    Una forma sencilla de hacer este movimiento un poco más natural sería simplemente multiplicar el valor por sí mismo:

    for ( i = 0; i = 1; i += 0.1 ) { x = i; y = i * i;}

    Esto significa que 0.1es 0.01, 0.2es 0.04, 0.3es 0.09, es, 0.4es 0.16, 0.5es 0.25y así sucesivamente. El resultado es una curva que comienza plana y luego se vuelve más pronunciada hacia el final:

    Puedes hacer esto aún más pronunciado si continúas multiplicando o usando la Math.pow()función "a la potencia de":

    for ( i = 0; i = 1; i += 0.1 ) { x = i; y = Math.pow( i, 4 );}

    Este es uno de los trucos de las funciones de aceleración utilizadas en bibliotecas como jQuery y YUI, así como en transiciones y animaciones CSS en los navegadores modernos.

    Puedes usar esto de la misma manera, pero hay una opción aún más simple para obtener un valor entre 0 y 1 que sigue un movimiento natural.

    No es un pecado, sólo un movimiento natural

    Las ondas sinusoidales son probablemente lo mejor que existe para lograr una animación fluida. Suceden en la naturaleza: presencia un manantial con un peso sobre él, las olas del océano, el sonido y la luz. En nuestro caso, queremos pasar de 0 a 1 sin problemas.

    Para crear un movimiento que vaya de 0 a 1 y vuelva a 0 suavemente, podemos utilizar una onda sinusoidal que vaya de 0 a π en unos pocos pasos. La onda sinusoidal completa que va de 0 a π × 2 (es decir, un círculo completo) daría como resultado valores de -1 a 1, y no queremos eso (todavía).

    var counter = 0;// 100 iterationsvar increase = Math.PI / 100;for ( i = 0; i = 1; i += 0.01 ) { x = i; y = Math.sin(counter); counter += increase;}

    Un breve comentario sobre los números del seno y el coseno: ambos Math.sin()y Math.cos()tomen como parámetro un ángulo que debe estar en radianes . Sin embargo, como seres humanos, los grados que van de 0 a 360 son mucho más fáciles de leer. Es por eso que puedes y debes convertir entre ellos con esta sencilla fórmula:

    var toRadian = Math.PI / 180;var toDegree = 180 / Math.PI;var angle = 30;var angleInRadians = angle * toRadian;var angleInDegrees = angleInRadians * toDegree;

    Volvamos a nuestras ondas sinusoidales. Puedes jugar mucho con esto. Por ejemplo, podrías usar el valor absoluto de un bucle completo de 2 × π:

    var counter = 0;// 100 iterationsvar increase = Math.PI * 2 / 100;for ( i = 0; i = 1; i += 0.01 ) { x = i; y = Math.abs( Math.sin( counter ) ); counter += increase;}

    Pero, de nuevo, esto parece sucio. Si desea subir y bajar completamente, sin una interrupción en el medio, entonces necesita cambiar los valores. Tienes que reducir la mitad del seno y luego agregarle 0,5:

    var counter = 0;// 100 iterationsvar increase = Math.PI * 2 / 100;for ( i = 0; i = 1; i += 0.01 ) { x = i; y = Math.sin( counter ) / 2 + 0.5; counter += increase;}

    Entonces, ¿cómo puedes usar esto? Tener una función que devuelve -1 a 1 a lo que sea que le alimentes puede ser genial. Todo lo que necesitas hacer es multiplicarlo por los valores que quieras y agregar un desplazamiento para evitar números negativos.

     

    Por ejemplo, mira esta demostración de movimiento sinusoidal :

    Se ve genial, ¿no? Muchos de los trucos ya están en el CSS:

    .stage { width:200px; height:200px; margin:2em; position:relative; background:#6cf; overflow:hidden;}.stage div { line-height:40px; width:100%; text-align:center; background:#369; color:#fff; font-weight:bold; position:absolute;}

    El stageelemento tiene una dimensión fija y está posicionado de forma relativa. Esto significa que todo lo que esté colocado absolutamente dentro de él será relativo al elemento mismo.

    El div dentro del escenario tiene 40 píxeles de alto y está posicionado de manera absoluta. Ahora, todo lo que tenemos que hacer es mover el div con JavaScript en una onda sinusoidal:

    var banner = document.querySelector( '.stage div' ), start = 0;function sine(){ banner.style.top = 50 * Math.sin( start ) + 80 + 'px'; start += 0.05;}window.setInterval( sine, 1000/30 );

    El valor inicial cambia constantemente y con ello Math.sin()obtenemos un bonito movimiento ondulatorio. Multiplicamos esto por 50 para obtener una onda más ancha y agregamos 80 píxeles para centrarla en el elemento del escenario. Sí, el elemento tiene 200 píxeles de alto y 100 es la mitad de eso, pero como el banner tiene 40 píxeles de alto, debemos restar la mitad para centrarlo.

    En este momento, este es un simple movimiento hacia arriba y hacia abajo. Sin embargo, nada te impide hacerlo más interesante. El factor multiplicador de 50, por ejemplo, podría ser una onda sinusoidal con un valor diferente:

    var banner = document.querySelector( '.stage div' ), start = 0, multiplier = 0;function sine(){ multiplier = 50 * Math.sin( start * 2 ); banner.style.top = multiplier * Math.sin( start ) + 80 + 'px'; start += 0.05;}window.setInterval( sine, 1000/30 );

    El resultado de esto es una pancarta que parece moverse tentativamente hacia arriba y hacia abajo. En el pasado, y en el muy lento Commodore 64, calcular la onda sinusoidal en vivo era demasiado lento. En cambio, teníamos herramientas para generar tablas de senos (matrices, por así decirlo) y las trazamos directamente. Una de las herramientas para crear excelentes ondas sinusoidales para que pudieras tener textos de desplazamiento rebotantes fue Wix Bouncer:

    Círculos en la arena, vueltas y vueltas…

    El movimiento circular es algo hermoso. Agrada a la vista, nos recuerda las ruedas que giran y la tierra en la que nos encontramos y, en general, tiene la sensación de que "esto no es algo de computadora". Las matemáticas para trazar algo en un círculo no son difíciles.

    Se remonta a Pitágoras , quien, según se rumorea, dibujó muchos círculos en la arena hasta encontrar su famoso teorema . Si quieres utilizar todo lo bueno que se deriva de este teorema, intenta encontrar un triángulo con un ángulo recto. Si la hipotenusa de este triángulo es 1, entonces puedes calcular fácilmente el cateto horizontal como el coseno del ángulo y el cateto vertical como el seno del ángulo:

     

    ¿Qué importancia tiene esto para un círculo? Bueno, es bastante sencillo encontrar un triángulo rectángulo en un círculo en cada punto del mismo: Artículos de danza y ballet

    Esto significa que si quieres trazar algo en un círculo (o dibujar uno), puedes hacerlo con un bucle y un seno y un coseno. Un círculo completo mide 360°, o 2 × π en radianes. Podríamos intentarlo, pero primero, es necesario crear algo de código de trazado.

    Una rutina rápida de trazado DOM

    Normalmente, mi arma preferida aquí sería el lienzo, pero para funcionar bien con navegadores más antiguos, hagámoslo en DOM simple. La siguiente función auxiliar agrega elementos div a un elemento de escenario y nos permite posicionarlos, cambiar sus dimensiones, establecer su color, cambiar su contenido y rotarlos sin tener que pasar por las molestas configuraciones de estilo de los elementos DOM.

    Plot = function ( stage ) { this.setDimensions = function( x, y ) { this.elm.style.width = x + 'px'; this.elm.style.height = y + 'px'; this.width = x; this.height = y; } this.position = function( x, y ) { var xoffset = arguments[2] ? 0 : this.width / 2; var yoffset = arguments[2] ? 0 : this.height / 2; this.elm.style.left = (x - xoffset) + 'px'; this.elm.style.top = (y - yoffset) + 'px'; this.x = x; this.y = y; }; this.setbackground = function( col ) { this.elm.style.background = col; } this.kill = function() { stage.removeChild( this.elm ); } this.rotate = function( str ) { this.elm.style.webkitTransform = this.elm.style.MozTransform = this.elm.style.OTransform = this.elm.style.transform = 'rotate('+str+')'; } this.content = function( content ) { this.elm.innerHTML = content; } this.round = function( round ) { this.elm.style.borderRadius = round ? '50%/50%' : ’; } this.elm = document.createElement( 'div' ); this.elm.style.position = 'absolute'; stage.appendChild( this.elm );};

    Lo único que podría ser nuevo aquí es la transformación con diferentes prefijos de navegador y el posicionamiento. La gente suele cometer el error de crear un div con las dimensiones wy hluego configurarlo xen yla pantalla. Esto significa que siempre tendrás que lidiar con el desplazamiento de la altura y el ancho. Al restar la mitad del ancho y el alto antes de colocar el div, realmente lo configuras donde lo deseas, independientemente de las dimensiones. He aquí una prueba :

    Ahora, usemos eso para trazar 10 rectángulos en un círculo , ¿de acuerdo?

    var stage = document.querySelector('.stage'), plots = 10; increase = Math.PI * 2 / plots, angle = 0, x = 0, y = 0;for( var i = 0; i plots; i++ ) { var p = new Plot( stage ); p.setBackground( 'green' ); p.setDimensions( 40, 40 ); x = 100 * Math.cos( angle ) + 200; y = 100 * Math.sin( angle ) + 200; p.position( x, y ); angle += increase;}

    Queremos 10 cosas en un círculo, entonces necesitamos encontrar el ángulo en el que queremos colocarlas. Un círculo completo es dos veces Math.PI, así que todo lo que tenemos que hacer es dividirlo. La posición xey de nuestros rectángulos se puede calcular según el ángulo en el que los queremos. × es el coseno y y es el seno, como se explicó anteriormente en la parte sobre Pitágoras. Todo lo que tenemos que hacer, entonces, es centrar el círculo que estamos pintando en el escenario ( 200,200es el centro del escenario), y listo. Hemos pintado un círculo con un radio de 100 píxeles en el lienzo en 10 pasos.

     

    El problema es que esto tiene una pinta terrible. Si realmente queremos trazar cosas en un círculo, entonces sus ángulos también deberían apuntar al centro, ¿verdad? Para ello, necesitamos calcular la tangente del cuadrado en ángulo recto, como se explica en esta encantadora página “Las matemáticas son divertidas” . En JavaScript, podemos usarlo Math.atan2()como atajo. El resultado se ve mucho mejor:

    var stage = document.querySelector('.stage'), plots = 10; increase = Math.PI * 2 / plots, angle = 0, x = 0, y = 0;for( var i = 0; i plots; i++ ) { var p = new Plot( stage ); p.setBackground( 'green' ); p.setDimensions( 40, 40 ); x = 100 * Math.cos( angle ) + 200; y = 100 * Math.sin( angle ) + 200; p.rotate( Math.atan2( y - 200, x - 200 ) + 'rad' ); p.position( x, y ); angle += increase;}

    Observe que la transformación de rotación en CSS nos ayuda mucho en este caso. De lo contrario, las matemáticas para rotar nuestros rectángulos serían mucho menos divertidas. Las transformaciones CSS también toman radianes y grados como valor. En este caso usamos rad; Si desea rotar en grados, simplemente utilícelo degcomo valor.

    ¿Qué tal animar el círculo ahora? Bueno, lo primero que debemos hacer es cambiar un poco el guión, porque no queremos tener que seguir creando nuevas tramas. Aparte de eso, todo lo que tenemos que hacer para rotar el círculo es seguir aumentando el ángulo inicial :

    var stage = document.querySelector('.stage'), plots = 10; increase = Math.PI * 2 / plots, angle = 0, x = 0, y = 0, plotcache = [];for( var i = 0; i plots; i++ ) { var p = new Plot( stage ); p.setBackground( 'green' ); p.setDimensions( 40, 40 ); plotcache.push( p );}function rotate(){ for( var i = 0; i plots; i++ ) { x = 100 * Math.cos( angle ) + 200; y = 100 * Math.sin( angle ) + 200; plotcache[ i ].rotate( Math.atan2( y - 200, x - 200 ) + 'rad' ); plotcache[ i ].position( x, y ); angle += increase; } angle += 0.06;}setInterval( rotate, 1000/30 );

    ¿Quieren más? ¿ Qué tal un mensaje de texto rotativo basado en esto? Lo complicado de esto es que también necesitamos girar los caracteres 90° en cada iteración:

    var stage = document.querySelector('.stage'), message = 'Smashing Magazine '.toUpperCase(), plots = message.length; increase = Math.PI * 2 / plots, angle = -Math.PI, turnangle = 0, x = 0, y = 0, plotcache = [];for( var i = 0; i plots; i++ ) { var p = new Plot( stage ); p.content( message.substr(i,1) ); p.setDimensions( 40, 40 ); plotcache.push( p );}function rotate(){ for( var i = 0; i plots; i++ ) { x = 100 * Math.cos( angle ) + 200; y = 100 * Math.sin( angle ) + 200; // rotation and rotating the text 90 degrees turnangle = Math.atan2( y - 200, x - 200 ) * 180 / Math.PI + 90 + 'deg'; plotcache[ i ].rotate( turnangle ); plotcache[ i ].position( x, y ); angle += increase; } angle += 0.06;}setInterval( rotate, 1000/40 );

    Una vez más, aquí no hay nada arreglado. Puedes hacer que el radio del círculo cambie constantemente , como hicimos anteriormente con el mensaje del banner rebotante (a continuación se muestra solo un extracto):

     

    multiplier = 80 * Math.sin( angle );for( var i = 0; i plots; i++ ) { x = multiplier * Math.cos( angle ) + 200; y = multiplier * Math.sin( angle ) + 200; turnangle = Math.atan2( y - 200, x - 200 ) * 180 / Math.PI + 90 + 'deg'; plotcache[ i ].rotate( turnangle ); plotcache[ i ].position( x, y ); angle += increase;}angle += 0.06;

    Y, por supuesto, también puedes mover el centro del círculo :

    rx = 50 * Math.cos( angle ) + 200;ry = 50 * Math.sin( angle ) + 200;for( var i = 0; i plots; i++ ) { x = 100 * Math.cos( angle ) + rx; y = 100 * Math.sin( angle ) + ry; turnangle = Math.atan2( y - ry, x - rx ) * 180 / Math.PI + 90 + 'deg'; plotcache[ i ].rotate( turnangle ); plotcache[ i ].position( x, y ); angle += increase;}angle += 0.06;

    Como consejo final, ¿qué tal si permitimos sólo un cierto rango de coordenadas ?

    function rotate() { rx = 70 * Math.cos( angle ) + 200; ry = 70 * Math.sin( angle ) + 200; for( var i = 0; i plots; i++ ) { x = 100 * Math.cos( angle ) + rx; y = 100 * Math.sin( angle ) + ry; x = contain( 70, 320, x ); y = contain( 70, 320, y ); turnangle = Math.atan2( y - ry, x - rx ) * 180 / Math.PI + 90 + 'deg'; plotcache[ i ].rotate( turnangle ); plotcache[ i ].position( x, y ); angle += increase; } angle += 0.06;}function contain( min, max, value ) { return Math.min( max, Math.max( min, value ) );}

    Resumen

    Esta fue solo una introducción rápida al uso de exponenciales y ondas sinusoidales y a trazar cosas en un círculo. Pruebe el código y juegue con los números. Es sorprendente la cantidad de efectos interesantes que puedes crear con unos pocos cambios en el radio o multiplicando los ángulos. Para que le resulte más fácil hacer esto, a continuación se muestran ejemplos en JSFiddle para jugar:

    • Mensaje de rebote sinusoidal
    • Mensaje de rebote de doble seno
    • Problema de compensación con el trazado
    • Distribuir elementos en un círculo.
    • Distribuir elementos en un círculo con ángulos correctos.
    • Girando un círculo de cajas
    • Mensaje giratorio oscilante
    • Mensaje giratorio en un movimiento circular.
    • Desplazador de mensajes rotado en caja

    Otras lecturas

    • Animaciones SVG y CSS con clip-path
    • Creando animaciones 'dibujadas a mano' con SVG
    • La nueva API de animación web
    • Técnicas prácticas de animación
    • Pautas y ejemplos de animación de la interfaz de usuario
    • Diseñar animaciones en Photoshop
    • Animaciones de interfaz de usuario de creación rápida de prototipos en Keynote

    (señor)Explora más en

    • Codificación
    • CSS
    • javascript
    • Técnicas
    • Animación





    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Una mirada rápida a las matemáticas de las animaciones con JavaScript

    Una mirada rápida a las matemáticas de las animaciones con JavaScript

    Implemente rápidamente. Implementar inteligentemente SmashingConf Friburgo 2024 Índice Pasar de 0 a 1 si

    programar

    es

    https://aprendeprogramando.es/static/images/programar-una-mirada-rapida-a-las-matematicas-de-las-animaciones-con-javascript-780-0.jpg

    2024-05-20

     

    Una mirada rápida a las matemáticas de las animaciones con JavaScript
    Una mirada rápida a las matemáticas de las animaciones con JavaScript

    Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

     

     

    Top 20