| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- //
- // 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()
- }
- }
|