简体   繁体   English

iOS 图表的 x 轴上的重复值

[英]Repeating values on x-axis for iOS Charts

I'm using the iOS Charts and I'm getting a repeating labels on my x-axis.我正在使用iOS 图表并且我的 x 轴上有一个重复的标签。
在此处输入图片说明

I'm getting numerous answers ( first , second , third ) that I should set the granularity settings:我得到了很多答案(第一第二第三)我应该设置粒度设置:

xAxis.granularityEnabled = true
xAxis.granularity = 1.0

but, when I do the labels on the x-axis simply disappear.但是,当我做 x 轴上的标签时,标签就会消失。

在此处输入图片说明

My settings for the x-axis:我对 x 轴的设置:

let xAxis = lineChartView.xAxis
xAxis.labelPosition = .bottom
xAxis.labelFont = .boldSystemFont(ofSize: 12)
xAxis.setLabelCount(6, force: false)
xAxis.labelTextColor = UIColor(red: 0, green: 0, blue: 255/255, alpha: 1.0)
xAxis.axisLineColor = UIColor(white: 0.2, alpha: 0.4)
xAxis.gridColor = UIColor(white: 0.8, alpha: 0.4)
xAxis.valueFormatter = ChartXAxisFormatter()

I've created a custom class to format the values being passed to the x-axis on the advise of the documentation :我根据文档的建议创建了一个自定义类来格式化传递到 x 轴的值:

class ChartXAxisFormatter: IAxisValueFormatter {
    func stringForValue(_ value: Double, axis: AxisBase?) -> String {
        let dateFormatter = DateFormatter()
        dateFormatter.setLocalizedDateFormatFromTemplate("MM/dd")
        let date = Date(timeIntervalSince1970: value)
        return dateFormatter.string(from: date)
    }
}

Update更新

Thanks to @aiwiguna and with the help from the Charts repo , I was able to create a custom class that takes in two things: a date (Double) and a corresponding index (Int), instead of just the date.感谢 @aiwiguna 并在 Charts repo的帮助下,我能够创建一个自定义类,该类包含两件事:日期(Double)和相应的索引(Int),而不仅仅是日期。

class ChartXAxisFormatter: NSObject, IAxisValueFormatter {
    private var dates: [Double]?
    
    convenience init(usingDates dateArr: [Double]) {
        self.init()
        self.dates = dateArr
    }
    
    func stringForValue(_ value: Double, axis: AxisBase?) -> String {
        print("value: \(value)")
        print("dates: \(dates)")
        let index = Int(value)
    
        guard let dates = dates, index < dates.count else {
            return "?"
        }
        
        let date = dates[index]
        let dateFormatter = DateFormatter()
        dateFormatter.setLocalizedDateFormatFromTemplate("MM/dd")
        let formattedDate = Date(timeIntervalSince1970: date.rounded())
        return dateFormatter.string(from: formattedDate)
    }
}

The idea is to have an array of dates, [1598409060.0, 1598409060.0] , and returning them one by one by accessing it with an index.这个想法是有一个日期数组[1598409060.0, 1598409060.0] ,并通过使用索引访问它一个一个地返回它们。 Logging the value and index does show this to be the case.记录valueindex确实表明情况确实如此。

The problem is, while the number of repeating labels have been reduced to match the number of plots, the duplicates still remain:问题是,虽然减少了重复标签的数量以匹配绘图数量,但重复标签仍然存在:

在此处输入图片说明

There two plots should both be stacked on top of each other on one x-axis label "8/25".两个图都应该在一个 x 轴标签“8/25”上彼此堆叠。

I'm using enumerated() to extract the index for ChartDataEntry :我正在使用enumerated()来提取ChartDataEntry的索引:

var dateArr = [Double]()
for (index, fetchedMetric) in fetchedMetrics.enumerated() {
    let date = fetchedMetric.date.timeIntervalSince1970
    dateArr.append(date)
    if var yValues = metricDict[fetchedMetric.unit] {
        yValues.append(ChartDataEntry(x: Double(index), y: Double(truncating: fetchedMetric.value)))
        metricDict.updateValue(yValues, forKey: fetchedMetric.unit)
    } else {
        metricDict.updateValue([ChartDataEntry(x: Double(index), y: Double(truncating: fetchedMetric.value))], forKey: fetchedMetric.unit)
    }
}

it because when you set your chart setup (granurality = 1 and ChartXAxisFormatter) is showing each second in xAxis这是因为当您设置图表设置(粒度 = 1 和 ChartXAxisFormatter)时,每秒都在 xAxis 中显示

I prefer to use array date to show day in axis, with something like this我更喜欢使用数组日期在轴上显示日期,类似这样

public class DateValueFormatter: NSObject, IAxisValueFormatter {
    private let dateFormatter = DateFormatter()
    private let dates:[Date]
    
    init(dates: [Date]) {
        self.dates= dates
        super.init()
        dateFormatter.dateFormat = "dd MMM HH:mm"
    }
    
    public func stringForValue(_ value: Double, axis: AxisBase?) -> String {
        if value >= 0 && value < objects.count{
            let date = dates[Int(value)]
            return dateFormatter.string(from: date)
        }   
        return ""
    }
}

if you don't want to change your value formatted you can try to set granularity to 86400 (total seconds in 1 day)如果您不想更改格式化的值,可以尝试将粒度设置为 86400(1 天内的总秒数)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM