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
(Don't forget to link and then import QuartzCore
, if you're using iOS 6 or prior)
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")
}
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:
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.
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)
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.