Перемещение объекта по кривой в разработке для iPhone

Я хотел анимировать объект изображения, перемещая его по определенной кривой. Это не общая или случайная кривая, а скорее кривая, которая следует определенному пути на экране.

В настоящее время я вручную указываю список координат x и y пути, по которому я хочу, чтобы объект изображения перемещался, каждый раз устанавливая его кадр. Это трудоемкий процесс в том смысле, что я задаю конкретные координаты x и y пути и перемещаю изображение по нему. Есть ли более эффективный способ сделать это?

Есть ли способ, которым я могу указать, скажем, около 15-20 точек и провести вдоль них кривую для перемещения объекта? Любой другой способ добиться этого? Любая помощь приветствуется. Спасибо.


person Nathan    schedule 27.12.2010    source источник


Ответы (2)


Вы можете использовать комбинацию UIBezierPath и CAKeyFrameAnimation. Я нашел очень полезную запись в блоге, посвященную этой теме.

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

Вот упрощенная версия того, что я использовал (она просто анимирует рисование квадрата):

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"];
person Jilouc    schedule 27.12.2010
comment
Спасибо. Это помогло. Вместо addLineToPoint я использую addQuadCurveToPoint, и это работает. Другой вопрос здесь. Как определить конец CAKeyFrameAnimation? Есть ли для этого метод делегата? Делегат animationDidStop не был вызван при остановке анимации. - person Nathan; 28.12.2010
comment
Прости. Исправил это. Глупая ошибка. Я использовал делегат animationDidStop для UIView вместо делегата для CAAnimation. Теперь делегат тоже работает. - person Nathan; 28.12.2010

В версии Swift-3 @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

person Shrawan    schedule 05.01.2017