forked from LoopKit/LoopKit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathChartPointsContextFillLayer.swift
More file actions
122 lines (91 loc) · 3.13 KB
/
ChartPointsContextFillLayer.swift
File metadata and controls
122 lines (91 loc) · 3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
//
// ChartPointsContextFillLayer.swift
// Loop
//
// Copyright © 2017 LoopKit Authors. All rights reserved.
//
import SwiftCharts
import CoreGraphics
import UIKit
struct ChartPointsFill {
let chartPoints: [ChartPoint]
let fillColor: UIColor
let createContainerPoints: Bool
let blendMode: CGBlendMode
fileprivate var screenPoints: [CGPoint] = []
init?(chartPoints: [ChartPoint], fillColor: UIColor, createContainerPoints: Bool = true, blendMode: CGBlendMode = .normal) {
guard chartPoints.count > 1 else {
return nil;
}
var chartPoints = chartPoints
if createContainerPoints {
// Create a container line at value position 0
if let first = chartPoints.first {
chartPoints.insert(ChartPoint(x: first.x, y: ChartAxisValueInt(0)), at: 0)
}
if let last = chartPoints.last {
chartPoints.append(ChartPoint(x: last.x, y: ChartAxisValueInt(0)))
}
}
self.chartPoints = chartPoints
self.fillColor = fillColor
self.createContainerPoints = createContainerPoints
self.blendMode = blendMode
}
var areaPath: UIBezierPath {
let path = UIBezierPath()
if let point = screenPoints.first {
path.move(to: point)
}
for point in screenPoints.dropFirst() {
path.addLine(to: point)
}
return path
}
}
final class ChartPointsFillsLayer: ChartCoordsSpaceLayer {
let fills: [ChartPointsFill]
init?(xAxis: ChartAxis, yAxis: ChartAxis, fills: [ChartPointsFill?]) {
self.fills = fills.compactMap({ $0 })
guard fills.count > 0 else {
return nil
}
super.init(xAxis: xAxis, yAxis: yAxis)
}
override func chartInitialized(chart: Chart) {
super.chartInitialized(chart: chart)
let view = ChartPointsFillsView(
frame: chart.bounds,
chartPointsFills: fills.map { (fill) -> ChartPointsFill in
var fill = fill
fill.screenPoints = fill.chartPoints.map { (point) -> CGPoint in
return modelLocToScreenLoc(x: point.x.scalar, y: point.y.scalar)
}
return fill
}
)
chart.addSubview(view)
}
}
class ChartPointsFillsView: UIView {
let chartPointsFills: [ChartPointsFill]
var allowsAntialiasing = false
init(frame: CGRect, chartPointsFills: [ChartPointsFill]) {
self.chartPointsFills = chartPointsFills
super.init(frame: frame)
backgroundColor = .clear
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
context.saveGState()
context.setAllowsAntialiasing(allowsAntialiasing)
for fill in chartPointsFills {
context.setFillColor(fill.fillColor.cgColor)
fill.areaPath.fill(with: fill.blendMode, alpha: 1)
}
context.restoreGState()
}
}