System Architecture Overview
Relevant source files
The following files were used as context for generating this wiki page:
SwiftDitherKit is a dependency-free SwiftUI library designed to render charts using ordered-dither textures. The system architecture is built around a decoupled rendering pipeline that separates chart logic from pixel-level dither generation. It supports various chart types, including area, line, bar, pie, donut, radar, and sparklines, while providing integrated motion effects and accessibility support.
The library architecture prioritizes performance by offloading dithered image rendering and caching to background tasks, away from the main actor. It utilizes a custom motion system to handle entrances, data crossfades, and idle "sparkle" animations, ensuring a responsive user interface even during complex transitions.
Sources: README.md:1-10, Sources/SwiftDitherKit/SwiftDitherKit.docc/SwiftDitherKit.md:1-15
Core Data Structures
The system architecture relies on a set of stable data types that define the structure of charts and their visual properties.
Data Models
The library uses three primary data structures to represent chart information:
- DitherDatum: Represents a single category (e.g., a point on the x-axis) and holds a dictionary of values mapped to series IDs.
- DitherSeries: Defines the visual configuration for a data series in Cartesian or radar charts, including color and dither variant.
- DitherSlice: Specifically for polar charts (pie/donut), combining value and visual configuration into a single object.
Sources: Sources/SwiftDitherKit/DitherTypes.swift:87-145
Visual Configuration Enums
Appearance is controlled through several strongly typed enumerations:
- DitherVariant: Defines the texture pattern (gradient, dotted, hatched, or solid).
- DitherBloom: Configures glow effects (low, high, aura) generated from the dithered raster.
- DitherStacking: Determines how Cartesian series share the value axis (overlaid, stacked, or percent-normalized).
Sources: Sources/SwiftDitherKit/DitherTypes.swift:49-74
Rendering Pipeline
The rendering architecture is designed for asynchronous execution to prevent blocking the UI thread. It consists of a top-level plot view that delegates to a specialized raster view.
The diagram above shows the flow from a high-level chart component to the generation and display of dithered pixels.
Asynchronous vs. Immediate Rendering
The system supports two rendering modes:
- Asynchronous (Default): Render requests are processed via
DitherRenderCache. If a frame is not cached, it is rendered in a background task. - Immediate: Used primarily for offscreen snapshots (e.g.,
ImageRenderer). This mode renders pixels during the view evaluation phase.
Sources: Sources/SwiftDitherKit/DitherRasterView.swift:145-175, Sources/SwiftDitherKit/SwiftDitherKit.docc/GettingStarted.md:44-55
Motion and Animation System
SwiftDitherKit implements a custom motion engine that manages transitions between different chart states.
Transition Logic
The system uses a DitherRasterMotionDecision engine to determine the appropriate animation style when chart data or options change.
| Decision | Trigger Condition | Visual Result |
|---|---|---|
| None | No state change | No visual update |
| Replace | High-frequency changes or disabled animation | Immediate swap of frames |
| Crossfade | Data or selection changes | Smooth transition between two frames |
| Replay | replayToken increment | Restarts the entrance animation |
| Settle | Reduce Motion setting toggled | Immediate jump to final state |
Sources: Sources/SwiftDitherKit/DitherMotion.swift:76-105
Idle Animations (Sparkles)
Area, line, and sparkline charts feature an idle "sparkle" effect. These are not part of the static dithered image but are rendered via a TimelineView using a Canvas.
- DitherSparkleField: Pre-calculates sparkle positions based on chart geometry.
- DitherSparkleMotion: Calculates alpha and flare values based on a 0.1s tick interval.
- Reduce Motion: If enabled, sparkles remain static and non-flared.
Sources: Sources/SwiftDitherKit/DitherSparkles.swift:1-140, Sources/SwiftDitherKit/DitherRasterView.swift:295-320
Interaction Architecture
Interaction is handled through a dedicated layer that sits on top of the rendered raster.
The sequence diagram illustrates how user gestures are converted into selection state and subsequent visual updates.
Selection and Scrubbing
Charts manage selection through an optional Binding<String?>. Area and line charts use the visible series polygon as tap targets, while bar charts use exact rectangles. Scrubbing (dragging across the chart) updates a hoverIndex, which triggers the display of a DitherTooltip and highlights specific data points.
Sources: Sources/SwiftDitherKit/DitherCartesianCharts.swift:300-350, Sources/SwiftDitherKit/SwiftDitherKit.docc/InteractionAndAccessibility.md:1-15
Accessibility Integration
Despite the decorative nature of the dithered pixels, the library provides a semantic representation of data to assistive technologies.
| Component | Description |
|---|---|
| DitherAccessibility | A struct for localized strings (title, summary, axis labels). |
| AXChartDescriptor | Converts internal data to Apple's chart accessibility format. |
| Content Direction | Cartesian charts use .leftToRight; Polar/Radar use .radialClockwise. |
Sources: Sources/SwiftDitherKit/DitherAccessibility.swift:1-25, Sources/SwiftDitherKit/DitherCartesianAccessibility.swift:12-45, Sources/SwiftDitherKit/DitherPieAccessibility.swift:10-40
System Constraints and Constants
The architecture defines specific limits and defaults for visual consistency and performance:
- Backing Size: Raster resolution is typically half the proposed view size (two-point cells) but capped to prevent memory issues on large surfaces.
- Color Palette: Includes seven built-in presets (green, blue, purple, pink, orange, red, grey) based on the original Dither Kit.
- Animation Timing: Default entrance duration is 0.28s, while updates/crossfades typically take 0.22s.
Sources: Sources/SwiftDitherKit/DitherTypes.swift:31-45, Sources/SwiftDitherKit/DitherMotion.swift:6-10
The architecture of SwiftDitherKit ensures that the unique visual style of dithered charts does not compromise SwiftUI's performance or accessibility standards. By decoupling the rendering, motion, and data layers, the system provides a robust framework for high-performance data visualization.