2013-08-22 7 views
26

Mam CAShapeLayer, który zawiera CGPath. Korzystając z wbudowanej animacji systemu iOS, można łatwo przekształcić tę ścieżkę w inną za pomocą animacji:Tweening/Interpolacja między dwoma CGPaths/UIBeziers

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]; 

To działa idealnie.

Chciałbym jednak stopniowo zmieniać się między tymi ścieżkami podczas operacji przeciągania. Aby to zrobić, muszę mieć możliwość pobrania interpolowanej ścieżki w dowolnym momencie przeciągania. Czy istnieje sposób, aby poprosić o to system iOS?

+0

W nietrywialnych przypadków, wybudowany w morfingu ścieżek staje się bezużyteczny dość szybko. Zobacz problem i wyjaśnienia opisane tutaj: http://stackoverflow.com/a/17864445/438982 – ipmcc

+0

To prawda, ale w moim przypadku przemiana wygląda dobrze ... – tarmes

Odpowiedz

77

Jest to o wiele prostsze niż na początku pomyślałeś i używasz animacji z "nie" prędkością (pauza). Teraz, po dodaniu animacji zatrzymanej do warstwy, możesz zmienić przesunięcie czasu, aby przejść do określonego czasu w animacji.

Jeśli nie planujesz uruchomienia animacji samodzielnie (tzn. Steruj nią ręcznie) sugerowałbym zmianę czasu trwania animacji na 1. Oznacza to, że zmieniasz przesunięcie czasowe z 0 na 1 podczas przenoszenia od 0% do 100%. Jeśli twój czas trwania wynosił 0,3 (jak w twoim przykładzie), zamiast tego ustawiałbyś przesunięcie czasowe na wartość między 0 a 0.3.

Realizacja

Jak powiedziałem wyżej, jest bardzo mało kod zaangażowany w tej małej sztuczki.

  1. (Opcjonalnie) Ustaw czas trwania do 1,0
  2. Ustawianie speed warstwy (tak one zgodne CAMediaTiming) lub animację do 0,0
  3. podczas gestu przeciągania lub suwaka (jak w moim przykładzie) ustaw timeOffset warstwy lub animacji (w zależności od tego, co zrobiłeś w kroku 2).

ten sposób skonfigurowałem mojego animacji + kształt warstwy

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 

a akcja suwak:

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

można zobaczyć wynik końcowy poniżej. Szczęśliwe kodowanie!

enter image description here

+0

Fantastyczne, dziękuję. Nie miałem pojęcia o istnieniu timeOffset. Co byś zrobił, gdybyś sam planował używać animacji? – tarmes

+0

@tarmes To zależy od specyfiki interakcji. Nadal można wstrzymać animację i zmienić przesunięcie czasowe (w tym przypadku od 0 do 0.3). Możesz wznowić animację, ponownie ustawiając prędkość ponownie na 1. Jeśli animacja jest uruchomiona, gdy chcesz z nią współdziałać, możesz pobrać aktualną wartość za pomocą opcji [layer convertTime: CACurrentMediaTime() fromLayer: nil] '. Aby uzyskać więcej informacji, zobacz [tę odpowiedź] (http://stackoverflow.com/a/3003922/608157). –

+6

Ta wspaniała technika zainspirowała mnie do zrobienia przycisku z ikoną ► (odtwarzanie) lub ❚❚ (pauza), która ładnie zmienia się pomiędzy tymi dwoma. Zobacz go w akcji: http://instagram.com/p/l6a8uDHDk7 A oto źródło: http://gist.github.com/raphaelschaad/9734463 –

Powiązane problemy