iCharts
Telegram“3月编码大赛”的解决方案。完全使用Core Animation和自动布局(NSLayoutAnchor)实现。
您可以通过TestFlight参加beta测试。
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
是一个静态库,包含一些有用的结构和类型别名,如Result
、Variable
等。
架构
TL;DR
- 完全实现于
CALayer
上 - 优先使用组合而非继承
- 完全数据驱动的 UI
- 仅渲染图表的可见部分
详情
iCharts
框架的实现高度激励于 Core Animation
的 CALayer
功能和类的组合,而不是继承,以便具有以 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
是一个核心视图,负责渲染所有图表层:[](https://i.ibb.co/SwVLZvF/Simulator-Screen-Shot-i-Phone-X-2019-03-25-at-13-02-41.png) [](https://i.ibb.co/2MkdS2q/2019-03-25-12-56-28.jpg)GridLayer
渲染网格的水平线。LineChartLayer
包含LineLayer
和VerticalLineLayer
。LineLayer
基于点向量CGPoint
(如果有出现VerticalLineLayer
,它还会渲染圆圈以显示高亮点)绘制线。VerticalLineLayer
绘制通过高亮点的垂直线。
YLabelsLayer
绘制在GridLayer
的水平线之上(每条线的y
值)的标签。XLabelsLayer
绘制在LinearChartLayer
或x
轴上方(日期格式为 "MMM dd")的标签。
PannableChartView
是UIControl
的子类,实现了类似于UIPanGestureRecognizer
的行为。它告诉ChartView
显示高亮点,并在图表上方显示包含点详细信息的ChartInfoView
。[](https://i.ibb.co/Y7XLk5k/Simulator-Screen-Shot-i-Phone-X-2019-03-25-at-13-18-09.png)ChartScrollView
包含了PannableChartView
和ExpandableSliderView
的实例,允许用户选择图表的可视部分和其比例。DetailedChartView
包含ChartScrollView
和UITableView
的实例,具有线条名称和颜色的显示/隐藏功能。
规范化器
Normalizer
是一个协议,它定义了基于图层目标矩形大小进行线条归一化的方法。SizeNormalizer
是一个类,它基于- [minY, maxY] 区段进行归一化,该区段的
verticalInses
(依赖于isInFullSize
和verticalInset
属性) - [0, maxY] 区段(全尺寸)
- [minY, maxY] 区段进行归一化,该区段的
关于 minY, maxY 的说明
- 正式情况: minY, maxY 属于集合 {y | y ∈ Y1 ∪ Y2 ∪ ... ∪ Yn},其中 ∪ 表示并集(集合运算),Yi 是第 i 条线的 y 值集合
- 非正式情况: minY, maxY 中选择图表中每条线的每个 y 值
许可
iCharts 可在 MIT 许可下使用。有关更多信息,请参阅 LICENSE 文件。