charts-3d

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

3D Charts with Swift Charts

基于Swift Charts的3D图表

Create 3D data visualizations using
Chart3D
and
SurfacePlot
. Covers math-driven surfaces, data-driven surfaces, interactive camera pose control, surface styling, and camera projection modes.
使用
Chart3D
SurfacePlot
创建3D数据可视化。涵盖数学驱动曲面、数据驱动曲面、交互式相机姿态控制、曲面样式设置以及相机投影模式。

When This Skill Activates

技能适用场景

Use this skill when the user:
  • Wants to create a 3D chart or 3D data visualization
  • Asks about
    Chart3D
    ,
    SurfacePlot
    , or 3D surface plots
  • Needs to visualize a mathematical function as a 3D surface
  • Wants interactive drag-to-rotate on a 3D chart
  • Asks about 3D chart camera angles, pose, or projection
  • Needs to style 3D surfaces with gradients or height-based coloring
  • Wants to render multiple surfaces in a single 3D chart
  • Asks about data-driven 3D plots from an array of points
当用户有以下需求时,可使用本技能:
  • 想要创建3D图表或3D数据可视化
  • 询问
    Chart3D
    SurfacePlot
    或3D曲面图相关内容
  • 需要将数学函数可视化为3D曲面
  • 希望3D图表支持拖拽旋转交互
  • 询问3D图表的相机角度、姿态或投影方式
  • 需要通过渐变或基于高度的着色来设置3D曲面样式
  • 想要在单个3D图表中渲染多个曲面
  • 询问如何通过点数组创建数据驱动的3D图

Decision Tree

决策树

What 3D chart feature do you need?
|
+-- Visualize a math function f(x, y) -> z
|   +-- Use SurfacePlot(x:y:z:function:)
|
+-- Visualize data points as a surface
|   +-- Use Chart3D(data) { point in SurfacePlot(...) }
|
+-- Interactive drag-to-rotate
|   +-- Bind pose: .chart3DPose($pose) with @State var pose: Chart3DPose
|
+-- Fixed viewing angle (no interaction)
|   +-- Read-only pose: .chart3DPose(Chart3DPose.front) or custom
|
+-- Style the surface color
|   +-- Solid color -> .foregroundStyle(Color.blue)
|   +-- Gradient -> .foregroundStyle(LinearGradient(...))
|   +-- Height-based -> .foregroundStyle(.heightBased(gradient, yRange:))
|   +-- Normal-based -> .foregroundStyle(.normalBased)
|
+-- Camera projection
|   +-- Perspective (depth) -> .chart3DCameraProjection(.perspective)
|   +-- Orthographic (flat) -> .chart3DCameraProjection(.orthographic)
|   +-- System default -> .chart3DCameraProjection(.automatic)
|
+-- Multiple surfaces in one chart
    +-- Place multiple SurfacePlot calls inside a single Chart3D { }
你需要3D图表的哪些功能?
|
+-- 可视化数学函数f(x, y) -> z
|   +-- 使用SurfacePlot(x:y:z:function:)
|
+-- 将数据点可视化为曲面
|   +-- 使用Chart3D(data) { point in SurfacePlot(...) }
|
+-- 支持拖拽旋转交互
|   +-- 通过@State var pose: Chart3DPose绑定pose: .chart3DPose($pose)
|
+-- 固定视角(无交互)
|   +-- 使用只读姿态:.chart3DPose(Chart3DPose.front)或自定义姿态
|
+-- 设置曲面颜色
|   +-- 纯色 -> .foregroundStyle(Color.blue)
|   +-- 渐变 -> .foregroundStyle(LinearGradient(...))
|   +-- 基于高度 -> .foregroundStyle(.heightBased(gradient, yRange:))
|   +-- 基于法线 -> .foregroundStyle(.normalBased)
|
+-- 相机投影
|   +-- 透视(带深度) -> .chart3DCameraProjection(.perspective)
|   +-- 正交(平面) -> .chart3DCameraProjection(.orthographic)
|   +-- 系统默认 -> .chart3DCameraProjection(.automatic)
|
+-- 单图表多曲面
    +-- 在单个Chart3D { }中放置多个SurfacePlot调用

API Availability

API兼容性

APIMinimum VersionImportNotes
Chart3D
iOS 26 / macOS 26
Charts
Main 3D chart container
SurfacePlot
iOS 26 / macOS 26
Charts
3D surface mark
Chart3DPose
iOS 26 / macOS 26
Charts
Viewing angle control
Chart3DCameraProjection
iOS 26 / macOS 26
Charts
.automatic
,
.perspective
,
.orthographic
Chart3DSurfaceStyle
iOS 26 / macOS 26
Charts
.heightBased
,
.normalBased
API最低版本要求导入包说明
Chart3D
iOS 26 / macOS 26
Charts
3D图表主容器
SurfacePlot
iOS 26 / macOS 26
Charts
3D曲面标记
Chart3DPose
iOS 26 / macOS 26
Charts
视角控制
Chart3DCameraProjection
iOS 26 / macOS 26
Charts
包含
.automatic
.perspective
.orthographic
选项
Chart3DSurfaceStyle
iOS 26 / macOS 26
Charts
包含
.heightBased
.normalBased
选项

Quick Start

快速入门

Math-Driven Surface

数学驱动曲面

Render a surface from a function
f(x, y) -> z
:
swift
import SwiftUI
import Charts

struct WaveSurfaceView: View {
    var body: some View {
        Chart3D {
            SurfacePlot(
                x: "X",
                y: "Height",
                z: "Z",
                function: { x, z in
                    sin(x) * cos(z)
                }
            )
            .foregroundStyle(.blue)
        }
    }
}
通过函数
f(x, y) -> z
渲染曲面:
swift
import SwiftUI
import Charts

struct WaveSurfaceView: View {
    var body: some View {
        Chart3D {
            SurfacePlot(
                x: "X",
                y: "Height",
                z: "Z",
                function: { x, z in
                    sin(x) * cos(z)
                }
            )
            .foregroundStyle(.blue)
        }
    }
}

Data-Driven Surface

数据驱动曲面

Render a surface from an array of data points:
swift
import SwiftUI
import Charts

struct DataPoint: Identifiable {
    let id = UUID()
    let x: Double
    let y: Double
    let z: Double
}

struct DataSurfaceView: View {
    let points: [DataPoint]

    var body: some View {
        Chart3D(points) { point in
            SurfacePlot(
                x: .value("X", point.x),
                y: .value("Height", point.y),
                z: .value("Z", point.z)
            )
        }
    }
}
通过数据点数组渲染曲面:
swift
import SwiftUI
import Charts

struct DataPoint: Identifiable {
    let id = UUID()
    let x: Double
    let y: Double
    let z: Double
}

struct DataSurfaceView: View {
    let points: [DataPoint]

    var body: some View {
        Chart3D(points) { point in
            SurfacePlot(
                x: .value("X", point.x),
                y: .value("Height", point.y),
                z: .value("Z", point.z)
            )
        }
    }
}

Interactive Rotation

交互式旋转

Allow the user to drag to rotate the chart:
swift
import SwiftUI
import Charts

struct InteractiveChartView: View {
    @State private var pose = Chart3DPose.default

    var body: some View {
        Chart3D {
            SurfacePlot(
                x: "X",
                y: "Height",
                z: "Z",
                function: { x, z in
                    sin(x) * cos(z)
                }
            )
            .foregroundStyle(.blue)
        }
        .chart3DPose($pose)
    }
}
允许用户拖拽旋转图表:
swift
import SwiftUI
import Charts

struct InteractiveChartView: View {
    @State private var pose = Chart3DPose.default

    var body: some View {
        Chart3D {
            SurfacePlot(
                x: "X",
                y: "Height",
                z: "Z",
                function: { x, z in
                    sin(x) * cos(z)
                }
            )
            .foregroundStyle(.blue)
        }
        .chart3DPose($pose)
    }
}

Surface Styling Patterns

曲面样式设置方案

Solid Color

纯色

swift
SurfacePlot(x: "X", y: "Y", z: "Z", function: { x, z in x * z })
    .foregroundStyle(.blue)
swift
SurfacePlot(x: "X", y: "Y", z: "Z", function: { x, z in x * z })
    .foregroundStyle(.blue)

Linear Gradient

线性渐变

swift
SurfacePlot(x: "X", y: "Y", z: "Z", function: { x, z in x * z })
    .foregroundStyle(
        LinearGradient(
            colors: [.blue, .green, .yellow],
            startPoint: .bottom,
            endPoint: .top
        )
    )
swift
SurfacePlot(x: "X", y: "Y", z: "Z", function: { x, z in x * z })
    .foregroundStyle(
        LinearGradient(
            colors: [.blue, .green, .yellow],
            startPoint: .bottom,
            endPoint: .top
        )
    )

Height-Based Surface Style

基于高度的曲面样式

Color the surface based on height values, mapping a gradient across the y-axis range:
swift
SurfacePlot(x: "X", y: "Y", z: "Z", function: { x, z in sin(x) * cos(z) })
    .foregroundStyle(
        Chart3DSurfaceStyle.heightBased(
            Gradient(colors: [.blue, .cyan, .green, .yellow, .red]),
            yRange: -1...1
        )
    )
根据高度值为曲面着色,将渐变映射到y轴范围:
swift
SurfacePlot(x: "X", y: "Y", z: "Z", function: { x, z in sin(x) * cos(z) })
    .foregroundStyle(
        Chart3DSurfaceStyle.heightBased(
            Gradient(colors: [.blue, .cyan, .green, .yellow, .red]),
            yRange: -1...1
        )
    )

Normal-Based Surface Style

基于法线的曲面样式

Color based on surface normals, giving a lighting-aware appearance:
swift
SurfacePlot(x: "X", y: "Y", z: "Z", function: { x, z in sin(x) * cos(z) })
    .foregroundStyle(Chart3DSurfaceStyle.normalBased)
根据曲面法线着色,呈现光影感知效果:
swift
SurfacePlot(x: "X", y: "Y", z: "Z", function: { x, z in sin(x) * cos(z) })
    .foregroundStyle(Chart3DSurfaceStyle.normalBased)

Surface Roughness

曲面粗糙度

Control how shiny or matte the surface appears. A value of 0 is perfectly smooth (reflective), and 1 is fully rough (matte):
swift
SurfacePlot(x: "X", y: "Y", z: "Z", function: { x, z in sin(x) * cos(z) })
    .foregroundStyle(.blue)
    .roughness(0.3)
控制曲面的光泽度或哑光程度。值为0时完全光滑(反光),值为1时完全粗糙(哑光):
swift
SurfacePlot(x: "X", y: "Y", z: "Z", function: { x, z in sin(x) * cos(z) })
    .foregroundStyle(.blue)
    .roughness(0.3)

Interactive Pose Control

交互式姿态控制

Preset Poses

预设姿态

Chart3DPose
provides built-in presets for common viewing angles:
swift
.chart3DPose(.default)   // Standard 3/4 angle
.chart3DPose(.front)     // Viewing from front
.chart3DPose(.back)      // Viewing from back
.chart3DPose(.top)       // Top-down view
.chart3DPose(.bottom)    // Bottom-up view
.chart3DPose(.right)     // Right side view
.chart3DPose(.left)      // Left side view
Chart3DPose
提供了常见视角的内置预设:
swift
.chart3DPose(.default)   // 标准斜角视角
.chart3DPose(.front)     // 正面视角
.chart3DPose(.back)      // 背面视角
.chart3DPose(.top)       // 俯视视角
.chart3DPose(.bottom)    // 仰视视角
.chart3DPose(.right)     // 右侧视角
.chart3DPose(.left)      // 左侧视角

Custom Pose

自定义姿态

Specify exact azimuth (horizontal rotation) and inclination (vertical tilt):
swift
.chart3DPose(
    Chart3DPose(azimuth: .degrees(45), inclination: .degrees(30))
)
指定精确的方位角(水平旋转)和倾斜角(垂直倾斜):
swift
.chart3DPose(
    Chart3DPose(azimuth: .degrees(45), inclination: .degrees(30))
)

Read-Only vs Interactive

只读模式 vs 交互模式

swift
// ✅ Read-only — user cannot rotate the chart
.chart3DPose(Chart3DPose.front)

// ✅ Interactive — user can drag to rotate, pose updates automatically
@State private var pose = Chart3DPose.default
// ...
.chart3DPose($pose)
swift
// ✅ 只读模式 — 用户无法旋转图表
.chart3DPose(Chart3DPose.front)

// ✅ 交互模式 — 用户可拖拽旋转,姿态自动更新
@State private var pose = Chart3DPose.default
// ...
.chart3DPose($pose)

Anti-Patterns

反模式示例

swift
// ❌ Passing a literal where a binding is needed for interactivity
.chart3DPose(.default) // This is read-only; drag gestures will not work

// ✅ Use a @State binding for interactive rotation
@State private var pose = Chart3DPose.default
// ...
.chart3DPose($pose)
swift
// ❌ 传递字面量作为交互所需的绑定值
.chart3DPose(.default) // 此为只读模式,拖拽手势无效

// ✅ 使用@State绑定实现交互式旋转
@State private var pose = Chart3DPose.default
// ...
.chart3DPose($pose)

Camera Projection

相机投影

Control how 3D depth is rendered:
swift
Chart3D {
    SurfacePlot(x: "X", y: "Y", z: "Z", function: { x, z in sin(x) * cos(z) })
        .foregroundStyle(.blue)
}
.chart3DCameraProjection(.perspective)   // Objects farther away appear smaller
// .chart3DCameraProjection(.orthographic)  // No perspective distortion
// .chart3DCameraProjection(.automatic)     // System decides
  • Perspective: Gives natural depth perception. Objects farther from the camera appear smaller. Good for presentations and visual appeal.
  • Orthographic: No size distortion with distance. Good for precise data reading and scientific visualization.
  • Automatic: System selects based on context.
控制3D深度的渲染方式:
swift
Chart3D {
    SurfacePlot(x: "X", y: "Y", z: "Z", function: { x, z in sin(x) * cos(z) })
        .foregroundStyle(.blue)
}
.chart3DCameraProjection(.perspective)   // 远处物体看起来更小
// .chart3DCameraProjection(.orthographic)  // 无透视变形
// .chart3DCameraProjection(.automatic)     // 系统自动选择
  • 透视投影:呈现自然的深度感知,距离相机越远的物体看起来越小,适合演示和视觉展示。
  • 正交投影:物体大小不受距离影响,适合精确数据读取和科学可视化。
  • 自动模式:系统根据上下文选择投影方式。

Multiple Surfaces

多曲面渲染

Render multiple surfaces in a single chart for comparison:
swift
import SwiftUI
import Charts

struct ComparisonChartView: View {
    @State private var pose = Chart3DPose.default

    var body: some View {
        Chart3D {
            SurfacePlot(
                x: "X",
                y: "Wave A",
                z: "Z",
                function: { x, z in sin(x) * cos(z) }
            )
            .foregroundStyle(.blue.opacity(0.8))

            SurfacePlot(
                x: "X",
                y: "Wave B",
                z: "Z",
                function: { x, z in cos(x) * sin(z) }
            )
            .foregroundStyle(.red.opacity(0.8))
        }
        .chart3DPose($pose)
        .chart3DCameraProjection(.perspective)
    }
}
在单个图表中渲染多个曲面以便对比:
swift
import SwiftUI
import Charts

struct ComparisonChartView: View {
    @State private var pose = Chart3DPose.default

    var body: some View {
        Chart3D {
            SurfacePlot(
                x: "X",
                y: "Wave A",
                z: "Z",
                function: { x, z in sin(x) * cos(z) }
            )
            .foregroundStyle(.blue.opacity(0.8))

            SurfacePlot(
                x: "X",
                y: "Wave B",
                z: "Z",
                function: { x, z in cos(x) * sin(z) }
            )
            .foregroundStyle(.red.opacity(0.8))
        }
        .chart3DPose($pose)
        .chart3DCameraProjection(.perspective)
    }
}

Complete Example

完整示例

A full-featured 3D chart with height-based coloring, interactive rotation, and perspective projection:
swift
import SwiftUI
import Charts

struct TerrainView: View {
    @State private var pose = Chart3DPose(
        azimuth: .degrees(30),
        inclination: .degrees(25)
    )

    var body: some View {
        VStack {
            Text("Terrain Visualization")
                .font(.headline)

            Chart3D {
                SurfacePlot(
                    x: "Longitude",
                    y: "Elevation",
                    z: "Latitude",
                    function: { x, z in
                        let distance = sqrt(x * x + z * z)
                        return sin(distance) / max(distance, 0.1)
                    }
                )
                .foregroundStyle(
                    Chart3DSurfaceStyle.heightBased(
                        Gradient(colors: [
                            .blue, .cyan, .green, .yellow, .orange, .red
                        ]),
                        yRange: -0.5...1.0
                    )
                )
                .roughness(0.4)
            }
            .chart3DPose($pose)
            .chart3DCameraProjection(.perspective)
        }
        .padding()
    }
}
一个具备基于高度着色、交互式旋转和透视投影的全功能3D图表:
swift
import SwiftUI
import Charts

struct TerrainView: View {
    @State private var pose = Chart3DPose(
        azimuth: .degrees(30),
        inclination: .degrees(25)
    )

    var body: some View {
        VStack {
            Text("Terrain Visualization")
                .font(.headline)

            Chart3D {
                SurfacePlot(
                    x: "Longitude",
                    y: "Elevation",
                    z: "Latitude",
                    function: { x, z in
                        let distance = sqrt(x * x + z * z)
                        return sin(distance) / max(distance, 0.1)
                    }
                )
                .foregroundStyle(
                    Chart3DSurfaceStyle.heightBased(
                        Gradient(colors: [
                            .blue, .cyan, .green, .yellow, .orange, .red
                        ]),
                        yRange: -0.5...1.0
                    )
                )
                .roughness(0.4)
            }
            .chart3DPose($pose)
            .chart3DCameraProjection(.perspective)
        }
        .padding()
    }
}

Top Mistakes

常见错误

#MistakeFix
1Forgetting to
import Charts
Both
SwiftUI
and
Charts
imports are required
2Using
.chart3DPose(.default)
and expecting drag-to-rotate
Use a
@State
binding:
.chart3DPose($pose)
for interactive rotation
3Setting
yRange
that does not cover actual function output
Match the
yRange
in
.heightBased()
to the actual min/max of your function output
4Applying
.roughness()
without
.foregroundStyle()
Roughness modifies existing surface appearance; set a foreground style first
5Using orthographic projection for presentation/demo contextsPrefer
.perspective
for visual appeal; use
.orthographic
for precise data reading
序号错误内容修复方案
1忘记
import Charts
同时需要导入
SwiftUI
Charts
2使用
.chart3DPose(.default)
却期望支持拖拽旋转
使用
@State
绑定:
.chart3DPose($pose)
实现交互式旋转
3设置的
yRange
未覆盖函数实际输出范围
.heightBased()
中的
yRange
与函数实际输出的最小/最大值匹配
4未设置
.foregroundStyle()
就应用
.roughness()
粗糙度会修改现有曲面外观,需先设置前景样式
5在演示场景中使用正交投影优先选择
.perspective
提升视觉效果;精确数据读取时使用
.orthographic

Review Checklist

检查清单

Imports and Setup

导入与设置

  • Both
    import SwiftUI
    and
    import Charts
    are present
  • Deployment target is iOS 26 / macOS 26 or later
  • Chart3D
    wraps all
    SurfacePlot
    content
  • 已同时导入
    import SwiftUI
    import Charts
  • 部署目标为iOS 26 / macOS 26或更高版本
  • 所有
    SurfacePlot
    内容均被
    Chart3D
    包裹

Surface Configuration

曲面配置

  • Axis labels (
    x:
    ,
    y:
    ,
    z:
    ) are descriptive and meaningful
  • foregroundStyle
    applied to each
    SurfacePlot
    for clear visual distinction
  • yRange
    in
    .heightBased()
    matches the actual output range of the function
  • roughness
    value makes sense for the use case (0 = reflective, 1 = matte)
  • 轴标签(
    x:
    y:
    z:
    )描述清晰且有意义
  • 每个
    SurfacePlot
    都已应用
    foregroundStyle
    以明确区分
  • .heightBased()
    中的
    yRange
    与函数实际输出范围匹配
  • 粗糙度值符合使用场景(0=反光,1=哑光)

Interactivity

交互性

  • Pose is a
    @State
    binding if drag-to-rotate is intended
  • Pose is a constant (non-binding) if rotation should be locked
  • Initial pose angle provides a good default view of the data
  • 若需拖拽旋转,姿态为
    @State
    绑定类型
  • 若需锁定旋转,姿态为常量(非绑定)
  • 初始姿态角度能提供良好的数据默认视图

Camera

相机设置

  • Camera projection set appropriately (
    .perspective
    for visual,
    .orthographic
    for precision)
  • If using
    .automatic
    , verified the system choice looks acceptable
  • 相机投影设置合适(
    .perspective
    用于视觉展示,
    .orthographic
    用于精确场景)
  • 若使用
    .automatic
    ,已确认系统选择的效果符合预期

Multiple Surfaces

多曲面

  • Each surface has a distinct color or opacity to differentiate
  • Axis labels are unique per surface or shared where appropriate
  • 每个曲面有独特的颜色或透明度以区分
  • 轴标签根据情况设置为每个曲面独有或共享

References

参考资料