练习:构建简单的静态图表框架
目标
通过本练习,您将运用前几节学到的 SwiftUI 视图组合和布局知识,创建一个可展示基础数据结构的静态图表框架。最终成果将包含坐标轴、数据标记和基本样式。
步骤说明
1. 创建基础视图结构
import SwiftUI
struct StaticChartView: View {
// 示例数据(硬编码)
let dataPoints: [Double] = [20, 45, 28, 80, 50]
var body: some View {
VStack(alignment: .leading) {
Text("月度销售额")
.font(.headline)
// 图表主体容器
ChartContainer(dataPoints: dataPoints)
.frame(height: 200)
}
.padding()
}
}
2. 实现图表容器
struct ChartContainer: View {
let dataPoints: [Double]
private let axisWidth: CGFloat = 30
var body: some View {
HStack(alignment: .bottom, spacing: 0) {
// Y轴标签
YAxisView(maxValue: dataPoints.max() ?? 100)
.frame(width: axisWidth)
// 主图表区域
ZStack(alignment: .bottom) {
// 背景网格线
ChartGridLines()
// 数据可视化部分
HStack(spacing: 12) {
ForEach(Array(dataPoints.enumerated()), id: \.offset) { index, value in
BarColumn(value: value, maxValue: dataPoints.max() ?? 100)
}
}
.padding(.leading, 8)
}
}
}
}
3. 构建核心组件
柱状图元素
struct BarColumn: View {
let value: Double
let maxValue: Double
var body: some View {
VStack(spacing: 4) {
// 柱状主体
Rectangle()
.fill(Color.blue.gradient)
.frame(height: CGFloat(value / maxValue) * 150)
// X轴标签
Text("\(Int(value))")
.font(.caption2)
}
}
}
坐标轴组件
struct YAxisView: View {
let maxValue: Double
let steps = 5
var body: some View {
VStack {
ForEach(0..<steps, id: \.self) { step in
let value = Int(maxValue) - (Int(maxValue) / steps * step)
Text("\(value)")
.font(.system(size: 10))
.frame(height: 30)
Spacer()
}
}
}
}
struct ChartGridLines: View {
var body: some View {
GeometryReader { geometry in
Path { path in
let step = geometry.size.height / 5
for i in 0...5 {
let y = step * CGFloat(i)
path.move(to: CGPoint(x: 0, y: y))
path.addLine(to: CGPoint(x: geometry.size.width, y: y))
}
}
.stroke(Color.gray.opacity(0.2), style: StrokeStyle(lineWidth: 1, dash: [2]))
}
}
}
进阶挑战
- 添加动态颜色支持:根据数值大小显示不同渐变色
- 实现横向柱状图版本
- 添加点击交互高亮效果(使用
.onTapGesture)
最终效果预览
包含坐标轴、网格线和5个数据柱的基础图表
关键知识点回顾
- 使用
VStack/HStack构建复合布局 - 通过
GeometryReader实现相对尺寸计算 - 用
Path绘制自定义形状 - 数据到视图的映射模式(
ForEach遍历)
> 提示:此框架已预留扩展接口,后续学习动态数据绑定时可直接复用容器结构