JEL JEL - 1 year ago 99
Swift Question

Dynamic UIBezierPath for Animations

I want to create an animation where an object animates its position along a

. The trouble I am having is making this
dynamic meaning that it works on all screen sizes.

The spaceship in the gif above follows a "U" shape

I use this "U" shape
and it works, here is the code:

func animateAlongPath() {
// Create and add image to view
let flyingSaucerImage = UIImage(named: "flying-saucer")!
let flyingSaucerImageView = UIImageView(image: flyingSaucerImage)

flyingSaucerImageView.frame = CGRect(x: 100, y: 100, width: flyingSaucerImage.size.width, height: flyingSaucerImage.size.height)

// Create "U" shape path for animation (path code created in PaintCode)
let path = UIBezierPath()
path.moveToPoint(CGPointMake(59.5, 81.5))
path.addCurveToPoint(CGPointMake(66.5, 91.5), controlPoint1: CGPointMake(63.64, 84.13), controlPoint2: CGPointMake(62.62, 85.9))
path.addCurveToPoint(CGPointMake(81.5, 110.5), controlPoint1: CGPointMake(72.31, 99.88), controlPoint2: CGPointMake(75.91, 103.08))
path.addCurveToPoint(CGPointMake(109.5, 142.5), controlPoint1: CGPointMake(88.44, 119.71), controlPoint2: CGPointMake(102.39, 135.23))
path.addCurveToPoint(CGPointMake(145.5, 156.5), controlPoint1: CGPointMake(122.47, 155.76), controlPoint2: CGPointMake(129.15, 157.54))
path.addCurveToPoint(CGPointMake(237.5, 81.5), controlPoint1: CGPointMake(185.04, 153.99), controlPoint2: CGPointMake(237.5, 81.5))

let pathAnimation = CAKeyframeAnimation(keyPath: "position")
pathAnimation.path = path.CGPath // Use "U" shape path for animation
pathAnimation.calculationMode = kCAAnimationPaced
pathAnimation.timingFunctions = [CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)]
pathAnimation.duration = 1
pathAnimation.removedOnCompletion = false
pathAnimation.fillMode = kCAFillModeForwards

flyingSaucerImageView.layer.addAnimation(pathAnimation, forKey: nil)
flyingSaucerImageView.layer.position = path.currentPoint

The problem is that the
is not dynamic. It works great on the iPhone 6 device screen size, but does not work great on any other device size since it is static. I tried using PaintCode to create dynamic paths with variables, but just can't get it to work.

Any ideas?

Answer Source

PaintCode can generate code for resizable UIBezierPaths using Frames.

Put the Bezier inside a Frame object and then set desired autoresizing springs (all flexible). The resulting code will be parametrized with CGRect/NSRect and will use relative coefficients to calculate bezier points.

There’s also a video tutorial about Dynamic Shapes if you want to get more into depth.

PaintCode Bezier in Frame