iOS 17 lets any Swift Charts chart scroll. chartScrollableAxes turns it on, the visible-domain
modifiers set the window size, and chartScrollTargetBehavior controls snapping.
Making a Chart Scroll
Enable an axis, then cap how much data is visible at once with chartXVisibleDomain (or
chartYVisibleDomain for vertical scrolling).
Chart(Array(zip(numbers.indices, numbers)), id: \.1) { index, number in
LineMark(
x: .value("Index", index),
y: .value("Number", number)
)
}
.chartScrollableAxes(.horizontal)
.chartXVisibleDomain(length: 10)
Scroll Position
chartScrollPosition(initialX:) sets where the chart starts. The binding overload reads and
writes: the binding updates as the user scrolls, and setting it programmatically moves the
visible region.
@State private var scrollPosition = 50
Chart { /* ... */ }
.chartScrollableAxes(.horizontal)
.chartScrollPosition(x: $scrollPosition)
.onChange(of: scrollPosition) { print(scrollPosition) }
Snapping Behavior
chartScrollTargetBehavior(.valueAligned(...)) snaps the scroll to data values. The unit
sets the minor snap step; majorAlignment decides where a full swipe lands, .page for one
visible region, or .unit(10) for a value step.
.chartScrollTargetBehavior(
.valueAligned(unit: 5, majorAlignment: .page)
)
Date axes align with DateComponents instead of numbers, for example snapping to hours while a
swipe jumps by days.
Chart(data) { item in
LineMark(
x: .value("Date", item.date, unit: .day),
y: .value("Value", item.value)
)
}
.chartScrollableAxes(.horizontal)
.chartScrollTargetBehavior(
.valueAligned(
matching: DateComponents(minute: 0),
majorAlignment: .matching(DateComponents(hour: 0))
)
)
Custom behaviors conform to ChartScrollTargetBehavior, the chart-flavored sibling of the
ScrollTargetBehavior protocol covered in the scrollview-target-behavior doc.