Motion System
Relevant source files
The following files were used as context for generating this wiki page:
- Sources/SwiftDitherKit/DitherMotion.swift
- Sources/SwiftDitherKit/DitherRasterView.swift
- Sources/SwiftDitherKit/DitherSparkles.swift
- Examples/MotionDemo/MotionDemo/MotionDemoView.swift
- Tests/SwiftDitherKitTests/DitherMotionTests.swift
- Sources/SwiftDitherKit/DitherTypes.swift
- Sources/SwiftDitherKit/DitherPolarCharts.swift
- Sources/SwiftDitherKit/DitherCartesianCharts.swift
The Motion System in SwiftDitherKit governs the visual transitions, entrance animations, and idle effects applied to dithered charts. It is designed to provide a responsive user experience that respects system accessibility settings while maintaining the aesthetic of ordered-dither rendering. The system handles three primary motion types: initial entrance animations, data update crossfades, and periodic "sparkle" effects for idle states. Sources: README.md, Sources/SwiftDitherKit/DitherMotion.swift:7-9
High-level animation logic is encapsulated in DitherMotion, while the coordination of state transitions for rendered rasters is managed by DitherAnimatedRaster. The system automatically adjusts its behavior when UIAccessibility.isReduceMotionEnabled is active, replacing complex movements with simple opacity fades. Sources: Sources/SwiftDitherKit/DitherMotion.swift:10-33, Sources/SwiftDitherKit/DitherRasterView.swift:11-30
Animation Architecture
The architecture relies on a state-driven decision engine that compares the DitherRasterMotionState of the previous frame against the incoming frame to determine the appropriate transition. Sources: Sources/SwiftDitherKit/DitherMotion.swift:51-57
Motion State and Decision Engine
The system uses a DitherRasterMotionDecision enum to choose between replacing content immediately, crossfading, replaying an entrance, or settling an animation. Sources: Sources/SwiftDitherKit/DitherMotion.swift:94-99
Key Animation Constants
| Constant | Value | Description |
|---|---|---|
defaultEntranceDuration | 0.28s | Standard duration for initial chart reveals. |
updateDuration | 0.22s | Duration for crossfading between different data states. |
reducedMotionDuration | 0.14s | Shortened duration used when Reduce Motion is enabled. |
transitionBlur | 1.5pt | Amount of blur applied during crossfade transitions. |
Sources: Sources/SwiftDitherKit/DitherMotion.swift:7-12
Transition Types and Timing Curves
SwiftDitherKit utilizes specific timingCurve animations to maintain a consistent feel across all components. Sources: Sources/SwiftDitherKit/DitherMotion.swift:14-33
- Entrance: Uses a curve of
(0.23, 1, 0.32, 1)to provide a snappy yet smooth reveal. Sources: Sources/SwiftDitherKit/DitherMotion.swift:15 - Update: Uses a more pronounced curve of
(0.77, 0, 0.175, 1)for data changes. Sources: Sources/SwiftDitherKit/DitherMotion.swift:19 - Radar Scale: Radar charts utilize a specific scaling function where the progress maps from
0.96to1.0. Sources: Sources/SwiftDitherKit/DitherMotion.swift:35-37
Reveal Styles
Transitions are visually masked based on the chart type, defined in DitherRevealStyle:
- Leading: Used for Cartesian charts (Area, Line) to reveal from left to right.
- Angular: Used for Pie/Donut charts to reveal in a circular sweep.
- Radial: Used for Radar charts to expand from the center.
Sources: Sources/SwiftDitherKit/DitherRasterView.swift:4-8, Sources/SwiftDitherKit/DitherRasterView.swift:305-316
Sparkle System
The Sparkle System provides a subtle, twinkling effect over dithered areas in Area, Line, and Sparkline charts. These are rendered as single-pixel (or cell-sized) highlights that blink periodically. Sources: Sources/SwiftDitherKit/DitherSparkles.swift:15-30
Sparkle Logic Flow
The sparkle field is generated based on the chart geometry and series color. A TimelineView drives the animation by sampling the twinkle intensity at a fixed interval. Sources: Sources/SwiftDitherKit/DitherRasterView.swift:233-242
Sparkle Parameters
| Property | Value | Description |
|---|---|---|
tickInterval | 0.1s | The frequency at which sparkle phases are updated. |
minimumVisibleAlpha | 0.55 | The threshold below which a sparkle is hidden. |
steadyTwinkle | 0.85 | The fixed intensity used when Reduce Motion is enabled. |
Sources: Sources/SwiftDitherKit/DitherSparkles.swift:105-108
Accessibility Integration
The Motion System reacts dynamically to the environment's accessibilityReduceMotion setting. When enabled, the system modifies its behavior as follows: Sources: Sources/SwiftDitherKit/InteractionAndAccessibility.md:38-43
- Eliminate Movement: Geometric reveals (like the leading edge sweep) are replaced by a simple opacity fade. Sources: Sources/SwiftDitherKit/DitherRasterView.swift:293-297
- Remove Blur: The
transitionBlurapplied during crossfades is reduced to 0. Sources: Sources/SwiftDitherKit/DitherMotion.swift:39-45 - Static Sparkles: Sparkles stop twinkling and maintain a steady alpha of
0.85. Sources: Sources/SwiftDitherKit/DitherSparkles.swift:125-127
static func incomingBlur(progress: CGFloat, reduceMotion: Bool) -> CGFloat {
reduceMotion ? 0 : (1 - clamped(progress)) * transitionBlur
}
Sources: Sources/SwiftDitherKit/DitherMotion.swift:39-41
Conclusion
The Motion System ensures that SwiftDitherKit's ordered-dither charts feel modern and interactive despite their low-fidelity aesthetic. By separating rendering (rasterization) from animation (Core Animation and SwiftUI transitions), the library achieves high-performance visual effects without taxing the Main Actor. The system's strict adherence to accessibility settings ensures that the motion remains inclusive for all users. Sources: README.md, Sources/SwiftDitherKit/DitherRasterView.swift:87-105