diff --git a/Sources/SwiftUICharts/BarChart/Models/ChartData/BarChartData.swift b/Sources/SwiftUICharts/BarChart/Models/ChartData/BarChartData.swift index 032d6a31..e41f4f8b 100644 --- a/Sources/SwiftUICharts/BarChart/Models/ChartData/BarChartData.swift +++ b/Sources/SwiftUICharts/BarChart/Models/ChartData/BarChartData.swift @@ -25,7 +25,7 @@ public final class BarChartData: CTBarChartDataProtocol, GetDataProtocol, Publis @Published public final var viewData: ChartViewData @Published public final var infoView: InfoViewData = InfoViewData() - @Published public final var extraLineData: ExtraLineData! + @Published public final var extraLineData: ExtraLineData? // Publishable public var subscription = SubscriptionSet().subscription diff --git a/Sources/SwiftUICharts/BarChart/Models/ChartData/GroupedBarChartData.swift b/Sources/SwiftUICharts/BarChart/Models/ChartData/GroupedBarChartData.swift index f00b4b00..84c9a24e 100644 --- a/Sources/SwiftUICharts/BarChart/Models/ChartData/GroupedBarChartData.swift +++ b/Sources/SwiftUICharts/BarChart/Models/ChartData/GroupedBarChartData.swift @@ -30,7 +30,7 @@ public final class GroupedBarChartData: CTMultiBarChartDataProtocol, GetDataProt @Published public final var infoView: InfoViewData = InfoViewData() @Published public final var groups: [GroupingData] - @Published public final var extraLineData: ExtraLineData! + @Published public final var extraLineData: ExtraLineData? // Publishable public var subscription = SubscriptionSet().subscription diff --git a/Sources/SwiftUICharts/BarChart/Models/ChartData/HorizontalBarChartData.swift b/Sources/SwiftUICharts/BarChart/Models/ChartData/HorizontalBarChartData.swift index 1940740b..65f75ac6 100644 --- a/Sources/SwiftUICharts/BarChart/Models/ChartData/HorizontalBarChartData.swift +++ b/Sources/SwiftUICharts/BarChart/Models/ChartData/HorizontalBarChartData.swift @@ -25,7 +25,7 @@ public final class HorizontalBarChartData: CTHorizontalBarChartDataProtocol, Get @Published public final var viewData: ChartViewData @Published public final var infoView: InfoViewData = InfoViewData() - @Published public final var extraLineData: ExtraLineData! + @Published public final var extraLineData: ExtraLineData? // Publishable public var subscription = SubscriptionSet().subscription diff --git a/Sources/SwiftUICharts/BarChart/Models/ChartData/RangedBarChartData.swift b/Sources/SwiftUICharts/BarChart/Models/ChartData/RangedBarChartData.swift index 8a099084..eb0ef253 100644 --- a/Sources/SwiftUICharts/BarChart/Models/ChartData/RangedBarChartData.swift +++ b/Sources/SwiftUICharts/BarChart/Models/ChartData/RangedBarChartData.swift @@ -25,7 +25,7 @@ public final class RangedBarChartData: CTRangedBarChartDataProtocol, GetDataProt @Published public final var viewData: ChartViewData @Published public final var infoView: InfoViewData = InfoViewData() - @Published public final var extraLineData: ExtraLineData! + @Published public final var extraLineData: ExtraLineData? // Publishable public var subscription = SubscriptionSet().subscription diff --git a/Sources/SwiftUICharts/BarChart/Models/ChartData/StackedBarChartData.swift b/Sources/SwiftUICharts/BarChart/Models/ChartData/StackedBarChartData.swift index db1d7dbe..1129f6e4 100644 --- a/Sources/SwiftUICharts/BarChart/Models/ChartData/StackedBarChartData.swift +++ b/Sources/SwiftUICharts/BarChart/Models/ChartData/StackedBarChartData.swift @@ -29,7 +29,7 @@ public final class StackedBarChartData: CTMultiBarChartDataProtocol, GetDataProt @Published public final var infoView: InfoViewData = InfoViewData() @Published public final var groups: [GroupingData] - @Published public final var extraLineData: ExtraLineData! + @Published public final var extraLineData: ExtraLineData? // Publishable public var subscription = SubscriptionSet().subscription diff --git a/Sources/SwiftUICharts/LineChart/Models/ChartData/LineChartData.swift b/Sources/SwiftUICharts/LineChart/Models/ChartData/LineChartData.swift index bc8ff1b3..f9957935 100644 --- a/Sources/SwiftUICharts/LineChart/Models/ChartData/LineChartData.swift +++ b/Sources/SwiftUICharts/LineChart/Models/ChartData/LineChartData.swift @@ -30,7 +30,7 @@ public final class LineChartData: CTLineChartDataProtocol, GetDataProtocol, Publ public final var noDataText: Text public final var chartType: (chartType: ChartType, dataSetType: DataSetType) - @Published public final var extraLineData: ExtraLineData! + @Published public final var extraLineData: ExtraLineData? // Publishable public var subscription = SubscriptionSet().subscription diff --git a/Sources/SwiftUICharts/LineChart/Models/ChartData/MultiLineChartData.swift b/Sources/SwiftUICharts/LineChart/Models/ChartData/MultiLineChartData.swift index bc43c315..2bbfef31 100644 --- a/Sources/SwiftUICharts/LineChart/Models/ChartData/MultiLineChartData.swift +++ b/Sources/SwiftUICharts/LineChart/Models/ChartData/MultiLineChartData.swift @@ -30,7 +30,7 @@ public final class MultiLineChartData: CTLineChartDataProtocol, GetDataProtocol, public final var noDataText: Text public final var chartType: (chartType: ChartType, dataSetType: DataSetType) - @Published public final var extraLineData: ExtraLineData! + @Published public final var extraLineData: ExtraLineData? // Publishable public var subscription = SubscriptionSet().subscription diff --git a/Sources/SwiftUICharts/LineChart/Models/ChartData/RangedLineChartData.swift b/Sources/SwiftUICharts/LineChart/Models/ChartData/RangedLineChartData.swift index 3ab57ca4..648d2135 100644 --- a/Sources/SwiftUICharts/LineChart/Models/ChartData/RangedLineChartData.swift +++ b/Sources/SwiftUICharts/LineChart/Models/ChartData/RangedLineChartData.swift @@ -30,7 +30,7 @@ public final class RangedLineChartData: CTLineChartDataProtocol, GetDataProtocol public final var noDataText: Text public final var chartType: (chartType: ChartType, dataSetType: DataSetType) - @Published public final var extraLineData: ExtraLineData! + @Published public final var extraLineData: ExtraLineData? // Publishable public var subscription = SubscriptionSet().subscription diff --git a/Sources/SwiftUICharts/PieChart/Views/DoughnutChart.swift b/Sources/SwiftUICharts/PieChart/Views/DoughnutChart.swift index d40c6b5f..173724de 100644 --- a/Sources/SwiftUICharts/PieChart/Views/DoughnutChart.swift +++ b/Sources/SwiftUICharts/PieChart/Views/DoughnutChart.swift @@ -82,7 +82,7 @@ public struct DoughnutChart: View where ChartData: DoughnutChartData if chartData.disableAnimation { return 1 } else { - return startAnimation ? 1 : 0 + return startAnimation ? 1 : 0.001 } } } diff --git a/Sources/SwiftUICharts/Shared/Types/Stroke.swift b/Sources/SwiftUICharts/Shared/Types/Stroke.swift index d6b2300e..ce9a74b3 100644 --- a/Sources/SwiftUICharts/Shared/Types/Stroke.swift +++ b/Sources/SwiftUICharts/Shared/Types/Stroke.swift @@ -37,7 +37,9 @@ public struct Stroke: Hashable, Identifiable { self.miterLimit = miterLimit self.dash = dash self.dashPhase = dashPhase - } + } + + static let `default` = Stroke() } extension Stroke { diff --git a/Sources/SwiftUICharts/Shared/ViewModifiers/TouchOverlay.swift b/Sources/SwiftUICharts/Shared/ViewModifiers/TouchOverlay.swift index a0044f53..00e764b7 100644 --- a/Sources/SwiftUICharts/Shared/ViewModifiers/TouchOverlay.swift +++ b/Sources/SwiftUICharts/Shared/ViewModifiers/TouchOverlay.swift @@ -15,6 +15,9 @@ internal struct TouchOverlay: ViewModifier where T: CTChartData { @ObservedObject private var chartData: T let minDistance: CGFloat + private let specifier: String + private let formatter: NumberFormatter? + private let unit: TouchUnit internal init( chartData: T, @@ -25,9 +28,9 @@ internal struct TouchOverlay: ViewModifier where T: CTChartData { ) { self.chartData = chartData self.minDistance = minDistance - self.chartData.infoView.touchSpecifier = specifier - self.chartData.infoView.touchFormatter = formatter - self.chartData.infoView.touchUnit = unit + self.specifier = specifier + self.formatter = formatter + self.unit = unit } internal func body(content: Content) -> some View { @@ -55,6 +58,11 @@ internal struct TouchOverlay: ViewModifier where T: CTChartData { } } else { content } } + .onAppear { + self.chartData.infoView.touchSpecifier = specifier + self.chartData.infoView.touchFormatter = formatter + self.chartData.infoView.touchUnit = unit + } } } #endif diff --git a/Sources/SwiftUICharts/SharedLineAndBar/Models/Protocols/LineAndBarProtocols.swift b/Sources/SwiftUICharts/SharedLineAndBar/Models/Protocols/LineAndBarProtocols.swift index 5c97d057..02077873 100644 --- a/Sources/SwiftUICharts/SharedLineAndBar/Models/Protocols/LineAndBarProtocols.swift +++ b/Sources/SwiftUICharts/SharedLineAndBar/Models/Protocols/LineAndBarProtocols.swift @@ -38,7 +38,7 @@ public protocol CTLineBarChartDataProtocol: CTChartData where CTStyle: CTLineBar /** A data model for the `ExtraLine` View Modifier */ - var extraLineData: ExtraLineData! { get set } + var extraLineData: ExtraLineData? { get set } /** A type representing a View for displaying second set of labels on the Y axis. diff --git a/Sources/SwiftUICharts/SharedLineAndBar/Models/Protocols/LineAndBarProtocolsExtentions.swift b/Sources/SwiftUICharts/SharedLineAndBar/Models/Protocols/LineAndBarProtocolsExtentions.swift index fb98b591..9d10de08 100644 --- a/Sources/SwiftUICharts/SharedLineAndBar/Models/Protocols/LineAndBarProtocolsExtentions.swift +++ b/Sources/SwiftUICharts/SharedLineAndBar/Models/Protocols/LineAndBarProtocolsExtentions.swift @@ -311,12 +311,12 @@ extension CTLineBarChartDataProtocol { internal var extraLabelsArray: [String] { self.generateExtraYLabels(self.viewData.yAxisSpecifier) } private func generateExtraYLabels(_ specifier: String) -> [String] { - - let dataRange: Double = self.extraLineData.range - let minValue: Double = self.extraLineData.minValue - let range: Double = dataRange / Double(self.extraLineData.style.yAxisNumberOfLabels-1) + guard let extraLineData = extraLineData else { return [] } + let dataRange: Double = extraLineData.range + let minValue: Double = extraLineData.minValue + let range: Double = dataRange / Double(extraLineData.style.yAxisNumberOfLabels-1) let firstLabel = [String(format: specifier, minValue)] - let otherLabels = (1...self.extraLineData.style.yAxisNumberOfLabels-1).map { String(format: specifier, minValue + range * Double($0)) } + let otherLabels = (1...extraLineData.style.yAxisNumberOfLabels-1).map { String(format: specifier, minValue + range * Double($0)) } let labels = firstLabel + otherLabels return labels @@ -363,7 +363,7 @@ extension CTLineBarChartDataProtocol { public func getExtraYAxisTitle(colour: AxisColour) -> some View { Group { - if let title = self.extraLineData.style.yAxisTitle { + if let title = self.extraLineData?.style.yAxisTitle { VStack { if self.chartStyle.xAxisLabelPosition == .top { Spacer() @@ -391,7 +391,7 @@ extension CTLineBarChartDataProtocol { case .none: EmptyView() case .style(let size): - self.getAxisColourAsCircle(customColour: self.extraLineData.style.lineColour, width: size) + self.getAxisColourAsCircle(customColour: self.extraLineData?.style.lineColour ?? ColourStyle(), width: size) case .custom(let colour, let size): self.getAxisColourAsCircle(customColour: colour, width: size) } diff --git a/Sources/SwiftUICharts/SharedLineAndBar/ViewModifiers/ExtraLine.swift b/Sources/SwiftUICharts/SharedLineAndBar/ViewModifiers/ExtraLine.swift index 5a8ae167..9c7ad400 100644 --- a/Sources/SwiftUICharts/SharedLineAndBar/ViewModifiers/ExtraLine.swift +++ b/Sources/SwiftUICharts/SharedLineAndBar/ViewModifiers/ExtraLine.swift @@ -12,17 +12,20 @@ internal struct ExtraLine: ViewModifier where T: CTLineBarChartDataProtocol { @ObservedObject private var chartData: T - init( + private let legendTitle: String + private let datapoints: () -> ([ExtraLineDataPoint]) + private let style: () -> (ExtraLineStyle) + + internal init( chartData: T, legendTitle: String, - datapoints: @escaping ()->([ExtraLineDataPoint]), - style: @escaping ()->(ExtraLineStyle) + datapoints: @escaping () -> ([ExtraLineDataPoint]), + style: @escaping () -> (ExtraLineStyle) ) { self.chartData = chartData - self.chartData.extraLineData = ExtraLineData(legendTitle: legendTitle, - dataPoints: datapoints, - style: style) - self.lineLegendSetup() + self.legendTitle = legendTitle + self.datapoints = datapoints + self.style = style } @State private var startAnimation: Bool = false @@ -31,29 +34,32 @@ internal struct ExtraLine: ViewModifier where T: CTLineBarChartDataProtocol { Group { if chartData.isGreaterThanTwo() { ZStack { - if chartData.extraLineData.style.lineColour.colourType == .colour, - let colour = chartData.extraLineData.style.lineColour.colour + if let extraLineData = chartData.extraLineData, + extraLineData.style.lineColour.colourType == .colour, + let colour = chartData.extraLineData?.style.lineColour.colour { Group { - ColourExtraLineView(chartData: chartData, colour: colour, stroke: chartData.extraLineData.style.strokeStyle) + ColourExtraLineView(chartData: chartData, colour: colour, stroke: chartData.extraLineData?.style.strokeStyle ?? .default) PointsExtraLineView(chartData: chartData) } - } else if chartData.extraLineData.style.lineColour.colourType == .gradientColour, - let colours = chartData.extraLineData.style.lineColour.colours, - let startPoint = chartData.extraLineData.style.lineColour.startPoint, - let endPoint = chartData.extraLineData.style.lineColour.endPoint + } else if let extraLineData = chartData.extraLineData, + extraLineData.style.lineColour.colourType == .gradientColour, + let colours = chartData.extraLineData?.style.lineColour.colours, + let startPoint = chartData.extraLineData?.style.lineColour.startPoint, + let endPoint = chartData.extraLineData?.style.lineColour.endPoint { Group { - ColoursExtraLineView(chartData: chartData, colours: colours, startPoint: startPoint, endPoint: endPoint, stroke: chartData.extraLineData.style.strokeStyle) + ColoursExtraLineView(chartData: chartData, colours: colours, startPoint: startPoint, endPoint: endPoint, stroke: chartData.extraLineData?.style.strokeStyle ?? .default) PointsExtraLineView(chartData: chartData) } - } else if chartData.extraLineData.style.lineColour.colourType == .gradientStops, - let stops = chartData.extraLineData.style.lineColour.stops, - let startPoint = chartData.extraLineData.style.lineColour.startPoint, - let endPoint = chartData.extraLineData.style.lineColour.endPoint + } else if let extraLineData = chartData.extraLineData, + extraLineData.style.lineColour.colourType == .gradientStops, + let stops = chartData.extraLineData?.style.lineColour.stops, + let startPoint = chartData.extraLineData?.style.lineColour.startPoint, + let endPoint = chartData.extraLineData?.style.lineColour.endPoint { Group { - StopsExtraLineView(chartData: chartData, stops: stops, startPoint: startPoint, endPoint: endPoint, stroke: chartData.extraLineData.style.strokeStyle) + StopsExtraLineView(chartData: chartData, stops: stops, startPoint: startPoint, endPoint: endPoint, stroke: chartData.extraLineData?.style.strokeStyle ?? .default) PointsExtraLineView(chartData: chartData) } } @@ -61,58 +67,65 @@ internal struct ExtraLine: ViewModifier where T: CTLineBarChartDataProtocol { } } else { content } } + .onAppear { + self.chartData.extraLineData = ExtraLineData(legendTitle: legendTitle, + dataPoints: datapoints, + style: style) + self.lineLegendSetup() + } } private func lineLegendSetup() { - if self.chartData.extraLineData.style.lineColour.colourType == .colour, - let colour = self.chartData.extraLineData.style.lineColour.colour + guard let extraLineData = chartData.extraLineData else { return } + if extraLineData.style.lineColour.colourType == .colour, + let colour = extraLineData.style.lineColour.colour { if !chartData.legends.contains(where: { - $0.legend == chartData.extraLineData.legendTitle && + $0.legend == extraLineData.legendTitle && $0.colour == ColourStyle(colour: colour) && $0.prioity == 3 && $0.chartType == .line }) { - chartData.legends.append(LegendData(id: self.chartData.extraLineData.id, - legend: self.chartData.extraLineData.legendTitle, + chartData.legends.append(LegendData(id: extraLineData.id, + legend: extraLineData.legendTitle, colour: ColourStyle(colour: colour), - strokeStyle: self.chartData.extraLineData.style.strokeStyle, + strokeStyle: self.chartData.extraLineData?.style.strokeStyle, prioity: 3, chartType: .line)) } - } else if self.chartData.extraLineData.style.lineColour.colourType == .gradientColour, - let colours = self.chartData.extraLineData.style.lineColour.colours + } else if extraLineData.style.lineColour.colourType == .gradientColour, + let colours = extraLineData.style.lineColour.colours { if !chartData.legends.contains(where: { - $0.legend == chartData.extraLineData.legendTitle && + $0.legend == extraLineData.legendTitle && $0.colour == ColourStyle(colours: colours, startPoint: .leading, endPoint: .trailing) && $0.prioity == 3 && $0.chartType == .line }) { - chartData.legends.append(LegendData(id: self.chartData.extraLineData.id, - legend: self.chartData.extraLineData.legendTitle, + chartData.legends.append(LegendData(id: extraLineData.id, + legend: extraLineData.legendTitle, colour: ColourStyle(colours: colours, startPoint: .leading, endPoint: .trailing), - strokeStyle: self.chartData.extraLineData.style.strokeStyle, + strokeStyle: extraLineData.style.strokeStyle, prioity: 3, chartType: .line)) } - } else if self.chartData.extraLineData.style.lineColour.colourType == .gradientStops, - let stops = self.chartData.extraLineData.style.lineColour.stops + } else if extraLineData.style.lineColour.colourType == .gradientStops, + let stops = extraLineData.style.lineColour.stops { if !chartData.legends.contains(where: { - $0.legend == chartData.extraLineData.legendTitle && + $0.legend == extraLineData.legendTitle && $0.colour == ColourStyle(stops: stops, startPoint: .leading, endPoint: .trailing) && $0.prioity == 3 && $0.chartType == .line }) { - chartData.legends.append(LegendData(id: self.chartData.extraLineData.id, - legend: self.chartData.extraLineData.legendTitle, + chartData.legends.append(LegendData(id: extraLineData.id, + legend: extraLineData.legendTitle, colour: ColourStyle(stops: stops, startPoint: .leading, endPoint: .trailing), - strokeStyle: self.chartData.extraLineData.style.strokeStyle, + strokeStyle: extraLineData.style.strokeStyle, prioity: 3, chartType: .line)) } @@ -196,13 +209,13 @@ internal struct ColourExtraLineView: View where ChartData: CTLineBarC @State private var startAnimation: Bool = false var body: some View { - - ExtraLineShape(dataPoints: chartData.extraLineData.dataPoints.map(\.value), - lineType: chartData.extraLineData.style.lineType, - lineSpacing: chartData.extraLineData.style.lineSpacing, - range: chartData.extraLineData.range, - minValue: chartData.extraLineData.minValue) - .ifElse(chartData.extraLineData.style.animationType == .draw, if: { + if let extraLineData = chartData.extraLineData { + ExtraLineShape(dataPoints: extraLineData.dataPoints.map(\.value), + lineType: extraLineData.style.lineType, + lineSpacing: extraLineData.style.lineSpacing, + range: extraLineData.range, + minValue: extraLineData.minValue) + .ifElse(extraLineData.style.animationType == .draw, if: { $0.trim(to: animationValue) .stroke(colour, style: stroke.strokeToStrokeStyle()) }, else: { @@ -216,6 +229,9 @@ internal struct ColourExtraLineView: View where ChartData: CTLineBarC self.startAnimation = false } .zIndex(1) + } else { + EmptyView() + } } var animationValue: CGFloat { @@ -253,12 +269,13 @@ internal struct ColoursExtraLineView: View where ChartData: CTLineBar @State private var startAnimation: Bool = false var body: some View { - ExtraLineShape(dataPoints: chartData.extraLineData.dataPoints.map(\.value), - lineType: chartData.extraLineData.style.lineType, - lineSpacing: chartData.extraLineData.style.lineSpacing, - range: chartData.extraLineData.range, - minValue: chartData.extraLineData.minValue) - .ifElse(chartData.extraLineData.style.animationType == .draw, if: { + if let extraLineData = chartData.extraLineData { + ExtraLineShape(dataPoints: extraLineData.dataPoints.map(\.value), + lineType: extraLineData.style.lineType, + lineSpacing: extraLineData.style.lineSpacing, + range: extraLineData.range, + minValue: extraLineData.minValue) + .ifElse(extraLineData.style.animationType == .draw, if: { $0.trim(to: animationValue) .stroke(LinearGradient(gradient: Gradient(colors: colours), startPoint: startPoint, @@ -278,6 +295,9 @@ internal struct ColoursExtraLineView: View where ChartData: CTLineBar .animateOnDisappear(disabled: chartData.disableAnimation, using: chartData.chartStyle.globalAnimation) { self.startAnimation = false } + } else { + EmptyView() + } } var animationValue: CGFloat { @@ -315,12 +335,13 @@ internal struct StopsExtraLineView: View where ChartData: CTLineBarCh @State private var startAnimation: Bool = false var body: some View { - ExtraLineShape(dataPoints: chartData.extraLineData.dataPoints.map(\.value), - lineType: chartData.extraLineData.style.lineType, - lineSpacing: chartData.extraLineData.style.lineSpacing, - range: chartData.extraLineData.range, - minValue: chartData.extraLineData.minValue) - .ifElse(chartData.extraLineData.style.animationType == .draw, if: { + if let extraLineData = chartData.extraLineData { + ExtraLineShape(dataPoints: extraLineData.dataPoints.map(\.value), + lineType: extraLineData.style.lineType, + lineSpacing: extraLineData.style.lineSpacing, + range: extraLineData.range, + minValue: extraLineData.minValue) + .ifElse(extraLineData.style.animationType == .draw, if: { $0.trim(to: animationValue) .stroke(LinearGradient(gradient: Gradient(stops: stops), startPoint: startPoint, @@ -340,6 +361,9 @@ internal struct StopsExtraLineView: View where ChartData: CTLineBarCh self.startAnimation = false } .zIndex(1) + } else { + EmptyView() + } } var animationValue: CGFloat { @@ -365,42 +389,45 @@ internal struct PointsExtraLineView: View where ChartData: CTLineBarC @State private var startAnimation: Bool = false internal var body: some View { - - Group { - switch chartData.extraLineData.style.pointStyle.pointType { - case .filled: - ForEach(chartData.extraLineData.dataPoints.indices, id: \.self) { index in - FilledDataPointExtraLineView(chartData: chartData, - dataPoint: chartData.extraLineData.dataPoints[index], - index: index) - } - - case .outline: - ForEach(chartData.extraLineData.dataPoints.indices, id: \.self) { index in - OutLineDataPointExtraLineView(chartData: chartData, - dataPoint: chartData.extraLineData.dataPoints[index], - index: index) - } - - case .filledOutLine: - ForEach(chartData.extraLineData.dataPoints.indices, id: \.self) { index in - FilledDataPointExtraLineView(chartData: chartData, - dataPoint: chartData.extraLineData.dataPoints[index], - index: index) - .background(Point(value: chartData.extraLineData.dataPoints[index].value, + if let extraLineData = chartData.extraLineData { + Group { + switch extraLineData.style.pointStyle.pointType { + case .filled: + ForEach(extraLineData.dataPoints.indices, id: \.self) { index in + FilledDataPointExtraLineView(chartData: chartData, + dataPoint: extraLineData.dataPoints[index], + index: index) + } + + case .outline: + ForEach(extraLineData.dataPoints.indices, id: \.self) { index in + OutLineDataPointExtraLineView(chartData: chartData, + dataPoint: extraLineData.dataPoints[index], + index: index) + } + + case .filledOutLine: + ForEach(extraLineData.dataPoints.indices, id: \.self) { index in + FilledDataPointExtraLineView(chartData: chartData, + dataPoint: extraLineData.dataPoints[index], + index: index) + .background(Point(value: extraLineData.dataPoints[index].value, index: index, - minValue: chartData.extraLineData.minValue, - range: chartData.extraLineData.range, - datapointCount: chartData.extraLineData.dataPoints.count, - pointSize: chartData.extraLineData.style.pointStyle.pointSize, + minValue: extraLineData.minValue, + range: extraLineData.range, + datapointCount: extraLineData.dataPoints.count, + pointSize: extraLineData.style.pointStyle.pointSize, ignoreZero: false, - pointStyle: chartData.extraLineData.style.pointStyle.pointShape) - .foregroundColor(chartData.extraLineData.dataPoints[index].pointColour?.fill ?? chartData.extraLineData.style.pointStyle.fillColour) + pointStyle: extraLineData.style.pointStyle.pointShape) + .foregroundColor(extraLineData.dataPoints[index].pointColour?.fill ?? extraLineData.style.pointStyle.fillColour) ) + } } } + .zIndex(1.0) + } else { + EmptyView() } - .zIndex(1.0) } } @@ -424,25 +451,25 @@ internal struct FilledDataPointExtraLineView: View where ChartData: C @State private var startAnimation: Bool = false internal var body: some View { - - switch chartData.extraLineData.style.lineSpacing { - case .line: - Point(value: dataPoint.value, - index: index, - minValue: chartData.extraLineData.minValue, - range: chartData.extraLineData.range, - datapointCount: chartData.extraLineData.dataPoints.count, - pointSize: chartData.extraLineData.style.pointStyle.pointSize, - ignoreZero: false, - pointStyle: chartData.extraLineData.style.pointStyle.pointShape) - .ifElse(chartData.extraLineData.style.animationType == .draw, if: { + if let extraLineData = chartData.extraLineData { + switch extraLineData.style.lineSpacing { + case .line: + Point(value: dataPoint.value, + index: index, + minValue: extraLineData.minValue, + range: extraLineData.range, + datapointCount: extraLineData.dataPoints.count, + pointSize: extraLineData.style.pointStyle.pointSize, + ignoreZero: false, + pointStyle: extraLineData.style.pointStyle.pointShape) + .ifElse(extraLineData.style.animationType == .draw, if: { $0 .trim(to: animationValue) - .fill(dataPoint.pointColour?.fill ?? chartData.extraLineData.style.pointStyle.fillColour) + .fill(dataPoint.pointColour?.fill ?? extraLineData.style.pointStyle.fillColour) }, else: { $0 .scale(y: animationValue, anchor: .bottom) - .fill(dataPoint.pointColour?.fill ?? chartData.extraLineData.style.pointStyle.fillColour) + .fill(dataPoint.pointColour?.fill ?? extraLineData.style.pointStyle.fillColour) }) .animateOnAppear(disabled: chartData.disableAnimation, using: chartData.chartStyle.globalAnimation) { self.startAnimation = true @@ -450,23 +477,23 @@ internal struct FilledDataPointExtraLineView: View where ChartData: C .animateOnDisappear(disabled: chartData.disableAnimation, using: chartData.chartStyle.globalAnimation) { self.startAnimation = false } - case .bar: - PointBarSpcing(value: dataPoint.value, - index: index, - minValue: chartData.extraLineData.minValue, - range: chartData.extraLineData.range, - datapointCount: chartData.extraLineData.dataPoints.count, - pointSize: chartData.extraLineData.style.pointStyle.pointSize, - ignoreZero: false, - pointStyle: chartData.extraLineData.style.pointStyle.pointShape) - .ifElse(chartData.extraLineData.style.animationType == .draw, if: { + case .bar: + PointBarSpcing(value: dataPoint.value, + index: index, + minValue: extraLineData.minValue, + range: extraLineData.range, + datapointCount: extraLineData.dataPoints.count, + pointSize: extraLineData.style.pointStyle.pointSize, + ignoreZero: false, + pointStyle: extraLineData.style.pointStyle.pointShape) + .ifElse(extraLineData.style.animationType == .draw, if: { $0 .trim(to: animationValue) - .fill(dataPoint.pointColour?.fill ?? chartData.extraLineData.style.pointStyle.fillColour) + .fill(dataPoint.pointColour?.fill ?? extraLineData.style.pointStyle.fillColour) }, else: { $0 .scale(y: animationValue, anchor: .bottom) - .fill(dataPoint.pointColour?.fill ?? chartData.extraLineData.style.pointStyle.fillColour) + .fill(dataPoint.pointColour?.fill ?? extraLineData.style.pointStyle.fillColour) }) .animateOnAppear(disabled: chartData.disableAnimation, using: chartData.chartStyle.globalAnimation) { self.startAnimation = true @@ -474,6 +501,9 @@ internal struct FilledDataPointExtraLineView: View where ChartData: C .animateOnDisappear(disabled: chartData.disableAnimation, using: chartData.chartStyle.globalAnimation) { self.startAnimation = false } + } + } else { + EmptyView() } } @@ -506,25 +536,25 @@ internal struct OutLineDataPointExtraLineView: View where ChartData: @State private var startAnimation: Bool = false internal var body: some View { - - switch chartData.extraLineData.style.lineSpacing { - case .line: - Point(value: dataPoint.value, - index: index, - minValue: chartData.extraLineData.minValue, - range: chartData.extraLineData.range, - datapointCount: chartData.extraLineData.dataPoints.count, - pointSize: chartData.extraLineData.style.pointStyle.pointSize, - ignoreZero: false, - pointStyle: chartData.extraLineData.style.pointStyle.pointShape) - .ifElse(chartData.extraLineData.style.animationType == .draw, if: { + if let extraLineData = chartData.extraLineData { + switch extraLineData.style.lineSpacing { + case .line: + Point(value: dataPoint.value, + index: index, + minValue: extraLineData.minValue, + range: extraLineData.range, + datapointCount: extraLineData.dataPoints.count, + pointSize: extraLineData.style.pointStyle.pointSize, + ignoreZero: false, + pointStyle: extraLineData.style.pointStyle.pointShape) + .ifElse(extraLineData.style.animationType == .draw, if: { $0.trim(to: animationValue) - .stroke(dataPoint.pointColour?.border ?? chartData.extraLineData.style.pointStyle.borderColour, - lineWidth: chartData.extraLineData.style.pointStyle.lineWidth) + .stroke(dataPoint.pointColour?.border ?? extraLineData.style.pointStyle.borderColour, + lineWidth: extraLineData.style.pointStyle.lineWidth) }, else: { $0.scale(y: animationValue, anchor: .bottom) - .stroke(dataPoint.pointColour?.border ?? chartData.extraLineData.style.pointStyle.borderColour, - lineWidth: chartData.extraLineData.style.pointStyle.lineWidth) + .stroke(dataPoint.pointColour?.border ?? extraLineData.style.pointStyle.borderColour, + lineWidth: extraLineData.style.pointStyle.lineWidth) }) .animateOnAppear(disabled: chartData.disableAnimation, using: chartData.chartStyle.globalAnimation) { self.startAnimation = true @@ -532,23 +562,23 @@ internal struct OutLineDataPointExtraLineView: View where ChartData: .animateOnDisappear(disabled: chartData.disableAnimation, using: chartData.chartStyle.globalAnimation) { self.startAnimation = false } - case .bar: - PointBarSpcing(value: dataPoint.value, - index: index, - minValue: chartData.extraLineData.minValue, - range: chartData.extraLineData.range, - datapointCount: chartData.extraLineData.dataPoints.count, - pointSize: chartData.extraLineData.style.pointStyle.pointSize, - ignoreZero: false, - pointStyle: chartData.extraLineData.style.pointStyle.pointShape) - .ifElse(chartData.extraLineData.style.animationType == .draw, if: { + case .bar: + PointBarSpcing(value: dataPoint.value, + index: index, + minValue: extraLineData.minValue, + range: extraLineData.range, + datapointCount: extraLineData.dataPoints.count, + pointSize: extraLineData.style.pointStyle.pointSize, + ignoreZero: false, + pointStyle: extraLineData.style.pointStyle.pointShape) + .ifElse(extraLineData.style.animationType == .draw, if: { $0.trim(to: animationValue) - .stroke(dataPoint.pointColour?.border ?? chartData.extraLineData.style.pointStyle.borderColour, - lineWidth: chartData.extraLineData.style.pointStyle.lineWidth) + .stroke(dataPoint.pointColour?.border ?? extraLineData.style.pointStyle.borderColour, + lineWidth: extraLineData.style.pointStyle.lineWidth) }, else: { $0.scale(y: animationValue, anchor: .bottom) - .stroke(dataPoint.pointColour?.border ?? chartData.extraLineData.style.pointStyle.borderColour, - lineWidth: chartData.extraLineData.style.pointStyle.lineWidth) + .stroke(dataPoint.pointColour?.border ?? extraLineData.style.pointStyle.borderColour, + lineWidth: extraLineData.style.pointStyle.lineWidth) }) .animateOnAppear(disabled: chartData.disableAnimation, using: chartData.chartStyle.globalAnimation) { self.startAnimation = true @@ -556,6 +586,9 @@ internal struct OutLineDataPointExtraLineView: View where ChartData: .animateOnDisappear(disabled: chartData.disableAnimation, using: chartData.chartStyle.globalAnimation) { self.startAnimation = false } + } + } else { + EmptyView() } } diff --git a/Sources/SwiftUICharts/SharedLineAndBar/ViewModifiers/ExtraYAxisLabels.swift b/Sources/SwiftUICharts/SharedLineAndBar/ViewModifiers/ExtraYAxisLabels.swift index 5838ae8e..f498f862 100644 --- a/Sources/SwiftUICharts/SharedLineAndBar/ViewModifiers/ExtraYAxisLabels.swift +++ b/Sources/SwiftUICharts/SharedLineAndBar/ViewModifiers/ExtraYAxisLabels.swift @@ -21,7 +21,6 @@ internal struct ExtraYAxisLabels: ViewModifier where T: CTLineBarChartDataPro self.chartData = chartData self.specifier = specifier self.colourIndicator = colourIndicator - chartData.viewData.hasYAxisLabels = true } internal func body(content: Content) -> some View { @@ -43,6 +42,9 @@ internal struct ExtraYAxisLabels: ViewModifier where T: CTLineBarChartDataPro } } else { content } } + .onAppear { + chartData.viewData.hasYAxisLabels = true + } } } diff --git a/Sources/SwiftUICharts/SharedLineAndBar/ViewModifiers/XAxisLabels.swift b/Sources/SwiftUICharts/SharedLineAndBar/ViewModifiers/XAxisLabels.swift index 1ad4ac9d..6a231e40 100644 --- a/Sources/SwiftUICharts/SharedLineAndBar/ViewModifiers/XAxisLabels.swift +++ b/Sources/SwiftUICharts/SharedLineAndBar/ViewModifiers/XAxisLabels.swift @@ -16,7 +16,6 @@ internal struct XAxisLabels: ViewModifier where T: CTLineBarChartDataProtocol internal init(chartData: T) { self.chartData = chartData - self.chartData.viewData.hasXAxisLabels = true } internal func body(content: Content) -> some View { @@ -40,6 +39,9 @@ internal struct XAxisLabels: ViewModifier where T: CTLineBarChartDataProtocol } else { content } } } + .onAppear { + self.chartData.viewData.hasXAxisLabels = true + } } } diff --git a/Sources/SwiftUICharts/SharedLineAndBar/ViewModifiers/YAxisLabels.swift b/Sources/SwiftUICharts/SharedLineAndBar/ViewModifiers/YAxisLabels.swift index 52252dd4..d0b3b562 100644 --- a/Sources/SwiftUICharts/SharedLineAndBar/ViewModifiers/YAxisLabels.swift +++ b/Sources/SwiftUICharts/SharedLineAndBar/ViewModifiers/YAxisLabels.swift @@ -15,6 +15,7 @@ internal struct YAxisLabels: ViewModifier where T: CTLineBarChartDataProtocol @ObservedObject private var chartData: T private let specifier: String private let colourIndicator: AxisColour + private let formatter: NumberFormatter? internal init( chartData: T, @@ -25,9 +26,7 @@ internal struct YAxisLabels: ViewModifier where T: CTLineBarChartDataProtocol self.chartData = chartData self.specifier = specifier self.colourIndicator = colourIndicator - chartData.viewData.hasYAxisLabels = true - chartData.viewData.yAxisSpecifier = specifier - chartData.viewData.yAxisNumberFormatter = formatter + self.formatter = formatter } internal func body(content: Content) -> some View { @@ -49,6 +48,11 @@ internal struct YAxisLabels: ViewModifier where T: CTLineBarChartDataProtocol } } else { content } } + .onAppear { + chartData.viewData.hasYAxisLabels = true + chartData.viewData.yAxisSpecifier = specifier + chartData.viewData.yAxisNumberFormatter = formatter + } } } diff --git a/SwiftUICharts.podspec b/SwiftUICharts.podspec index 2337925b..9c1e1e73 100644 --- a/SwiftUICharts.podspec +++ b/SwiftUICharts.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'SwiftUICharts' - s.version = '2.9.9' + s.version = '2.10.1' s.summary = 'A charts / plotting library for SwiftUI.' s.description = 'A charts / plotting library for SwiftUI. Works on macOS, iOS, watchOS, and tvOS and has accessibility features built in.' s.homepage = 'https://github.com/willdale/SwiftUICharts'