Animate a SwiftUI Shape morphing point count
Driving custom interpolation with animatableData.
Expose a continuous sides value as animatableData so SwiftUI interpolates it, then compute the path from that fractional value each frame.
WHAT THIS TESTS This probes whether you understand SwiftUI's animation engine: it interpolates a numeric quantity, the animatableData, and re-renders, rather than tweening arbitrary geometry. Path-count morphing forces you to parameterize the shape.
A GOOD ANSWER COVERS SwiftUI cannot interpolate two arbitrary paths with different numbers of points, because there is no defined correspondence between their vertices. Instead you make the Shape conform to Animatable and implement the animatableData computed property, whose type is VectorArithmetic, typically Double or AnimatablePair. animatableData holds the parameter that defines the shape, for example a fractional number of sides. When the value changes inside an animation, SwiftUI interpolates animatableData from the old to the new value over the duration and calls path(in:) for each interpolated value. Your path(in:) must therefore compute a valid polygon for a non-integer side count, distributing vertices evenly around a circle based on that fractional count.
COMMON WRONG ANSWERS Trying to crossfade or directly interpolate between a triangle path and a pentagon path. Storing the side count as an Int, which cannot be interpolated to fractional values. Forgetting that animatableData's type must conform to VectorArithmetic. Putting the animation on the wrong property.
LIKELY FOLLOW-UPS How AnimatablePair lets you animate two values at once, like sides and a corner radius. Why the data type must conform to VectorArithmetic. How this same mechanism powers animating custom Layout or text via animatableData. The relationship to GeometryEffect.
ONE CONCRETE EXAMPLE You define struct PolygonShape: Shape with var sides: Double, and var animatableData: Double { get { sides } set { sides = newValue } }. In path(in rect:) you compute the integer base count, distribute that many points evenly on a circle, and offset the last point's position by the fractional remainder so a value of 3.5 looks halfway between a triangle and a quad. When you animate sides from 3 to 5 with .easeInOut, SwiftUI feeds path(in:) values like 3.2, 3.8, 4.5, and the shape visibly morphs from triangle to pentagon.
Read the original → hackingwithswift.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.