Pregunta

Lo que se entiende por facilitar la función en el contexto de la animación. Parece que Dojo, JQuery, Silverlight, Flex y otros sistemas de IU tienen la noción de función de facilidad. ¿No pude localizar una buena explicación de las funciones de facilitación? ¿Alguien puede explicar el concepto de facilitar las funciones, o señalar una buena explicación de ellas, estoy interesado en el concepto que no en los detalles específicos de un marco?

¿Se utiliza estrictamente para la ubicación o es general y se puede aplicar a cualquier propiedad de un objeto?

¿Fue útil?

Solución

Una función de flexibilización suele ser una función que describe el valor de una propiedad dado un porcentaje de integridad. Diferentes marcos usan variaciones ligeramente diferentes, pero el concepto es fácil de comprender una vez que se obtiene la idea, pero probablemente sea mejor mirar algunos ejemplos.

Primero veamos la interfaz que cumplirán todas nuestras funciones de flexión.

Nuestras funciones de flexión tomarán varios argumentos:

  • Porcentaje completo: (0.0 a 1.0).
  • Elaspedtime: el número de milisegundos que la animación ha estado ejecutando
  • StartValue: el valor para comenzar (o el valor cuando el porcentaje completo es del 0%)
  • Endvalue: el valor para terminar (o el valor cuando el porcentaje completo es del 100%)
  • Duración total: la longitud total deseada de la animación en milisegundos

Y devolverá un número que represente el valor en el que se debe establecer la propiedad.

Nota: Esta es la misma firma que JQuery usa para sus funciones de flexión, que tomaré prestado para ejemplos.

Lo más fácil de entender es una facilidad lineal:

var linear = function(percent,elapsed,start,end,total) {
    return start+(end-start)*percent;
}

Y ahora para poner esto en uso:

Digamos que teníamos una animación que iba a ir por 1000 milisegundos y se suponía que comenzaría a las 0 y terminaría a los 50. Pasar esos valores a nuestra función de flexibilización debería decirnos cuál debería ser el valor real:

linear(0, 0, 0,50, 1000)        // 0
linear(0.25, 250, 0, 50, 1000)  // 12.5
linear(0.5, 500, 0, 50, 1000)   // 25
linear(0.75, 750, 0, 50, 1000)  // 37.5
linear(1.0, 1000, 0, 50, 1000)  // 50

Este es un adolescente bastante sencillo (sin juego de palabras). Es una interpolación lineal simple. Si tuviera un gráfico de valor frente a tiempo, sería una línea recta:

Linear ease

Echemos un vistazo a una función de flexibilización un poco más complicada, una facilidad cuadrática en:

var easeInQuad = function (x, t, b, c, d) {
    return c*(t/=d)*t + b;
}

Y veamos los mismos resultados, utilizando las mismas entradas que antes:

easeInQuad(0, 0, 0, 50, 1000)      // 0
easeInQuad(0.25, 250, 0, 50, 1000) // 3.125
easeInQuad(0.5, 500, 0, 50, 1000)  // 12.5
easeInQuad(0.75, 750, 0, 50, 1000) // 28.125
easeInQuad(1, 1000, 0, 50, 1000)   // 50

Observe que los valores son muy diferentes a nuestra facilidad lineal. Comienza muy lento, luego se acelera a su punto final. Con un 50% de finalización de la animación, solo ha llegado a un valor de 12.5, que es una cuarta parte de la distancia real entre el start y end valores que hemos especificado.

Si tuviéramos que graficar esta función, se vería algo así:

Quad-Ease-In

Ahora echemos un vistazo a una facilidad básica:

var easeOutQuad = function (x, t, b, c, d) {
    return -c *(t/=d)*(t-2) + b;
};

Esto esencialmente hace la curva de aceleración "opuesta" de una facilidad. Comienza rápidamente y luego se desacelera a su valor final:

Ease out

Y luego hay funciones que alivian tanto dentro como fuera:

var easeInOutQuad = function (x, t, b, c, d) {
    if ((t/=d/2) < 1) return c/2*t*t + b;
    return -c/2 * ((--t)*(t-2) - 1) + b;
};

EaseInOut

Esta función comenzará lentamente y terminará lentamente, alcanzando su velocidad máxima en el medio.

Hay un montón de flexibilización/interpolaciones que puede usar: lineal, cuadradica, cúbica, cuarta, quint, sinusoidal. Y hay funciones de facilitación especializada como Bounce y Elastic, que tienen las suyas.

Por ejemplo, una facilidad elástica en:

var easeInElastic = function (x, t, b, c, d) {
    var s=1.70158;var p=0;var a=c;
    if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
    if (a < Math.abs(c)) { a=c; var s=p/4; }
    else var s = p/(2*Math.PI) * Math.asin (c/a);
    return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
},

Elastic ease in

Quizás alguien más pueda explicar la parte matemática real detrás de la interpolación, porque, sinceramente, no soy un mago matemático. Pero ese es el principio básico de las funciones de flexión en sí.

Cuando comienzas una adolescencia/animación, el motor de animación recuerda los valores de arranque y finalización que deseas. Luego, cada vez que se actualiza, sus figuras de cuánto tiempo ha pasado. Llama a la función de facilitación suministrada con los valores para determinar el valor que se debe establecer la propiedad. Mientras todas las funciones de flexión implementen la misma firma, se pueden cambiar con facilidad, y el motor de animación central no tiene que saber la diferencia. (Lo que hace una excelente separación de preocupaciones).

Notarás que he evitado hablar de x y y posiciones explícitamente, porque Easing no tiene nada específicamente que ver con la posición per se. Una función de flexibilización solo define una transición entre los valores de inicio y finalización. Esos podrían ser x coordenadas, o un color, o la transparencia de un objeto.

Y, de hecho, en teoría, podría aplicar una función de flexibilización diferente para interpolar para diferentes propiedades. Esperemos que esto ayude a arrojar algo de luz sobre la idea básica.

Y aquí hay realmente un Ejemplo genial (que usa una firma ligeramente diferente, pero es el mismo principio) para jugar para tener la idea de cómo la flexibilización se relaciona con la posición.


Editar

Aquí hay un poco jsfiddle Tiré para demostrar algunos de los usos básicos en JavaScript. Observe que el top la propiedad se interpone usando Bounce y el left La propiedad se interpone con un quad. Use el control deslizante para simular el bucle de renderizado.

Ya que todas las funciones en el easing El objeto tiene la misma firma, puede intercambiar cualquiera de ellos el uno por el otro. En este momento, la mayoría de estas cosas son todas codificadas (cosas como los valores de inicio y finalización, las funciones de adolescencia que se usan y la duración de la animación), pero en un ejemplo del mundo real de un ayudante de animación, querrás aprobar En las siguientes propiedades:

  • La propiedad a cambiar
  • El valor de inicio (o si se queda undefined luego use su valor actual)
  • El valor final
  • La duración de la animación debería ser
  • La referencia a la función de interpolación que desea usar.

El motor de animación realizaría un seguimiento de estas configuraciones durante la duración de la animación y durante cada ciclo de actualización, utilizaría el argumento de entrega para calcular el nuevo valor de propiedades.

Otros consejos

Una función de flexibilización es un algoritmo que controla la velocidad de una animación para dar un efecto deseado (rebotar, acercar y lentamente, etc.).

Mira qué MSDN tiene que decir sobre ellos Para un poco más de detalle.

Me gustaría publicar mi respuesta a esta vieja pregunta a pesar de que tiene una respuesta aceptada. 32 bitkid ha hecho la explicación necesaria. Lo que agregaré es la implementación práctica básica, porque no pude encontrar una (que también publiqué un pregunta sobre eso).

Tome esta simple animación lineal, por ejemplo. Dudo que requiera explicaciones ya que el código se explica por sí mismo. Calculamos un valor de incremento constante que no cambia con el tiempo y en cada iteración, aumentamos la posición de la caja. Estamos modificando la variable de posición directamente y luego aplicándola en el cuadro.

Jsfiddle

var box = document.getElementById("box");

var fps           = 60;
var duration	  = 2;                                   // seconds
var iterations	  = fps * duration;                      // 120 frames
var startPosition = 0;                                   // left end of the screen
var endPosition	  = window.innerWidth - box.clientWidth; // right end of the screen
var distance	  = endPosition - startPosition;         // total distance
var posIncrement  = distance / iterations;               // change per frame
var position	  = startPosition;                       // current position

function move() {
  position += posIncrement;              // increase position
  if (position >= endPosition) {         // check if reached endPosition
    clearInterval(handler);              // if so, stop interval
    box.style.left = endPosition + "px"; // jump to endPosition
    return;                              // exit function
  }
  box.style.left = position + "px";      // move to the new position
}

var handler = setInterval(move, 1000/fps); // run move() every 16~ millisecond
body {
	background: gainsboro;
}
#box {
	width: 100px;
	height: 100px;
	background: white;
	box-shadow: 1px 1px 1px rgba(0,0,0,.2);
	position: absolute;
	left: 0;
}
<div id="box"></div>


Ahora, agreguemos la facilidad. Comenzamos simple usando linear (sin aliviar). Resultará la misma animación anterior, pero el enfoque es diferente. Esta vez, no modificaremos la variable de posición directamente. Lo que modificaremos es el tiempo.

function linear(time, begin, change, duration) {
    return change * (time / duration) + start;
}

Primero, hablemos de los parámetros.

  • time: el tiempo transcurrido
  • begin: Valor inicial de una propiedad (ancho, izquierda, margen, opacidad, etc.)
  • change: desplazamiento, (valor final - valor de inicio)
  • duration: tiempo total que tomará la animación

time y duration están directamente relacionados. Si tienes una animación de 2 segundos, aumenta time y pasarlo a la función de flexión linear. La función devolverá una posición que indica que el cuadro debe estar en esa posición en el momento dado.

Digamos que estoy moviendo una caja de 0 a 100 en 2 segundos. Si quiero obtener la posición de la caja, digamos a los 700 milisegundos, llamaría al linear función de la siguiente manera:

linear(0.7, 0, 100, 2);

Que volvería 35. 700 milisegundos Después de que comience la animación, la posición de Box estará a 35 px. Veamos esto en acción.

Jsfiddle

var box = document.getElementById("box");

var fps           = 60;
var duration	  = 2;                                   // seconds
var iterations	  = fps * duration;                      // 120 frames
var startPosition = 0;                                   // left end of the screen
var endPosition	  = window.innerWidth - box.clientWidth; // right end of the screen
var distance      = endPosition - startPosition;         // total distance
var timeIncrement = duration / iterations;
var position      = 0;
var time          = 0;

function move() {
	time += timeIncrement;
	position = linear(time, startPosition, distance, duration);
	if (position >= endPosition) {
		clearInterval(handler);
		box.style.left = endPosition + "px";
		return;
	}
	box.style.left = position + "px";
}

var handler = setInterval(move, 1000/fps);

function linear(time, begin, change, duration) {
	return change * (time / duration) + begin;
}
body {
	background: gainsboro;
}
#box {
	width: 100px;
	height: 100px;
	background: white;
	box-shadow: 1px 1px 1px rgba(0,0,0,.2);
	position: absolute;
	left: 0;
}
<div id="box"></div>


La Parth que necesita atención en este código es:

var timeIncrement = duration / iterations;
var time = 0;

function move() {
    time += timeIncrement;
    position = linear(time, startPosition, distance, duration);
    // ...

En la primera animación, modificamos directamente la variable de posición. Necesitábamos un valor de incremento de posición constante. La forma en que calculamos que es posIncrement = distance / iterations. Con la facilidad, ya no modificamos la variable de posición, sino la variable de tiempo. Por lo tanto, necesitamos un valor de incremento de tiempo. Lo calculamos de la misma manera que hicimos una posición incrementada, solo que esta vez nos dividimos duration por iterations. Aumentamos el tiempo con el incremento de tiempo y pasamos el tiempo para facilitar la función, y la función de flexión nos devuelve la siguiente posición que debe ocupar la caja.

total distance / iterations (frames) = position change per frame
total duration / iterations (frames) = time change per frame

Aquí hay algún gráfico para el ojo.

Ease function graph


Y, por último, un ejemplo de facilidad.

Jsfiddle

var box = document.getElementById("box");

var fps           = 60;
var duration      = 2;                                   // seconds
var iterations    = fps * duration;                      // 120 frames
var startPosition = 0;                                   // left end of the screen
var endPosition   = window.innerWidth - box.clientWidth; // right end of the screen
var distance      = endPosition - startPosition;         // total distance
var timeIncrement = duration / iterations;
var time          = 0;
var position      = 0;

function move() {
  time += timeIncrement;
  position = easeInOutQuad(time, startPosition, distance, duration);
  if (position >= endPosition) {
    clearInterval(handler);
    box.style.left = endPosition + "px";
    return;
  }
  box.style.left = position + "px";
}

var handler = setInterval(move, 1000 / fps);

function easeInOutQuad(t, b, c, d) {
  if ((t /= d / 2) < 1) {
    return c / 2 * t * t + b;
  } else {
    return -c / 2 * ((--t) * (t - 2) - 1) + b;
  }
}
body {
	background: gainsboro;
}
#box {
	width: 100px;
	height: 100px;
	background: white;
	box-shadow: 1px 1px 1px rgba(0,0,0,.2);
	position: absolute;
	left: 0;
}
<div id="box"></div>

Es una propiedad (tamaño, forma, ubicación) de transición de un estado a otro.

Aquí hay algunos gráficos pequeños y ordenados que describen las funciones de flexión ofrecidas por JQuery UI.

http://jqueryui.com/demos/effect/esing.html

Piensa en la vida real no funciona como las computadoras. Piensa que no cambien de encendido hacia apagado y fuera de inmediato de inmediato como si no pudieras fingir que tu novia te amará de inmediato. Entonces, los científicos y las personas de la computadora (que no saben nada sobre tu novia), inventaron las funciones de relajación. Es como aplicar o cambiar cosas como animaciones no de manera inmediata. Entonces, si mueve un rectángulo de izquierda a la derecha, no se mueve como un robot: "Comience, muévase con una velocidad constante y se detenga inmediatamente", pero "comienza, aumenta la velocidad constantemente, disminuye la velocidad constantemente y se detiene finalmente". Así que facilitar es como dejar algunas animaciones, funciones, objetos o cosas, comportarse como cosas en la vida real. Cada efecto de facilidad define un comportamiento, por eso tenemos efectos de facilidad "elásticos", "que rebotan", etc.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top