Animating between two bezier path shapes

后端 未结 3 801
忘掉有多难
忘掉有多难 2021-01-31 12:39

I found it tricky to animate a UIImageView between two states: its original rectangle frame, and a new shape created with a UIBezierPath. There are man

3条回答
  •  误落风尘
    2021-01-31 13:10

    The first important point is to construct the two bezier paths similarly, so the rectangle is a (trivial) analogue to the more complex shape.

    // the complex bezier path
    let initialPoint = CGPoint(x: 0, y: 0)
    let curveStart = CGPoint(x: 0, y: (rect.size.height) * (0.2))
    let curveControl = CGPoint(x: (rect.size.width) * (0.6), y: (rect.size.height) * (0.5))
    let curveEnd = CGPoint(x: 0, y: (rect.size.height) * (0.8))
    let firstCorner = CGPoint(x: 0, y: rect.size.height)
    let secondCorner = CGPoint(x: rect.size.width, y: rect.size.height)
    let thirdCorner = CGPoint(x: rect.size.width, y: 0)
    
    var myBezierArc = UIBezierPath()
    myBezierArc.moveToPoint(initialPoint)
    myBezierArc.addLineToPoint(curveStart)
    myBezierArc.addQuadCurveToPoint(curveEnd, controlPoint: curveControl)
    myBezierArc.addLineToPoint(firstCorner)
    myBezierArc.addLineToPoint(secondCorner)
    myBezierArc.addLineToPoint(thirdCorner)
    

    The simpler 'trivial' bezier path, that creates a rectangle, is exactly the same but the controlPoint is set so that it appears to not be there:

    let curveControl = CGPoint(x: 0, y: (rect.size.height) * (0.5))
    

    ( Try removing the addQuadCurveToPoint line to get a very strange animation! )

    And finally, the animation commands:

    let myAnimation = CABasicAnimation(keyPath: "path")
    
    if (isArcVisible == true) {
        myAnimation.fromValue = myBezierArc.CGPath
        myAnimation.toValue = myBezierTrivial.CGPath
    } else {
        myAnimation.fromValue = myBezierTrivial.CGPath
        myAnimation.toValue = myBezierArc.CGPath
    }       
    myAnimation.duration = 0.4
    myAnimation.fillMode = kCAFillModeForwards
    myAnimation.removedOnCompletion = false
    
    myImageView.layer.mask.addAnimation(myAnimation, forKey: "animatePath")
    

    If anyone is interested, the project is here.

提交回复
热议问题