SwiftUI 3D Charts: Add a Whole New Dimension to Your Data

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)
Swift
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:

Swift
.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:

Swift
.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.

Swift
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:

Swift
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:

Swift
.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:


Posted

in

Tags: