Idle Sparkles
Relevant source files
The following files were used as context for generating this wiki page:
- Sources/SwiftDitherKit/DitherSparkles.swift
- Sources/SwiftDitherKit/DitherRasterView.swift
- Sources/SwiftDitherKit/DitherTypes.swift
- Sources/SwiftDitherKit/SwiftDitherKit.docc/InteractionAndAccessibility.md
- Tests/SwiftDitherKitTests/DitherSparkleTests.swift
- Sources/SwiftDitherKit/DitherCartesianCharts.swift
Idle Sparkles is a visual effects system within SwiftDitherKit that renders occasional blinking glints over specific chart types. This system is primarily used in DitherAreaChart, DitherLineChart, and DitherSparkline to provide a dynamic, "shimmering" aesthetic while the charts are in an idle state.
The system consists of a generation logic that determines sparkle placement based on chart data geometry and a motion engine that handles the temporal "twinkle" effect. When "Reduce Motion" is enabled via system settings, the sparkles transition to a steady, non-blinking state to ensure accessibility compliance.
Sources: Sources/SwiftDitherKit/DitherSparkles.swift:1-125, Sources/SwiftDitherKit/SwiftDitherKit.docc/InteractionAndAccessibility.md:37-41
Architecture and Data Structures
The sparkles system is built around three primary data structures that define the position, visual state, and motion of the glints.
Key Data Structures
| Structure | Description |
|---|---|
DitherSparkle | Represents a single glint with specific coordinates (x, y), an initial phase, and a color. |
DitherSparkleField | A collection of sparkles mapped to a specific chart's dimensions and data series. |
DitherSparkleSample | The calculated alpha values for a sparkle's center and flare at a specific point in time. |
Sources: Sources/SwiftDitherKit/DitherSparkles.swift:3-12, Sources/SwiftDitherKit/DitherSparkles.swift:101-105
Sparkle Field Generation
The DitherSparkleField is generated by sampling the geometric bands of a chart. It computes the "top" and "floor" of series data to ensure sparkles appear within the rendered area of the chart.
The logic excludes .bar charts from showing sparkles. For .line charts, the "glow" area is used to constrain the Y-coordinate, while for area charts, the sparkles are distributed between the upper and lower bounds of the series.
Sources: Sources/SwiftDitherKit/DitherSparkles.swift:18-67, Tests/SwiftDitherKitTests/DitherSparkleTests.swift:42-55
Motion Engine
The motion of the sparkles is governed by the DitherSparkleMotion enum, which uses a time-based "tick" system to calculate the current visibility and opacity of each sparkle.
Twinkle Logic
The system calculates a twinkle value using a sine wave based on the current time tick and the sparkle's unique phase. This creates an asynchronous blinking effect across the field.
- Tick Interval: 0.1 seconds.
- Steady Twinkle: 0.85 (used when Reduce Motion is active).
- Minimum Visible Alpha: 0.55.
Sources: Sources/SwiftDitherKit/DitherSparkles.swift:107-111, Sources/SwiftDitherKit/DitherSparkles.swift:118-125
Rendering Sequence
Sparkles are rendered using a SwiftUI Canvas within the DitherSparkleOverlay.
Visual Components
The Glint and Flare
A sparkle consists of a 1x1 pixel center. When the twinkle intensity reaches a "peak" (typically > 0.9), the system renders a four-point flare—additional pixels offset by one unit in the cardinal directions (up, down, left, right).
Sources: Sources/SwiftDitherKit/DitherRasterView.swift:368-385, Tests/SwiftDitherKitTests/DitherSparkleTests.swift:57-73
Accessibility: Reduce Motion
When accessibilityReduceMotion is detected in the environment, the following changes occur:
- Motion stops: The
TimelineViewis bypassed or provides a static tick. - Opacity is fixed: Sparkles remain at a steady alpha (
0.595center alpha) without blinking. - Flares are removed: Peak glints (flares) are not rendered to avoid sharp visual changes.
Sources: Sources/SwiftDitherKit/DitherRasterView.swift:310-315, Sources/SwiftDitherKit/DitherSparkles.swift:122-125, Tests/SwiftDitherKitTests/DitherSparkleTests.swift:75-90
Integration with Raster Rendering
Sparkles are integrated into the DitherRasterLayers as an overlay. Crucially, they are rendered separately from the dithered raster image, allowing the sparkles to animate at 10Hz (0.1s interval) while the underlying chart raster remains cached and static.
| File Path | Responsibility |
|---|---|
DitherSparkles.swift | Data models and motion math. |
DitherRasterView.swift | DitherSparkleOverlay component and Canvas drawing. |
DitherCartesianCharts.swift | Provides input for sparkle field generation. |
Sources: Sources/SwiftDitherKit/DitherRasterView.swift:290-302, Sources/SwiftDitherKit/DitherSparkles.swift:108
Conclusion
The Idle Sparkles system provides a lightweight, performant way to add visual interest to static charts. By decoupling sparkle motion from the main chart rendering and respecting system-wide accessibility settings, it maintains high technical standards for both performance and inclusivity.