Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ios Swift Animate a view in non linear path

I am trying to animate a UIView through non linear path(i'm not trying to draw the path itself) like this :

object animated through a curve

The initial position of the view is determinated using a trailing and bottom constraint (viewBottomConstraint.constant == 100 & viewTrailingConstraint.constant == 300) I am using UIView.animatedWithDuration like this :

viewTrailingConstraint.constant = 20
viewBottomConstraint.constant = 450
UIView.animateWithDuration(1.5,animation:{
    self.view.layoutIfNeeded()
},completition:nil)

But it animate the view in a linear path.

like image 611
LHIOUI Avatar asked Dec 02 '15 13:12

LHIOUI


2 Answers

You can use keyFrame animation with path

    let keyFrameAnimation = CAKeyframeAnimation(keyPath:"position")
    let mutablePath = CGPathCreateMutable()
    CGPathMoveToPoint(mutablePath, nil,50,200)
    CGPathAddQuadCurveToPoint(mutablePath, nil,150,100, 250, 200)
    keyFrameAnimation.path = mutablePath
    keyFrameAnimation.duration = 2.0
    keyFrameAnimation.fillMode = kCAFillModeForwards
    keyFrameAnimation.removedOnCompletion = false
    self.label.layer.addAnimation(keyFrameAnimation, forKey: "animation")

Gif

About this function

void CGContextAddQuadCurveToPoint (
   CGContextRef _Nullable c,
   CGFloat cpx,
   CGFloat cpy,
   CGFloat x,
   CGFloat y
);

(cpx,cpy) is control point,and (x,y) is end point enter image description here

like image 158
Leo Avatar answered Nov 12 '22 13:11

Leo


Leo's answer of using Core Animation and CAKeyframeAnimation is good, but it operates on the view's "presentation layer" and only creates the appearance of moving the view to a new location. You'll need to add extra code to actually move the view to it's final location after the animation completes. Plus Core Animation is complex and confusing.

I'd recommend using the UIView method animateKeyframesWithDuration:delay:options:animations:completion:. You'd probably want to use the option value UIViewKeyframeAnimationOptionCalculationModeCubic, which causes the object to move along a curved path that passes through all of your points.

You call that on your view, and then in the animation block, you make multiple calls to addKeyframeWithRelativeStartTime:relativeDuration:animations: that move your view to points along your curve.

I have a sample project on github that shows this and other techniques. It's called KeyframeViewAnimations (link)

Edit:

(Note that UIView animations like animateKeyframes(withDuration:delay:options:animations:completion:) don't actually animate your views along the path you specify. They use a presentation layer just like CALayer animations do, and while the presentation layer makes the view look like it's moving along the specified path, it actually snaps from the beginning position to the end position at the beginning of the animation. UIView animations do move the view to its destination position, where CALayer animations move the presentation layer while not moving the layer/view at all.)

Another subtle difference between Leo's path-based UIView animation and my answer using UIView animateKeyframes(withDuration:delay:options:animations:completion:)is that CGPath curves are cubic or quadratic Bezier curves, and my answer animates using a different kind of curve called a Katmull-Rom spline. Bezier paths start and end at their beginning and ending points, and are attracted to, but don't pass through their middle control points. Catmull-Rom splines generate a curve that passes through every one of their control points.

like image 7
Duncan C Avatar answered Nov 12 '22 14:11

Duncan C