How to do a curve/arc animation with CAAnimation?

前端 未结 5 665
离开以前
离开以前 2021-01-30 09:35

I have an user interface where an item get deleted, I would like to mimic the \"move to folder\" effect in iOS mail. The effect where the little letter icon is \"thrown\" into t

5条回答
  •  失恋的感觉
    2021-01-30 10:08

    Using UIBezierPath

    (Don't forget to link and then import QuartzCore, if you're using iOS 6 or prior)

    Example code

    You could use an animation that will follow a path, conveniently enough, CAKeyframeAnimation supports a CGPath, which can be obtained from an UIBezierPath. Swift 3

    func animate(view : UIView, fromPoint start : CGPoint, toPoint end: CGPoint)
    {
        // The animation
        let animation = CAKeyframeAnimation(keyPath: "position")
    
        // Animation's path
        let path = UIBezierPath()
    
        // Move the "cursor" to the start
        path.move(to: start)
    
        // Calculate the control points
        let c1 = CGPoint(x: start.x + 64, y: start.y)
        let c2 = CGPoint(x: end.x,        y: end.y - 128)
    
        // Draw a curve towards the end, using control points
        path.addCurve(to: end, controlPoint1: c1, controlPoint2: c2)
    
        // Use this path as the animation's path (casted to CGPath)
        animation.path = path.cgPath;
    
        // The other animations properties
        animation.fillMode              = kCAFillModeForwards
        animation.isRemovedOnCompletion = false
        animation.duration              = 1.0
        animation.timingFunction        = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseIn)
    
        // Apply it
        view.layer.add(animation, forKey:"trash")
    }
    

    Understanding UIBezierPath

    Bezier paths (or Bezier Curves, to be accurate) work exactly like the ones you'd find in photoshop, fireworks, sketch... They have two "control points", one for each vertex. For example, the animation I just made:

    enter image description here

    Works the bezier path like that. See the documentation on the specifics, but it's basically two points that "pull" the arc towards a certain direction.

    Drawing a path

    One cool feature about UIBezierPath, is that you can draw them on screen with CAShapeLayer, thus, helping you visualise the path that it will follow.

    // Drawing the path
    let *layer          = CAShapeLayer()
    layer.path          = path.cgPath
    layer.strokeColor   = UIColor.black.cgColor
    layer.lineWidth     = 1.0
    layer.fillColor     = nil
    
    self.view.layer.addSublayer(layer)
    

    Improving the original example

    The idea of calculating your own bezier path, is that you can make the completely dynamic, thus, the animation can change the curve it's going to do, based on multiple factors, instead of just hard-coding as I did in the example, for instance, the control points could be calculated as follows:

    // Calculate the control points
    let factor : CGFloat = 0.5
    
    let deltaX : CGFloat = end.x - start.x
    let deltaY : CGFloat = end.y - start.y
    
    let c1 = CGPoint(x: start.x + deltaX * factor, y: start.y)
    let c2 = CGPoint(x: end.x                    , y: end.y - deltaY * factor)
    

    This last bit of code makes it so that the points are like the previous figure, but in a variable amount, respect to the triangle that the points form, multiplied by a factor which would be the equivalent of a "tension" value.

提交回复
热议问题