2010-12-27 23 views
10

Chciałem animować obiekt obrazu, przesuwając go wzdłuż określonej krzywej. Nie jest to krzywa ogólna ani losowa, lecz krzywa podążająca określoną ścieżką na ekranie.Przesuwanie obiektu wzdłuż krzywej w rozwoju iPhone'a

Obecnie ręcznie podaję listę współrzędnych x i y ścieżki, którą chcę przesunąć obiekt obrazu, ustawiając za każdym razem jego ramkę. Jest to żmudny proces w tym sensie, że ustawiam określone współrzędne X i Y ścieżki i przesuwanie obrazu wzdłuż niej. Czy istnieje skuteczniejszy sposób na zrobienie tego?

Czy istnieje sposób, że mogę określić, powiedzmy, około 15 - 20 punktów i czy krzywa jest przesunięta wzdłuż tych, aby przesunąć obiekt? Każdy inny sposób, aby to osiągnąć? Każda pomoc byłaby bardzo cenna. Dzięki.

Odpowiedz

10

Można użyć kombinacji UIBezierPath i CAKeyFrameAnimation. Znalazłem bardzo przydatny wpis na blogu dotyczący tego tematu.

http://oleb.net/blog/2010/12/animating-drawing-of-cgpath-with-cashapelayer/

Oto uproszczona wersja tego, co kiedyś (to tylko ożywia rysunek kwadratu):

UIBezierPath *customPath = [UIBezierPath bezierPath]; 
[customPath moveToPoint:CGPointMake(100,100)]; 
[customPath addLineToPoint:CGPointMake(200,100)]; 
[customPath addLineToPoint:CGPointMake(200,200)]; 
[customPath addLineToPoint:CGPointMake(100,200)]; 
[customPath addLineToPoint:CGPointMake(100,100)]; 

UIImage *movingImage = [UIImage imageNamed:@"foo.png"]; 
CALayer *movingLayer = [CALayer layer]; 
movingLayer.contents = (id)movingImage.CGImage; 
movingLayer.anchorPoint = CGPointZero; 
movingLayer.frame = CGRectMake(0.0f, 0.0f, movingImage.size.width, movingImage.size.height); 
[self.view.layer addSublayer:movingLayer]; 

CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; 
pathAnimation.duration = 4.0f; 
pathAnimation.path = customPath.CGPath; 
pathAnimation.calculationMode = kCAAnimationLinear; 
[movingLayer addAnimation:pathAnimation forKey:@"movingAnimation"]; 
+0

Dzięki. To pomogło. Zamiast addLineToPoint używam addQuadCurveToPoint i to się sprawdza. Kolejne pytanie tutaj. Jak wykryć koniec CAKeyFrameAnimation? Czy jest jakaś metoda delegata? Delegat animationDidStop nie został wywołany, gdy animacja została zatrzymana. – Nathan

+0

Przepraszamy. Mam to naprawione. Głupi błąd. Używałem delegata animationDidStop z UIView zamiast jednego dla CAAnimation. Teraz delegat też pracuje. – Nathan

0

W Swift-3 wersji @Jilouc: -

override func viewDidLoad() { 
     super.viewDidLoad() 
     addAdditiveAnimation() 
     initiateAnimation() 
    } 

    //curve which follows a particular path 
    func pathToTrace() -> UIBezierPath { 
      let path = UIBezierPath(ovalIn: CGRect(x: 120 , y: 120, width: 100, height: 100)) 
      let shapeLayer = CAShapeLayer() 
      shapeLayer.path = path.cgPath 
      shapeLayer.strokeColor = UIColor.red.cgColor 
      shapeLayer.lineWidth = 1.0 
      self.view.layer.addSublayer(shapeLayer) 
      return path 
     } 

func addAdditiveAnimation() { 
     let movement = CAKeyframeAnimation(keyPath: "position") 
     movement.path = pathToTrace().cgPath 
     movement.duration = 5 
     movement.repeatCount = HUGE 
     movement.calculationMode = kCAAnimationPaced 
     movement.timingFunctions = [CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)] 
     self.movement = movement 
} 

func createLayer() -> CALayer { 
     let layer = CALayer() 
     let image = UIImage(named: "launch.png") 
     layer.frame = CGRect(x: 0 , y: 0, width: (image?.size.width),height: (image?.size.height)) 
     layer.position = CGPoint(x: 5, y: 5) 
     layer.contents = image?.cgImage 
     layer.anchorPoint = .zero 
     layer.backgroundColor = UIColor.red.cgColor 
     //layer.cornerRadius = 5 
     self.view.layer.addSublayer(layer) 
     return layer 
    } 

func initiateAnimation() { 
     let layer = createLayer() 
     layer.add(self.movement, forKey: "Object Movement") 
    } 

Github Demo