You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- Added convenience inits for Path classes to remove the need to pass in a PathState manually
- Added setupPerformanceMode convenience method to Path classes (which call PathState's method internally)
Copy file name to clipboardExpand all lines: Guides/MoveableClasses.md
+11-18Lines changed: 11 additions & 18 deletions
Original file line number
Diff line number
Diff line change
@@ -135,8 +135,7 @@ let motion = PhysicsMotion(target: view,
135
135
Here's a basic example. We've supplied the `PathMotion` with a basic CGPath via a `PathState` object, an easing equation, and we've told it to reverse back to the beginning once it travels to the end. Notice though how we've defined a `startPosition` and `endPosition`. This tells the `PathMotion` it should start the animation at a point 10% from the beginning of the path and end the animation at a point 80% along the path's length. If you leave these parameters out it will travel the full distance.
In this example note that we've added an `edgeBehavior` parameter to the `PathMotion` initializer. There are two types of edge behaviors – `stopAtEdges` (the default), which simply stops motion once the animated point gets to either specified edge point, and `contiguousEdges`, which tells the `PathMotion` that the path's starting and ending edges should be treated as connected, contiguous points. If the animated point travels beyond the path's edge, as can happen with some easing equation classes like `EasingElastic` and `EasingBack`, the motion will continue in the current direction at the beginning of the other edge. This behavior type is useful with closed paths like polygonal shapes to create a seamless animation.
The `startPosition` and `endPosition` values can also be flipped. Doing so will make the point travel along the path from the end of the path towards the beginning in its forward motion. In this example, the motion point will start at 80% along the path and travel "backwards" to 20%. If you added a `reverses` option, then at the end of the motion it would reverse along the path back to 80%.
> Note that because it is mathematically complex to find all points on a CGPath, large, complex paths can present performance challenges for `PathMotion` to animate along. Fortunately, `PathMotion` comes with a performance mode. When this mode is activated, `PathState` generates a lookup table which it uses to find points on the path in O(n) time. While this increases setup time, it significantly improves performance while the motion is running, for instance from 10% down to 1% CPU usage. To use performance mode, call the async method `setupPerformanceMode()`on the `PathState` instance before starting the `PathMotion`. This method will run the lookup table generation code on a background queue and return when complete. For most reasonably large paths this should take under a second.
170
+
> Note that because it is mathematically complex to find all points on a CGPath, large, complex paths can present performance challenges for `PathMotion` to animate along. Fortunately, `PathMotion` comes with a performance mode. When this mode is activated, `PathState` generates a lookup table which it uses to find points on the path in O(n) time. While this increases setup time, it significantly improves performance while the motion is running, for instance from 10% down to 1% CPU usage. To use performance mode, call the async method `setupPerformanceMode()`before starting the `PathMotion`, as shown in the below example. This method will run the lookup table generation code on a background queue and return when complete. For most reasonably large paths this should take under a second.
174
171
```swift
175
172
Task {
176
-
awaitpathState?.setupPerformanceMode()
173
+
awaitmotion?.setupPerformanceMode()
177
174
motion?.start()
178
175
}
179
176
```
@@ -185,9 +182,8 @@ Task {
185
182
Here's a basic example. We've supplied the `PathPhysicsMotion` with a basic CGPath via a `PathState` object, an easing equation, and we've told it to reverse back to the beginning once it travels to the end. Notice though how we've defined a `startPosition` and `endPosition`. This tells the `PathPhysicsMotion` it should start the animation at a point 10% from the beginning of the path and end the animation at a point 80% along the path's length. If you leave these parameters out it will have the full length of the path to travel along.
let config =PhysicsConfiguration(velocity: 500, friction: 0.4)
190
-
motion =PathPhysicsMotion(path: pathState,
186
+
motion =PathPhysicsMotion(path: path.cgPath,
191
187
configuration: config,
192
188
startPosition: 0.1,
193
189
endPosition: 0.8)
@@ -197,19 +193,17 @@ motion.start()
197
193
In this second example we're going to turn on collision detection and add a `restitution` value. Technically, collisions are turned on any time the `stopAtEdges` edge behavior is chosen, but adding a `restitution` value will cause a change in the motion. This value enables the object to collide and "bounce" off the starting and ending points when a point reaches them. The `restitution` value determines the elasticity of the object, which in effect determines how much velocity the object retains after colliding with an edge. A `restitution` value of 0.0 (the default if no value is provided) results in no bouncing at all, while a value of 1.0 results in no energy being lost in the collision. By default the collision points are at the start and end of the path, but if you specify your own start and end points those will be used instead.
let config =PhysicsConfiguration(velocity: 600, friction: 0.4, restitution: 0.8)
202
-
motion =PathPhysicsMotion(path: pathState,
197
+
motion =PathPhysicsMotion(path: path.cgPath,
203
198
configuration: config)
204
199
motion.start()
205
200
```
206
201
207
202
Although `PathPhysicsMotion` uses a physics simulation instead of specifying discrete ending values, we can still apply `repeats` and `reverses` options. Repeating and reversing act in the same way as `Motion` and interacts with `MoveableCollection` classes as you would expect.
The `startPosition` and `endPosition` values can also be flipped. Doing so will make the point travel along the path from the end of the path towards the beginning in its forward motion. Be aware that if you do this, the velocity should also be a negative value in order for the point to travel in the correct direction. In this example, the motion point will start at 80% along the path and travel "backwards" to 20%.
let config =PhysicsConfiguration(velocity: -600, friction: 0.4, restitution: 0.8)
224
-
motion =PathPhysicsMotion(path: pathState,
217
+
motion =PathPhysicsMotion(path: path.cgPath,
225
218
configuration: config,
226
219
startPosition: 0.8,
227
220
endPosition: 0.2)
228
221
motion.start()
229
222
```
230
223
231
224
> [!IMPORTANT]
232
-
> Note that because it is mathematically complex to find all points on a CGPath, large, complex paths can present performance challenges for `PathPhysicsMotion` to animate along. Fortunately, `PathPhysicsMotion` comes with a performance mode. When this mode is activated, the `PathState` object generates a lookup table which it uses to find points on the path in O(n) time. While this increases setup time, it significantly improves performance while the motion is running, for instance from 10% down to 1% CPU usage. To use performance mode, call the async method `setupPerformanceMode()`on the `PathState` instance before starting the `PathPhysicsMotion`. This method will run the lookup table generation code on a background queue and return when complete. For most reasonably large paths this should take under a second.
225
+
> Note that because it is mathematically complex to find all points on a CGPath, large, complex paths can present performance challenges for `PathPhysicsMotion` to animate along. Fortunately, `PathPhysicsMotion` comes with a performance mode. When this mode is activated, the `PathState` object generates a lookup table which it uses to find points on the path in O(n) time. While this increases setup time, it significantly improves performance while the motion is running, for instance from 10% down to 1% CPU usage. To use performance mode, call the async method `setupPerformanceMode()`before starting the `PathPhysicsMotion`, as shown in the below example. This method will run the lookup table generation code on a background queue and return when complete. For most reasonably large paths this should take under a second.
MotionMachine provides a modular, powerful, and generic platform for manipulating values, whether that be animating UI elements or interpolating property values in your own classes. It offers sensible default functionality that abstracts most of the hard work away, allowing you to focus on your work. While it is type-agnostic, MotionMachine does support most major UIKit types out of the box and provides syntactic sugar to easily manipulate them. But it's also easy to dive in and modify for your own needs, whether that be custom motion classes, supporting custom value types, or new easing equations.
@@ -166,7 +166,7 @@ You can add MotionMachine to an Xcode project by adding it as a Swift package de
166
166
## Compatibility
167
167
168
168
MotionMachine currently requires:
169
-
* Swift 5.5 or above
169
+
* Swift 5.10 or above
170
170
* Xcode 16+
171
171
* iOS 13.0 or later, tvOS 13.0 or later
172
172
@@ -182,7 +182,7 @@ MotionMachine currently requires:
182
182
183
183
## Credits
184
184
185
-
MotionMachine was created by [Brett Walker](https://twitter.com/petsound). It is loosely based on the author's Objective-C library [PMTween](https://github.com/poetmountain/PMTween).
185
+
MotionMachine was created by [Brett Walker](https://bsky.app/profile/petsound.bsky.social). It is loosely based on the author's Objective-C library [PMTween](https://github.com/poetmountain/PMTween).
0 commit comments