iCharts 1.0.0

iCharts 1.0.0

Volodymyr Hryhoriev维护。



iCharts 1.0.0

iCharts

Swift version Cocoapods License

Telegram“3月编码大赛”的解决方案。完全使用Core Animation和自动布局(NSLayoutAnchor)实现。

您可以通过TestFlight参加beta测试。

Demo Gif

Telegram“3月编码大赛”任务

  • 使用来自chart_data.json的日期作为您的图表的输入
  • 在一个屏幕上显示所有5个图表
  • 实现白天/夜晚模式
  • 在图表上添加平移手势,以便在高亮显示的点x上观看详细信息
  • x轴下方显示日期标签
  • y轴上方显示标签
  • 创建可扩展滑块控件以选择图表的可视部分及其缩放。
  • 在[最小Y,最大Y]区间内,在顶部和底部具有垂直嵌入式[最小X,最大X]的可视部分标签,其中最小Y = {y | y <= f(x), x in [最小X,最大X]},最大Y = {y | y >= f(x), x in [最小X,最大X]}
  • 动画化标签的变化
  • 动画化日期标签的变化
  • 动画化图表上线的出现和消失

使用方法

以下是一个简单示例。您只需创建具有Line数组的道具,并将其传递到render(props:=)方法中。

let chartView = DetailedChartView() // ChartScrollView, PannableChartView, ChartView

// Frame based layout or Auto Layout

let props = ChartView.Props(lines: [
              Line(title: "#1", xs: [1, 2, 3], ys: [3, 4, 5], color: .red),
              Line(title: "#2", xs: [1, 2, 3], ys: [5, 4, 3], color: .green)
            ])

chartView.render(props: props)

为了更改主题,只需更改Colors属性。

chartView.colors = makeColors() // you should write `makeColors` method, it is just example

ChartView.Props 属性

  • lines - 一系列 Line 结构体数组
  • lineWidth - 定义图表上线条宽度的正实数值
  • highlithedX - 用户在 PannableChartView 上高亮的 x 坐标
  • estimatedGridSpace - 估计的水平网格线条之间的空间
  • estimatedXLabelWidth - 估计的 x 轴下方标签的宽度
  • inset - 用户将图表渲染为全尺寸时的垂直缩进
  • isInFullSize - 确定是否应渲染图表为全尺寸
  • range - 图表可见部分的范围,以百分比或点为单位
  • didHighlightX - 当用户在 PannableChartView 上高亮点时触发的闭包

颜色

无需列出每个组件 Colors 结构体的所有属性。您只需知道,您可以更改图表任何部分的颜色。

有关更多信息,请参阅 DetailedChartView 中的 Colors 结构体。

安装

待定

工作空间结构

  • iChartsDemo 是一个演示 iCharts 框架用法的 iOS 单视图应用程序项目
  • iCharts 是一个包含 ChartView 源代码的框架
  • Utils 是一个静态库,包含一些有用的结构和类型别名,如 ResultVariable 等。

架构

TL;DR

  • 完全实现于 CALayer
  • 优先使用组合而非继承
  • 完全数据驱动的 UI
  • 仅渲染图表的可见部分

详情

iCharts 框架的实现高度激励于 Core AnimationCALayer 功能和类的组合,而不是继承,以便具有以 SRP 原则为核心的可灵活扩展、易于维护的代码库。

注意:当然,在有时间限制的竞争环境中,很难在速度和质量之间找到折衷方案,这就是为什么有时会违反 SOLID 的某些原则。

还应指出,UI 的所有部分都是数据驱动的。Props 被用作 UI 状态在每个时间点的哑表现。这种方法使实施未来的 时间旅行调试 功能成为可能。

ChartView.Props 示例

extension ChartView {

  public struct Props {
    public var lines: [Line]
    public var lineWidth: CGFloat
    public var highlithedX: CGFloat?
    public var estimatedGridSpace: Int?
    public var estimatedXLabelWidth: Int?
    public var inset: CGFloat?
    public var isInFullSize: Bool
    public var range: Range?
    public var didHighlightX: ClosureWith<Output>?

    // Init
  }
}

为了出色地实现主题,每个组件上也都使用了 Colors 结构。

ChartView.Colors 示例

extension ChartView {

  public struct Colors {
    public let labels: UIColor
    public let horizontalLines: UIColor
    public let lineChart: LineChartLayer.Colors
    
    // Init
    
    public static let initial = Colors(
            labels: .gray,
            horizontalLines: .gray,
            lineChart: .initial)
  }
}

图表的每一行都由 Line 结构表示,其中 Points[CGPoint] 的别名。

public struct Line {
  public let title: String
  public var points: Points
  public var highlightedPoint: CGPoint?
  public let color: UIColor
  public var isHidden: Bool

  // Init
}

视图 & 层

  • ChartView 是一个核心视图,负责渲染所有图表层:[![ChartView](https://camo.githubusercontent.com/9d7ad945196184a21bbcf71503309529b4674ef1/68747470733a2f2f692e6962622e636f2f5377564c5a76462f53696d756c61746f722d53637265656e2d53686f742d692d50686f6e652d582d323031392d30332d32352d61742d31332d30322d34312e706e67)](https://i.ibb.co/SwVLZvF/Simulator-Screen-Shot-i-Phone-X-2019-03-25-at-13-02-41.png) [![ChartView 层级结构](https://camo.githubusercontent.com/8e6ce91766cb2b74b668f4fbf76177916693bbb6/68747470733a2f2f692e6962622e636f2f324d6b645332712f323031392d30332d32352d31322d35362d32382e6a7067)](https://i.ibb.co/2MkdS2q/2019-03-25-12-56-28.jpg)
    • GridLayer 渲染网格的水平线。
    • LineChartLayer 包含 LineLayerVerticalLineLayer
      • LineLayer 基于点向量 CGPoint(如果有出现 VerticalLineLayer,它还会渲染圆圈以显示高亮点)绘制线。
      • VerticalLineLayer 绘制通过高亮点的垂直线。
    • YLabelsLayer 绘制在 GridLayer 的水平线之上(每条线的 y 值)的标签。
    • XLabelsLayer 绘制在 LinearChartLayerx 轴上方(日期格式为 "MMM dd")的标签。
  • PannableChartViewUIControl 的子类,实现了类似于 UIPanGestureRecognizer 的行为。它告诉 ChartView 显示高亮点,并在图表上方显示包含点详细信息的 ChartInfoView。[![PannableChartView](https://camo.githubusercontent.com/b4505859a9475fcfafc09103e4f9ca519ed67b1b/68747470733a2f2f692e6962622e636f2f5937584c6b356b2f53696d756c61746f722d53637265656e2d53686f742d692d50686f6e652d582d323031392d30332d32352d61742d31332d31382d30392e706e67)](https://i.ibb.co/Y7XLk5k/Simulator-Screen-Shot-i-Phone-X-2019-03-25-at-13-18-09.png)
  • ChartScrollView 包含了 PannableChartViewExpandableSliderView 的实例,允许用户选择图表的可视部分和其比例。ChartScrollView
  • DetailedChartView 包含 ChartScrollViewUITableView 的实例,具有线条名称和颜色的显示/隐藏功能。DetailedChartView

规范化器

  • Normalizer 是一个协议,它定义了基于图层目标矩形大小进行线条归一化的方法。
  • SizeNormalizer 是一个类,它基于
    • [minY, maxY] 区段进行归一化,该区段的 verticalInses(依赖于 isInFullSizeverticalInset 属性)
    • [0, maxY] 区段(全尺寸)

关于 minY, maxY 的说明

  • 正式情况: minY, maxY 属于集合 {y | y ∈ Y1 ∪ Y2 ∪ ... ∪ Yn},其中 ∪ 表示并集(集合运算),Yi 是第 i 条线的 y 值集合
  • 非正式情况: minY, maxY 中选择图表中每条线的每个 y 值

许可

iCharts 可在 MIT 许可下使用。有关更多信息,请参阅 LICENSE 文件。