iOS 图表折线图未在 SwiftUI 中点击/拖动时选择值 - 最新版本 4.0.2
您预计会发生什么?
当我点击或拖动图表时,我希望它一一选择所有条目。
相反发生了什么?
但是,它仅选择最右侧的值。这真的很奇怪。
图表环境
最新版本:4.0.2
XCode 13.2.1
斯威夫特 5.5.2
仅限 iOS
macOS 12.1
运行 XCode演示项目的
[代码改编自 Stewart Lynch 的本教程:https://www.youtube.com/watch?v=csd7pyfEXgw 他制作了一个条形图,我将其转换为折线图并添加了一些额外的位,例如渐变]
LineChartView:
import SwiftUI
import Charts
struct TimeTakenLineChartView: UIViewRepresentable { \
let entries: [ChartDataEntry]
let lineChart = LineChartView()
@Binding var selectedYear: Int
@Binding var selectedItem: String
func makeUIView(context: Context) -> LineChartView {
lineChart.delegate = context.coordinator
lineChart.animate(xAxisDuration: 2)
lineChart.backgroundColor = UIColor(Color.gray)
return lineChart
}
func updateUIView(_ uiView: LineChartView, context: Context) {
let dataSet = LineChartDataSet(entries: entries)
uiView.noDataText = "No Data"
uiView.data = LineChartData(dataSet: dataSet)
uiView.rightAxis.enabled = false
uiView.setScaleEnabled(false)
uiView.notifyDataSetChanged()
formatDataSet(dataSet: dataSet)
formatLeftAxis(leftAxis: uiView.leftAxis)
formatXAxis(xAxis: uiView.xAxis)
formatLegend(legend: uiView.legend)
// data set updates
dataSet.lineWidth = 3
dataSet.label = "Seconds Taken"
dataSet.drawValuesEnabled = false
dataSet.drawCirclesEnabled = false
dataSet.mode = .cubicBezier // add this line
dataSet.drawHorizontalHighlightIndicatorEnabled = false
dataSet.highlightColor = .white
// Gradient
let gradientColors = [UIColor(Color.blue).cgColor, UIColor(Color.green).cgColor] as CFArray // Colors of the gradient
let colorLocations:[CGFloat] = [1.0, 1.0] // Positioning of the gradient
let gradient = CGGradient.init(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: gradientColors, locations: colorLocations) // Gradient Object
dataSet.isDrawLineWithGradientEnabled = true
dataSet.gradientPositions = colorLocations
dataSet.fill = LinearGradientFill(gradient: gradient!)
dataSet.drawFilledEnabled = true // Draw the Gradient
}
class Coordinator: NSObject, ChartViewDelegate {
let parent:TimeTakenLineChartView
init(parent: TimeTakenLineChartView) {
self.parent = parent
}
func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
let quantity = Int(entry.y)
parent.selectedItem = "\(quantity) seconds"
}
}
func makeCoordinator() -> Coordinator {
return Coordinator(parent: self)
}
func formatDataSet(dataSet: LineChartDataSet) {
dataSet.colors = [.blue]
dataSet.valueColors = [.blue]
let formatter = NumberFormatter()
formatter.numberStyle = .none
dataSet.valueFormatter = DefaultValueFormatter(formatter: formatter)
}
func formatLeftAxis(leftAxis: YAxis) {
leftAxis.labelTextColor = .white
let formatter = NumberFormatter()
formatter.numberStyle = .none
leftAxis.valueFormatter = DefaultAxisValueFormatter(formatter: formatter)
leftAxis.axisMinimum = 0
leftAxis.drawGridLinesEnabled = false
leftAxis.labelFont = .boldSystemFont(ofSize: 15)
leftAxis.drawAxisLineEnabled = false
leftAxis.drawLabelsEnabled = false
}
func formatXAxis(xAxis: XAxis) {
let formatter = NumberFormatter()
formatter.numberStyle = .none
xAxis.valueFormatter = DefaultAxisValueFormatter(formatter: formatter)
xAxis.labelPosition = .bottom
xAxis.labelTextColor = .white
xAxis.labelFont = .boldSystemFont(ofSize: 15)
xAxis.drawGridLinesEnabled = false
xAxis.drawAxisLineEnabled = false
}
func formatLegend(legend: Legend) {
legend.textColor = .white
legend.horizontalAlignment = .right
legend.verticalAlignment = .top
legend.drawInside = true
legend.yOffset = 30.0
legend.form = Legend.Form.circle
legend.formSize = CGFloat(12.0)
legend.font = .boldSystemFont(ofSize: 15)
}
}
ContentView:
import SwiftUI
import Charts
struct ContentView: View {
@State private var selectedYear: Int = 2019
@State private var barEntries: [ChartDataEntry] = []
@State private var selectedItem = ""
@State private var entries = [ChartDataEntry]()
var body: some View {
VStack {
Text("\(selectedYear)".replacingOccurrences(of: ",", with: ""))
.font(.title2)
Button("Change Year") {
// if selectedYear == 2019 {
// selectedYear = 2020
// } else {
// selectedYear = 2019
// }
}
TimeTakenLineChartView(entries: entries, selectedYear: $selectedYear, selectedItem: $selectedItem)
.frame(width: 300, height: 300)
Text(selectedItem)
}
.onAppear {
entries = WineTransaction.dataEntriesForYear(selectedYear, transactions: WineTransaction.allTransactions)
}
}
}
任何帮助表示赞赏!
What did you expect to happen?
When I tap or drag across the chart I expected it to select all the entries one-by-one.
What happened instead?
However, it only selects the values on the far right. Which is really weird.
Charts Environment
Latest Release: 4.0.2
XCode 13.2.1
Swift 5.5.2
iOS only
macOS 12.1 running XCode
Demo Project
[Code adapted from this tutorial by Stewart Lynch: https://www.youtube.com/watch?v=csd7pyfEXgw
He made a bar chart, I converted it to a Line chart and added some extra bits like the gradient]
LineChartView:
import SwiftUI
import Charts
struct TimeTakenLineChartView: UIViewRepresentable { \
let entries: [ChartDataEntry]
let lineChart = LineChartView()
@Binding var selectedYear: Int
@Binding var selectedItem: String
func makeUIView(context: Context) -> LineChartView {
lineChart.delegate = context.coordinator
lineChart.animate(xAxisDuration: 2)
lineChart.backgroundColor = UIColor(Color.gray)
return lineChart
}
func updateUIView(_ uiView: LineChartView, context: Context) {
let dataSet = LineChartDataSet(entries: entries)
uiView.noDataText = "No Data"
uiView.data = LineChartData(dataSet: dataSet)
uiView.rightAxis.enabled = false
uiView.setScaleEnabled(false)
uiView.notifyDataSetChanged()
formatDataSet(dataSet: dataSet)
formatLeftAxis(leftAxis: uiView.leftAxis)
formatXAxis(xAxis: uiView.xAxis)
formatLegend(legend: uiView.legend)
// data set updates
dataSet.lineWidth = 3
dataSet.label = "Seconds Taken"
dataSet.drawValuesEnabled = false
dataSet.drawCirclesEnabled = false
dataSet.mode = .cubicBezier // add this line
dataSet.drawHorizontalHighlightIndicatorEnabled = false
dataSet.highlightColor = .white
// Gradient
let gradientColors = [UIColor(Color.blue).cgColor, UIColor(Color.green).cgColor] as CFArray // Colors of the gradient
let colorLocations:[CGFloat] = [1.0, 1.0] // Positioning of the gradient
let gradient = CGGradient.init(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: gradientColors, locations: colorLocations) // Gradient Object
dataSet.isDrawLineWithGradientEnabled = true
dataSet.gradientPositions = colorLocations
dataSet.fill = LinearGradientFill(gradient: gradient!)
dataSet.drawFilledEnabled = true // Draw the Gradient
}
class Coordinator: NSObject, ChartViewDelegate {
let parent:TimeTakenLineChartView
init(parent: TimeTakenLineChartView) {
self.parent = parent
}
func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
let quantity = Int(entry.y)
parent.selectedItem = "\(quantity) seconds"
}
}
func makeCoordinator() -> Coordinator {
return Coordinator(parent: self)
}
func formatDataSet(dataSet: LineChartDataSet) {
dataSet.colors = [.blue]
dataSet.valueColors = [.blue]
let formatter = NumberFormatter()
formatter.numberStyle = .none
dataSet.valueFormatter = DefaultValueFormatter(formatter: formatter)
}
func formatLeftAxis(leftAxis: YAxis) {
leftAxis.labelTextColor = .white
let formatter = NumberFormatter()
formatter.numberStyle = .none
leftAxis.valueFormatter = DefaultAxisValueFormatter(formatter: formatter)
leftAxis.axisMinimum = 0
leftAxis.drawGridLinesEnabled = false
leftAxis.labelFont = .boldSystemFont(ofSize: 15)
leftAxis.drawAxisLineEnabled = false
leftAxis.drawLabelsEnabled = false
}
func formatXAxis(xAxis: XAxis) {
let formatter = NumberFormatter()
formatter.numberStyle = .none
xAxis.valueFormatter = DefaultAxisValueFormatter(formatter: formatter)
xAxis.labelPosition = .bottom
xAxis.labelTextColor = .white
xAxis.labelFont = .boldSystemFont(ofSize: 15)
xAxis.drawGridLinesEnabled = false
xAxis.drawAxisLineEnabled = false
}
func formatLegend(legend: Legend) {
legend.textColor = .white
legend.horizontalAlignment = .right
legend.verticalAlignment = .top
legend.drawInside = true
legend.yOffset = 30.0
legend.form = Legend.Form.circle
legend.formSize = CGFloat(12.0)
legend.font = .boldSystemFont(ofSize: 15)
}
}
ContentView:
import SwiftUI
import Charts
struct ContentView: View {
@State private var selectedYear: Int = 2019
@State private var barEntries: [ChartDataEntry] = []
@State private var selectedItem = ""
@State private var entries = [ChartDataEntry]()
var body: some View {
VStack {
Text("\(selectedYear)".replacingOccurrences(of: ",", with: ""))
.font(.title2)
Button("Change Year") {
// if selectedYear == 2019 {
// selectedYear = 2020
// } else {
// selectedYear = 2019
// }
}
TimeTakenLineChartView(entries: entries, selectedYear: $selectedYear, selectedItem: $selectedItem)
.frame(width: 300, height: 300)
Text(selectedItem)
}
.onAppear {
entries = WineTransaction.dataEntriesForYear(selectedYear, transactions: WineTransaction.allTransactions)
}
}
}
Any help appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论