algorithm - Algoritmo para implementar desplazamiento cinético
language-agnostic mobile (5)
¿Cuáles son algunos buenos algoritmos para crear una implementación de desplazamiento cinético? La característica se probará en una lista de IU personalizada. Mientras apuntar a dispositivos móviles (aquellos que no tienen esta función incorporada), cualquier algoritmo o ejemplo de código de diferentes campos de programación también puede ser adecuado.
¿Has mirado las funciones de relajación de Robert Penner?
http://www.robertpenner.com/easing/
IIRC estos fueron originalmente para Actionscript y han existido por mucho tiempo.
Acabo de agregar un widget de desplazamiento al marco de mi GUI móvil, así que pensé en compartir mi solución aquí.
Como se trata de un tema bastante complejo, decidí dividirlo en subtareas más pequeñas e independientes, de la siguiente manera:
Funcionalidad básica de desplazamiento : esta tarea consistía en manejar eventos de arrastre de la manera más simple, que consiste en desplazar los contenidos de acuerdo con la distancia y dirección de arrastre. Esto fue relativamente sencillo de implementar, el único aspecto complicado fue saber cuándo iniciar una operación de arrastre y cuándo pasar un evento tap a un widget secundario dentro del área desplazable.
Inercia de desplazamiento : este fue el más desafiante. La idea aquí es que el desplazamiento debe continuar por un tiempo después de que el usuario levanta el dedo, disminuyendo la velocidad hasta que se detenga por completo. Para esto necesitaba tener una idea de la velocidad de desplazamiento. Lamentablemente, no es preciso calcular la velocidad a partir de una sola muestra, por lo que mientras el usuario se desplaza, grabo los últimos eventos de N movimiento en un búfer circular, junto con el momento en el que ocurrió cada evento. Encontré que N = 4 funciona bien en el iPhone y en el HP TouchPad. Cuando se levanta el dedo, puedo calcular una velocidad de inicio aproximada para el desplazamiento inercial desde el movimiento grabado. Definí un coeficiente de aceleración negativo y utilicé fórmulas de movimiento estándar (ver here ) para dejar que el desplazamiento se redujera muy bien. Si la posición de desplazamiento alcanza un borde mientras aún está en movimiento, simplemente restablezco la velocidad a 0 para evitar que salga del rango (se aborda la parada abrupta a continuación).
Límites flexibles de desplazamiento : en lugar de detenerse abruptamente cuando el desplazamiento llega al final, quería que el widget se desplazara un poco, pero ofreciera resistencia. Para esto extendí el rango de desplazamiento permitido en ambos extremos por una cantidad que definí como una función de las dimensiones del widget. Descubrí que agregar la mitad del ancho o la altura en cada extremo funcionaba bien. El truco para dar al desplazamiento la sensación de que ofrece algo de resistencia fue ajustar las posiciones de desplazamiento visualizadas cuando están fuera de rango. Utilicé una reducción de escala más una función de deceleración para esto (aquí hay algunas buenas funciones de aceleración).
Comportamiento de resorte : dado que ahora es posible desplazarse más allá del rango válido, necesitaba una forma de volver a colocar el desplazamiento en una posición válida si el usuario lo dejaba fuera del alcance. Esto se logra ajustando el desplazamiento de desplazamiento cuando la rueda de desplazamiento se detiene en una posición fuera de rango. La función de ajuste que he encontrado para dar una buena apariencia elástica fue dividir la distancia desde la posición actual a la posición deseada por una constante y mover la compensación en esa cantidad. Cuanto mayor es la constante, más lento.
Barras de desplazamiento : el toque final fue agregar barras de desplazamiento superpuestas, que se desvanecen cuando se inicia el desplazamiento y se desvanecen cuando termina.
Bueno, creo que sería algo así como a) obtener la velocidad de la rapidez con que el usuario se desplazó b) cuando deja el dedo, desplaza automáticamente la lista pero con una velocidad decreciente con una velocidad inicial de la que tenía el usuario.
Dado que esto se solicitó originalmente, desde entonces he leído cuidadosamente el código fuente de pastrykit, el marco en el que Apple ha duplicado exactamente su desplazamiento cinético en javascript. No hay bucle de física de partículas. La velocidad del toque se mide en el momento exacto en que se levanta el dedo. A partir de ese momento, el desplazamiento se anima utilizando una función de relajación simple que utiliza la velocidad como parámetro de entrada.
Implementé uno recientemente. Estos son los pasos que tomé.
- Necesitas medir la velocidad de tu cursor (ya sea con el cursor del mouse o con el dedo)
- Implementa un simple bucle de física de partículas. La información sobre cómo hacer eso se puede encontrar here
- dale a tu partícula "límites" usando matemáticas derivadas del ancho de tu plano de desplazamiento, y el ancho de tu ventana gráfica
- continuamente Agregue la diferencia entre la velocidad del mouse y la velocidad de la partícula, a la velocidad de la partícula, de modo que la velocidad de la partícula "coincida" con la velocidad del mouse mientras se mueva.
- Deje de hacer el paso 4 tan pronto como el usuario levante su dedo. El ciclo de la física se ocupa de la inercia.
- Agregue sus florituras personales, como los márgenes "de parachoques", y los puntos de "anclaje" de desplazamiento suave que operan en la paradoja de zeno para calcular el movimiento.
- Casi lo olvido: tome las coordenadas derivadas de arriba, y úselo como la ubicación de su plano de desplazamiento.
Probablemente abriré este código pronto. ¿Qué tan pronto necesitas esto?
editar: cambió el enlace. Lo siento, señaló ligeramente la página incorrecta. edit2: ¿o no? De todos modos, la página original a la que me he vinculado era el primer enlace de la página actualmente enlazada.