问题
I am trying to draw a chart where the x-axis is TimeInterval
and Y-axis is power consumption
. There will be too much data to show as for each day there will be data. For that reason, I want to show 5 x values at a time. I achieved that by setting self.chart.setVisibleXRangeMaximum(5)
after setting data for the chart. Though 5 x-axis values are showing but the values are repeating for an indefinite time. Like if the first day is 10/10/2016 all the x-axis values after that are the same for indefinite scrolling (see below screenshot). Some other SO answers say that setting granularity enabled will fix that but even after enabling that it's showing the repeated indefinite value of the first point. How can I solve this?
code I am using currently (using dummy data for testing purposes)
func setupChart(){
self.chart = BarChartView()
self.chart.translatesAutoresizingMaskIntoConstraints = false
self.chart.chartDescription?.enabled = false
self.chart.dragEnabled = true
self.chart.setScaleEnabled(true)
self.chart.pinchZoomEnabled = true
self.chart.delegate = self
self.chart.drawBarShadowEnabled = false
self.chart.drawValueAboveBarEnabled = true
let xAxis = self.chart.xAxis
xAxis.labelPosition = .bottom
xAxis.labelFont = .systemFont(ofSize: 10)
xAxis.granularityEnabled = true
xAxis.granularity = 1
xAxis.labelCount = 5
xAxis.drawGridLinesEnabled = false
xAxis.valueFormatter = DateValueFormatter() //DayAxisValueFormatter(chart: self.chart)
let leftAxisFormatter = NumberFormatter()
leftAxisFormatter.minimumFractionDigits = 0
leftAxisFormatter.maximumFractionDigits = 1
leftAxisFormatter.negativeSuffix = " KWH"
leftAxisFormatter.positiveSuffix = " KWH"
let leftAxis = self.chart.leftAxis
leftAxis.labelFont = .systemFont(ofSize: 10)
leftAxis.drawGridLinesEnabled = false
leftAxis.valueFormatter = DefaultAxisValueFormatter(formatter: leftAxisFormatter)
leftAxis.labelPosition = .outsideChart
leftAxis.spaceTop = 0.15
leftAxis.labelCount = 8
leftAxis.axisMinimum = 0 // FIXME: HUH?? this replaces startAtZero = YES
let l = self.chart.legend
l.horizontalAlignment = .left
l.verticalAlignment = .bottom
l.orientation = .horizontal
l.drawInside = false
l.form = .circle
l.formSize = 9
l.font = UIFont(name: "HelveticaNeue-Light", size: 11)!
l.xEntrySpace = 4
let marker = XYMarkerView(color: UIColor(white: 180/250, alpha: 1),
font: .systemFont(ofSize: 12),
textColor: .white,
insets: UIEdgeInsets(top: 8, left: 8, bottom: 20, right: 8),
xAxisValueFormatter: self.chart.xAxis.valueFormatter!)
marker.chartView = self.chart
marker.minimumSize = CGSize(width: 80, height: 40)
self.chart.marker = marker
self.chart.rightAxis.enabled = false
self.addSubview(self.chart)
let upperConstraintChart = NSLayoutConstraint(item: self.chart, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self.titleLabel!, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 20)
let leftConstraintChart = NSLayoutConstraint(item: self.chart, attribute: NSLayoutAttribute.left, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.left, multiplier: 1, constant: 10)
let rightConstraintChart = NSLayoutConstraint(item: self.chart, attribute: NSLayoutAttribute.right, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.right, multiplier: 1, constant: -10)
let bottomConstraintChart = NSLayoutConstraint(item: self.chart, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: self, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: -10)
NSLayoutConstraint.activate([upperConstraintChart,leftConstraintChart,rightConstraintChart,bottomConstraintChart])
self.setupDataForChart()
}
func setupDataForChart(){
var set1: BarChartDataSet! = nil
var values:[BarChartDataEntry] = []
for i in 10..<30 {
// Specify date components
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy"
let someDateTime = formatter.date(from: "\(i)/10/2016")
print("anuran x value \(someDateTime!.timeIntervalSince1970)")
values.append(BarChartDataEntry(x: someDateTime!.timeIntervalSince1970, y: Double(20)))
}
set1 = BarChartDataSet(values: values, label: "")
var colors:[UIColor] = []
for i in 0..<values.count {
var color = UIColor(netHex: "FFC300")
if i == values.count - 1 {
color = UIColor.cyan
}
colors.append(color)
}
set1.colors = colors
//set1.drawValuesEnabled = true
let data = BarChartData(dataSet: set1)
data.setValueFont(UIFont(name: "HelveticaNeue-Light", size: 10)!)
data.barWidth = 0.9
self.chart.legend.setCustom(entries: [LegendEntry(label: "Earlier", form: Legend.Form.circle, formSize: CGFloat.nan, formLineWidth: CGFloat.nan, formLineDashPhase: 10, formLineDashLengths: [CGFloat.nan], formColor: UIColor(netHex: "FFC300")),
LegendEntry(label: "Today", form: Legend.Form.circle, formSize: CGFloat.nan, formLineWidth: CGFloat.nan, formLineDashPhase: 10, formLineDashLengths: [CGFloat.nan], formColor: UIColor.cyan)])
self.chart.data = data
self.chart.setVisibleXRangeMaximum(5)
}
the result I am getting is like the following:
it scrolls for indefinite amount, I do not know when 11/10/2016 will come. What's wrong with this?
回答1:
Turns out you can not set any value to the X value of the BarChartDataEntry
. So what you should do is put index 0 to length of the array you are using to hold your model and inside your IAxisValueFormatter
subclass hold the timestamp values. so when you override stringForValue
get the timestamp from the stored property. So your subclass should look like this:
import Foundation
import Charts
public class DateValueFormatter: NSObject, IAxisValueFormatter {
private let dateFormatter = DateFormatter()
var values:[TimeInterval]!
override init() {
super.init()
dateFormatter.dateFormat = "dd/MM/yy"
}
public func stringForValue(_ value: Double, axis: AxisBase?) -> String {
return dateFormatter.string(from: Date(timeIntervalSince1970: self.values![Int(value)]))
}
}
So bottom line is you should maintain one extra array to hold the timestamp value and put normal for loop index
as the X value of the BarChartDataEntry
来源:https://stackoverflow.com/questions/57326384/ios-charts-x-axis-values-are-repeating-indefinitely-when-setvisiblexrangemaximum