热力图和树形图
热力图(Heatmap)
基本概念
热力图通过颜色梯度表示矩阵数据的密度或强度值,常用于:
- 时间序列数据(如日历热力图)
- 地理空间数据(如人口密度图)
- 相关性矩阵(如基因表达数据)
SwiftUI 实现方案
- 基础实现:
struct HeatmapView: View {
let data: [[Double]]
let colors: [Color]
var body: some View {
Grid(horizontalSpacing: 2, verticalSpacing: 2) {
ForEach(0..<data.count, id: \.self) { row in
GridRow {
ForEach(0..<data[row].count, id: \.self) { col in
Rectangle()
.fill(colorForValue(data[row][col]))
.aspectRatio(1, contentMode: .fit)
}
}
}
}
}
private func colorForValue(_ value: Double) -> Color {
// 实现颜色插值逻辑
}
}
- 高级特性:
- 使用
LinearGradient实现平滑色阶 - 添加轴标签和数值标注
- 集成手势交互(点击查看具体数值)
案例:日历热力图
struct CalendarHeatmap: View {
@State private var selectedDay: Date?
var body: some View {
// 实现类似 GitHub 贡献日历的热力图
}
}
树形图(Treemap)
基本概念
树形图通过嵌套矩形展示层次结构数据:
- 矩形面积表示数值大小
- 颜色可表示额外维度(如增长率)
- 典型应用:磁盘空间分析、组织结构可视化
SwiftUI 实现方案
- 递归布局算法:
struct TreemapView: View {
let nodes: [TreeNode]
let size: CGSize
var body: some View {
ZStack {
ForEach(nodes) { node in
TreemapNodeView(node: node,
rect: calculateRect(for: node))
}
}
.frame(width: size.width, height: size.height)
}
private func calculateRect(for node: TreeNode) -> CGRect {
// 实现 squarified 或 slice-and-dice 布局算法
}
}
- 交互设计:
- 点击展开/折叠子节点
- 悬停显示 Tooltip
- 平滑的过渡动画
案例:文件系统分析工具
struct FileSystemTreemap: View {
@ObservedObject var fileAnalyzer: FileAnalyzer
var body: some View {
TreemapView(nodes: fileAnalyzer.rootNodes,
size: CGSize(width: 300, height: 200))
.onTapGesture { /* 处理节点选择 */ }
}
}
性能优化技巧
- 热力图优化:
- 对大数据集使用
LazyVGrid和LazyHGrid - 预计算颜色映射表
- 考虑使用
Canvas进行底层绘制
- 树形图优化:
- 实现虚拟滚动(仅渲染可见区域)
- 缓存布局计算结果
- 对静态数据使用
EquatableView
完整示例项目
建议实现一个结合两种图表的 App Store 下载分析工具:
- 热力图展示每日下载趋势
- 树形图展示地区/设备分布
- 使用
Charts框架的RectangleMark作为基础
struct AppAnalyticsDashboard: View {
var body: some View {
TabView {
DownloadHeatmap()
.tabItem { Label("时间趋势", systemImage: "calendar") }
RegionTreemap()
.tabItem { Label("地区分布", systemImage: "map") }
}
}
}
延伸阅读
- D3.js 的热力图实现原理
- 树形图的 squarified 布局算法论文
- SwiftUI 的
Layout协议高级用法
