Tweening / Interpolating entre dos CGPaths / UIBeziers

Tengo un CAShapeLayer que contiene un CGPath. Usando la animación incorporada de iOS, puedo transformar fácilmente esta ruta en otra usando una animación:

CABasicAnimation *morph = [CABasicAnimation animationWithKeyPath:@"path"]; morph.fromValue = (id)myLayer.path; mayLayer.path = [self getNewPath]; morph.toValue = (id)myLayer.path; morph.duration = 0.3; [myLayer addAnimation:morph forKey:nil]; 

Eso funciona perfectamente.

Sin embargo, me gustaría cambiar gradualmente entre estas rutas durante una operación de arrastre. Para hacer esto, necesito poder recuperar la ruta interpolada en cualquier punto durante el arrastre. ¿Hay alguna manera de preguntarle a iOS por esto?

En realidad, esto es mucho más simple de lo que piensas y usa animaciones con “no” velocidad (pausa). Ahora con la animación pausada agregada a la capa, puede cambiar la compensación de tiempo para saltar a un tiempo específico dentro de la animación.

Si no planea ejecutar la animación por sí mismo (es decir, solo controlarla manualmente), le sugiero que cambie la duración de la animación a 1. Esto significa que cambia la compensación de tiempo de 0 a 1 al pasar de 0% a 100% Si su duración fue 0.3 (como en su ejemplo), entonces establecería el desplazamiento de tiempo a un valor entre 0 y 0.3 en su lugar.

Implementación

Como dije antes, hay muy poco código involucrado en este pequeño truco.

  1. (Opcional) Establezca la duración en 1.0
  2. Establezca la speed de la capa (sí se ajustan a CAMediaTiming ) o la animación a 0.0
  3. Durante el gesto de arrastrar o deslizar (como en mi ejemplo) configure el timeOffset de la capa o animación (dependiendo de lo que hizo en el paso 2).

Así es como configuré mi capa de animación + forma

 CABasicAnimation *morph = [CABasicAnimation animationWithKeyPath:@"path"]; morph.duration = 1.; // Step 1 morph.fromValue = (__bridge id)fromPath; morph.toValue = (__bridge id)toPath; [self.shapeLayer addAnimation:morph forKey:@"morph shape back and forth"]; self.shapeLayer.speed = 0.0; // Step 2 

Y la acción del control deslizante:

 - (IBAction)sliderChanged:(UISlider *)sender { self.shapeLayer.timeOffset = sender.value; // Step 3 } 

Puedes ver el resultado final a continuación. Feliz encoding!

enter image description here