Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
  • 多轴图表(双 Y 轴、混合图表)

多轴图表(双 Y 轴、混合图表)

概述

多轴图表是数据可视化中的高级技术,允许在同一图表中展示多个数据维度或不同量纲的数据。通过双 Y 轴或混合图表类型(如折线图+柱状图组合),可以更高效地呈现复杂数据关系。


双 Y 轴实现

核心概念

  1. 双 Y 轴适用场景

    • 比较不同量纲的数据(如温度℃ vs. 降水量mm)
    • 显示同一时间范围内两种不同尺度的趋势
  2. SwiftUI Charts 实现方案

    Chart {
        // 主 Y 轴数据(左侧)
        BarMark(
            x: .value("Date", data.date),
            y: .value("Sales", data.sales)
        )
        
        // 次 Y 轴数据(右侧)
        LineMark(
            x: .value("Date", data.date),
            y: .value("Profit Rate", data.profitRate)
        )
        .foregroundStyle(.red)
        .yAxis(.secondary) // 关键配置
    }
    .chartYAxis {
        AxisMarks(position: .leading) // 左侧主Y轴
        AxisMarks(position: .trailing) // 右侧次Y轴
    }
    

样式控制

  • 轴标签格式化
    .chartYAxis {
        AxisMarks(position: .trailing, values: .automatic) { value in
            AxisGridLine()
            AxisTick()
            AxisValueLabel {
                Text("\(value.as(Int.self)!)%") 
                    .foregroundStyle(.red)
            }
        }
    }
    

混合图表类型

常见组合模式

组合类型适用场景示例
柱状图+折线图数值对比+趋势展示销售额(柱状)vs. 增长率(线)
面积图+散点图分布展示+突出关键点温度分布(面积)vs. 极端值(点)

实现示例

Chart {
    // 柱状图部分
    BarMark(
        x: .value("Month", data.month),
        y: .value("Revenue", data.revenue)
    )
    .foregroundStyle(.blue)
    
    // 折线图部分
    LineMark(
        x: .value("Month", data.month),
        y: .value("Users", data.users)
    )
    .foregroundStyle(.orange)
    .symbol(.circle)
}
.chartYAxis {
    AxisMarks(position: .leading) // 共用Y轴
}

高级技巧

1. 轴对齐策略

// 强制双Y轴零基线对齐
.chartYScale(domain: [0, maxPrimaryValue])
.chartYScale(domainSecondary: [0, maxSecondaryValue])

2. 图例(legend)优化

.chartLegend(position: .top) {
    HStack {
        Circle().fill(.blue).frame(width: 10)
        Text("Revenue")
        Circle().fill(.orange).frame(width: 10)
        Text("User Growth")
    }
}

3. 交互增强

// 同步高亮两个数据系列
.chartOverlay { proxy in
    Color.clear
        .onTapGesture { location in
            if let date = proxy.value(atX: location.x) as String? {
                highlightDate = date
            }
        }
}

案例:加密货币行情图表

功能需求

  • 主Y轴(左):显示价格(USD)
  • 次Y轴(右):显示交易量(BTC)
  • 组合类型:蜡烛图(价格) + 柱状图(交易量)

关键代码

Chart(cryptoData) { item in
    // 蜡烛图
    BarMark(
        x: .value("Day", item.date),
        yStart: .value("Low", item.lowPrice),
        yEnd: .value("High", item.highPrice),
        width: .fixed(8)
    )
    .foregroundStyle(
        item.openPrice > item.closePrice ? .red : .green
    )
    
    // 交易量柱状图
    BarMark(
        x: .value("Day", item.date),
        y: .value("Volume", item.volume)
    )
    .yAxis(.secondary)
    .foregroundStyle(.gray.opacity(0.3))
}

常见问题解决

Q1: 轴刻度不对齐怎么办?

  • 方案:手动设置chartYScale的domain和domainSecondary

Q2: 如何避免视觉混淆?

  • 最佳实践:
    • 使用对比色但保持低饱和度
    • 为次要数据系列添加透明度
    • 添加清晰的图例说明

Q3: 性能优化建议

  • 大数据集时:
    • 对次要系列启用interpolationMethod(.monotone)
    • 使用Canvas替代标准Mark绘制

延伸阅读

  • Apple Developer: Composing Custom Charts
  • Visualizing Mixed Chart Types in SwiftUI
Last Updated:: 5/18/25, 10:44 AM