Hey Swifters đź‘‹ , Today we are going to dive into brand new 3D charts in SwiftUI. Introduced in iOS 26, Chart3D
brings depth (literally) to your visualizations. You can now plot data using the X, Y, and Z axes and rotate, tilt, and explore datasets in a much more immersive way. Let’s dig in.
Why Use 3D Charts?
2D charts are great until they aren’t. Say you are analyzing bike data from a city sharing service:
- Rider weight
- Bike frame size
- Trip duration
It’s hard to see all 3 in a single 2D chart. You would need 3 separate charts to compare 2 properties at a time. Wouldn’t it be better to have one chart that shows the full picture? Thats where 3D charts comes in.
Building A Chart3D
Let’s build a 3D chart that plots:
- X-axis: Rider weight (kg)
- Y-axis: Trip duration (min)
- Z-axis: Bike frame size (cm)
struct Ride: Identifiable {
let id = UUID()
let riderWeight: Double
let duration: Double
let bikeFrameSize: Double
let bikeType: String
}
let rides: [Ride] = [
Ride(riderWeight: 18, duration: 45, bikeFrameSize: 54, bikeType: "Road"),
Ride(riderWeight: 9, duration: 30, bikeFrameSize: 56, bikeType: "Hybrid"),
Ride(riderWeight: 13, duration: 12, bikeFrameSize: 58, bikeType: "Mountain"),
Ride(riderWeight: 31, duration: 25, bikeFrameSize: 52, bikeType: "Road"),
Ride(riderWeight: 20, duration: 40, bikeFrameSize: 60, bikeType: "Electric"),
]
struct RideChart: View {
var body: some View {
Chart3D(rides) { ride in
PointMark(
x: .value("Rider Weight (kg)", ride.riderWeight),
y: .value("Duration (min)", ride.duration),
z: .value("Frame Size (cm)", ride.bikeFrameSize)
)
.foregroundStyle(by: .value("Bike Type", ride.bikeType))
}
.chartXAxisLabel("Rider Weight (kg)")
.chartYAxisLabel("Duration (min)")
.chartZAxisLabel("Frame Size (cm)")
}
}

This single view now plots 3 variables beautifully.
Adjusting the View with .chart3DPose
Want to control the initial rotation of the chart? You can set the Chart3DPose
like this:
.chart3DPose(
Chart3DPose(
azimuth: .degrees(30), // left-right rotation
inclination: .degrees(15) // up-down tilt
)
)

This is useful for emphasizing clusters, highlighting specific data relationships and picking a “camera angle” that shows off your dataset.
Change the Projection Style
By default, 3D charts use orthographic projection, everything is the same size, regardless of distance. If you want depth, enable perspective:
.chart3DCameraProjection(.perspective)
Now the closer points appear larger, the distant ones shrink slightly and it feels more like a 3D scene which is great for apps on visionOS or with touch/gesture interaction.
Build A SurfacePlot
If you’re visualizing a mathematical function or prediction model (like regression or AI), SurfacePlot
is your best friend.
struct RideChart: View {
var body: some View {
Chart3D {
SurfacePlot(
x: "Speed",
y: "Distance",
z: "Time"
) { speed, time in
speed * time
}
}
.frame(width: 500, height: 400)
}
}

This plots a smooth 3D surface kind of like a 3D version of LineMark
. This is idea for physics simulations, predictive models and heatmaps with depth.
Styling the Surface
You can apply color gradients based on height or surface angle:
struct RideChart: View {
var body: some View {
Chart3D {
SurfacePlot(x: "Speed", y: "Distance", z: "Time") { speed, time in
speed * time
}
.foregroundStyle(.heightBased)
// or
// .foregroundStyle(.normalBased)
}
.frame(width: 500, height: 400)
}
}

Or go full rainbow:
.foregroundStyle(
EllipticalGradient(colors: [.red, .orange, .yellow, .green, .blue])
)
Gradient based styles make data trends easier to interpret visually.
When Should You Use 3D Charts?
Use when:
- You need to show relationships between 3+ variables
- Spatial layout matters (e.g. body movement, physical sensors)
- Interaction adds value (rotating to find patterns)
Avoid if:
- Your audience needs to read exact values precisely
- You can solve the same problem with a cleaner 2D chart
SwiftUI’s new Chart3D
and SurfacePlot
APIs are incredibly powerful tools for exploring multi-dimensional data in a way that feels visual, natural, and intuitive. If you want to dig deeper here is the are some resources: