Files
ChartView/Sources/SwiftUICharts/Charts/LineChart/Line.swift
Andras Samu ac7680320f feat(core): refactoring chart dispalying
now it is possible to add background lines precisely as charts are displayed at correct size
also rewrote basics to conform with Shapes and Animatable protocol
2021-04-04 15:54:15 +02:00

101 lines
4.0 KiB
Swift

import SwiftUI
/// A single line of data, a view in a `LineChart`
public struct Line: View {
@EnvironmentObject var chartValue: ChartValue
@ObservedObject var chartData: ChartData
var style: ChartStyle
@State private var showIndicator: Bool = false
@State private var touchLocation: CGPoint = .zero
@State private var showBackground: Bool = true
@State private var didCellAppear: Bool = false
var curvedLines: Bool = true
/// The content and behavior of the `Line`.
/// Draw the background if showing the full line (?) and the `showBackground` option is set. Above that draw the line, and then the data indicator if the graph is currently being touched.
/// On appear, set the frame so that the data graph metrics can be calculated. On a drag (touch) gesture, highlight the closest touched data point.
/// TODO: explain rotation
public var body: some View {
GeometryReader { geometry in
ZStack {
if self.didCellAppear && self.showBackground {
LineBackgroundShapeView(chartData: chartData,
geometry: geometry,
style: style)
}
LineShapeView(chartData: chartData,
geometry: geometry,
style: style,
trimTo: didCellAppear ? 1.0 : 0.0)
.animation(.easeIn)
// if self.showIndicator {
// IndicatorPoint()
// .position(self.getClosestPointOnPath(touchLocation: self.touchLocation))
// .rotationEffect(.degrees(180), anchor: .center)
// .rotation3DEffect(.degrees(180), axis: (x: 0, y: 1, z: 0))
// }
}
.onAppear {
didCellAppear = true
}
.onDisappear() {
didCellAppear = false
}
.gesture(DragGesture()
.onChanged({ value in
self.touchLocation = value.location
self.showIndicator = true
// self.getClosestDataPoint(point: self.getClosestPointOnPath(touchLocation: value.location))
self.chartValue.interactionInProgress = true
})
.onEnded({ value in
self.touchLocation = .zero
self.showIndicator = false
self.chartValue.interactionInProgress = false
})
)
}
}
}
// MARK: - Private functions
//extension Line {
// /// Calculate point closest to where the user touched
// /// - Parameter touchLocation: location in view where touched
// /// - Returns: `CGPoint` of data point on chart
// private func getClosestPointOnPath(touchLocation: CGPoint) -> CGPoint {
// let closest = self.path.point(to: touchLocation.x)
// return closest
// }
//
// /// Figure out where closest touch point was
// /// - Parameter point: location of data point on graph, near touch location
// private func getClosestDataPoint(point: CGPoint) {
// let index = Int(round((point.x)/step.x))
// if (index >= 0 && index < self.chartData.data.count){
// self.chartValue.currentValue = self.chartData.points[index]
// }
// }
//}
struct Line_Previews: PreviewProvider {
/// Predefined style, black over white, for preview
static let blackLineStyle = ChartStyle(backgroundColor: ColorGradient(.white), foregroundColor: ColorGradient(.black))
/// Predefined style red over white, for preview
static let redLineStyle = ChartStyle(backgroundColor: .whiteBlack, foregroundColor: ColorGradient(.red))
static var previews: some View {
Group {
Line(chartData: ChartData([8, 23, 32, 7, 23, -4]), style: blackLineStyle)
Line(chartData: ChartData([8, 23, 32, 7, 23, 43]), style: redLineStyle)
}
}
}