UIBezierPath 动画 - 对象固定在左上角

Posted

技术标签:

【中文标题】UIBezierPath 动画 - 对象固定在左上角【英文标题】:Animation with UIBezierPath - Object gets fixed on the top left corner 【发布时间】:2020-05-07 11:43:37 【问题描述】:

我正在尝试快速创建一个动画,以使一些气球从屏幕底部浮动到顶部。然而,在动画的中间,一个气球会固定在屏幕的左上角,即使动画结束也不会消失。

请观看此视频以了解我在说什么:

https://imgur.com/a/tyS0Q5u

这是我的代码。我真的不知道我做错了什么。

func presentVictoryView() 

        blackView.isHidden = false

        for _ in 0 ... 20 

            let objectView = UIView()
            objectView.translatesAutoresizingMaskIntoConstraints = false
            objectView.frame = CGRect(x: 50, y: 50, width: 20, height: 100)
            //objectView.backgroundColor = .clear
            //objectView.alpha = CGFloat(0.9)
            objectView.isHidden = false


            let ballon = UILabel()
            ballon.translatesAutoresizingMaskIntoConstraints = false
            ballon.frame = CGRect(x: 50, y: 50, width: 20, height: 100)
            //ballon.backgroundColor = .clear
            //ballon.alpha = CGFloat(0.9)
            ballon.text = "????"
            ballon.font = UIFont.systemFont(ofSize: 60)
            objectView.addSubview(ballon)


            NSLayoutConstraint.activate([
                ballon.centerXAnchor.constraint(equalTo: objectView.centerXAnchor),
                ballon.centerYAnchor.constraint(equalTo: objectView.centerYAnchor)
            ])

            blackView.addSubview(objectView)

            let randomXOffset = Int.random(in: -120 ..< 200)

            let path = UIBezierPath()
            path.move(to: CGPoint(x: 270 + randomXOffset, y: 1000))
            path.addCurve(to: CGPoint(x: 100 + randomXOffset, y: -300), controlPoint1: CGPoint(x: 300 - randomXOffset, y: 600), controlPoint2: CGPoint(x: 70 + randomXOffset, y: 300))

            let animation = CAKeyframeAnimation(keyPath: "position")
            animation.path = path.cgPath
            animation.repeatCount = 1

            animation.duration = Double.random(in: 4.0 ..< 7.0)
            //animation.timeOffset = Double(arc4random_uniform(50))

            objectView.layer.add(animation, forKey: "animate position along path")

        

        //objectView.isHidden = true


        //self?.newGame()
    

感谢您的帮助! :)

【问题讨论】:

【参考方案1】:

您应该使用委托来检测动画的结束并删除bubbleView。

func presentVictoryView() 

    blackView.isHidden = false

    for _ in 0 ... 20 

        let objectView = UIView()
        objectView.translatesAutoresizingMaskIntoConstraints = false
        objectView.frame = CGRect(x: 50, y: 50, width: 20, height: 100)
        //objectView.backgroundColor = .clear
        //objectView.alpha = CGFloat(0.9)
        objectView.isHidden = false

        let ballon = UILabel()
        ballon.translatesAutoresizingMaskIntoConstraints = false
        ballon.frame = CGRect(x: 50, y: 50, width: 20, height: 100)
        //ballon.backgroundColor = .clear
        //ballon.alpha = CGFloat(0.9)
        ballon.text = "?"
        ballon.font = UIFont.systemFont(ofSize: 60)
        objectView.addSubview(ballon)

        NSLayoutConstraint.activate([
            ballon.centerXAnchor.constraint(equalTo: objectView.centerXAnchor),
            ballon.centerYAnchor.constraint(equalTo: objectView.centerYAnchor)
        ])

        blackView.addSubview(objectView)

        let randomXOffset = Int.random(in: -120 ..< 200)

        let path = UIBezierPath()
        path.move(to: CGPoint(x: 270 + randomXOffset, y: 1000))
        path.addCurve(to: CGPoint(x: 100 + randomXOffset, y: -300), controlPoint1: CGPoint(x: 300 - randomXOffset, y: 600), controlPoint2: CGPoint(x: 70 + randomXOffset, y: 300))

        let animation = CAKeyframeAnimation(keyPath: "position")
        animation.path = path.cgPath
        animation.repeatCount = 1

        // add these
        animation.fillMode = .forwards
        animation.isRemovedOnCompletion = false
        let delegate = BubbleAnimDelegate()
        delegate.didFinishAnimation = 
            objectView.removeFromSuperview()
        
        animation.delegate = delegate
        // upto here

        animation.duration = Double.random(in: 4.0 ..< 7.0)
        //animation.timeOffset = Double(arc4random_uniform(50))

        objectView.layer.add(animation, forKey: "animate position along path")

    
    //objectView.isHidden = true
    //self?.newGame()


class BubbleAnimDelegate: NSObject, CAAnimationDelegate 

    var didFinishAnimation: (()->Void)?

    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) 
        didFinishAnimation?()
    

【讨论】:

以上是关于UIBezierPath 动画 - 对象固定在左上角的主要内容,如果未能解决你的问题,请参考以下文章

如何在 draw(_:) 中为 UIBezierPath 设置动画?

iOS学习:CAShapeLayer与UIBezierPath动画

动画Bezier曲线,就像在iPhone屏幕上绘制一样

如何为 UIBezierPath 上的填充颜色变化设置动画?

iOS - 仅对 UIBezierPath 的“appendPath”进行动画处理

在自定义 UIView 中动画 UIBezierPath 不起作用