Cartesian Charts
Relevant source files
The following files were used as context for generating this wiki page:
Cartesian charts in SwiftDitherKit are SwiftUI views designed to render categorical data points along a horizontal axis against numeric values on a vertical axis. Unlike standard vector-based charts, these views utilize an ordered-dither rendering technique to create unique textures and visual effects, such as "bloom" glows and "sparkle" animations.
The system supports four primary types of Cartesian visualizations: area charts, line charts, bar charts, and sparklines. These are all built upon a shared private infrastructure that handles layout, interaction, and asynchronous raster generation to ensure high performance even during complex animations or data transitions.
Sources: DitherCartesianCharts.swift:65-71, DitherCartesianCharts.swift:130-136, DitherCartesianCharts.swift:192-198, DitherTypes.swift:144-148
Architecture and Components
The Cartesian chart system is organized into a hierarchical structure where public-facing views wrap a centralized rendering and interaction logic.
Component Hierarchy
The internal DitherCartesianChart view acts as the primary coordinator, managing state for selection and hovering while composing the plot area with supplemental "chrome" such as legends and axes.
This diagram shows the structural relationship between public chart views and the internal components responsible for rendering and user interaction.
Sources: DitherCartesianCharts.swift:284-315, DitherCartesianCharts.swift:349-397
Key Data Structures
The charts rely on standardized models to represent data points and visual series:
| Structure | Description | Key Fields |
|---|---|---|
DitherDatum | Represents one category along the x-axis. | id, label, values: [String: Double] |
DitherSeries | Configures the appearance of a specific value set. | id, label, color, variant |
DitherCartesianOptions | High-level configuration for layout and behavior. | stacking, bloom, animate, interactive |
Sources: DitherTypes.swift:97-101, DitherTypes.swift:115-120, DitherCartesianCharts.swift:4-23
Rendering and Layout Logic
Cartesian charts calculate their geometry based on the provided data and the requested stacking mode. The rendering process is asynchronous, offloading the generation of dithered pixels from the main thread.
Stacking Modes
The DitherStacking enum defines how multiple series share the vertical value axis:
- Overlaid: Every series starts at zero, potentially overlapping others.
- Stacked: Positive values stack upwards; negative values stack downwards.
- Percent: Normalized stacking where values are represented as a percentage of the total for that category.
Sources: DitherTypes.swift:69-77, DitherCartesianCharts.swift:353-357
Raster Generation Flow
The system converts high-level chart definitions into a DitherCartesianRenderInput which the renderer uses to produce a checksum-cached raster image.
The sequence above illustrates the transition from SwiftUI state to a generated dithered bitmap via the asynchronous rendering pipeline.
Sources: DitherCartesianCharts.swift:363-397, DitherRendererTests.swift:23-40
Chrome and Interaction
"Chrome" refers to the non-dithered supporting elements that provide context to the data, such as axes, grids, and tooltips.
Visual Elements
- Axes and Grids:
DitherCartesianChromerenders the value axis ticks and category labels. It uses aDitherLinearScaleto map data values to coordinate space. - Legend:
DitherLegenddisplays interactive swatches for each series, allowing users to toggle selections. - Tooltip:
DitherTooltipappears during hover or drag gestures, showing precise values for the selected category.
Sources: DitherChartChrome.swift:150-184, DitherChartChrome.swift:11-40
Interaction Handling
Interaction is managed by the DitherCartesianInteractionLayer, which utilizes SwiftUI gestures to detect scrubbing and tapping.
// Sources/SwiftDitherKit/DitherCartesianCharts.swift:513-524
DragGesture(minimumDistance: 0, coordinateSpace: .local)
.onChanged { value in
update(location: value.location)
}
.onEnded { _ in
update(index: nil)
}
For bar charts, interaction uses band-based indexing (DitherGeometry.bandIndex), while area and line charts use nearest-point detection (DitherGeometry.nearestIndex).
Sources: DitherCartesianCharts.swift:505-534, DitherCartesianCharts.swift:540-545
Accessibility
SwiftDitherKit implements the AXChartDescriptorRepresentable protocol to provide semantic meaning to the dithered pixels. The DitherCartesianChartDescriptor generates a structured representation of the chart for assistive technologies.
| Feature | Implementation Detail |
|---|---|
| Category Axis | Derived from DitherDatum.label values. |
| Value Axis | Uses DitherLinearScale bounds and ticks. |
| Data Points | Each DitherSeries is exposed as an AXDataSeriesDescriptor. |
| Summaries | Dynamic strings describing categories, series count, and active selection. |
Sources: DitherCartesianAccessibility.swift:7-50, DitherCartesianAccessibility.swift:57-65
Sparklines
The DitherSparkline is a specialized, compact version of an area chart. It simplifies the Cartesian interface by removing axes, legends, and tooltips, focusing solely on a single data series.
// Sources/SwiftDitherKit/DitherCartesianCharts.swift:274-282
let options = DitherCartesianOptions(
margins: .sparkline,
bloom: bloom,
animate: animate,
interactive: false,
showsAxes: false,
showsLegend: false,
showsTooltip: false
)
Sources: DitherCartesianCharts.swift:245-283
Conclusion
Cartesian charts in this kit provide a bridge between retro-inspired dithered aesthetics and modern SwiftUI functionality. By centralizing the complex logic of stacking, scaling, and asynchronous rendering within DitherCartesianChart, the library offers a consistent API for various chart types while maintaining accessibility and interactive performance.