ios Charts 3.0 - 将x标签(日期)与图

时间:2017-01-18 13:15:27

标签: swift ios-charts

我很难将库图表(来自Daniel Gindi)从版本2(Swift 2.3)迁移到3(Swift 3)。

基本上,我不能将x标签(日期)与相应的图正确对齐。

这是我之前在第2版中所拥有的:

在版本2中,我有第7天,第8天,第10天和第11天的值。 所以我错过了中间的一天,但标签正确地与情节一致。 Charts 2

以下是版本3中的内容:

在版本3中,"标签"在x轴上现在已被替换为double(对于日期,它自1970年以来是timeInterval),并通过格式化程序格式化。 因此,无可否认,图表更加正确"现在,因为图表正确地推断了第9个的值,但是我无法找到如何将标签放在相应的图表下面。 Charts 3

这是我的x轴代码:

 let chartView = LineChartView()
 ...
 let xAxis = chartView.xAxis
 xAxis.labelPosition = .bottom
 xAxis.labelCount = entries.count
 xAxis.drawLabelsEnabled = true
 xAxis.drawLimitLinesBehindDataEnabled = true
 xAxis.avoidFirstLastClippingEnabled = true

 // Set the x values date formatter
 let xValuesNumberFormatter = ChartXAxisFormatter()
 xValuesNumberFormatter.dateFormatter = dayNumberAndShortNameFormatter // e.g. "wed 26"
 xAxis.valueFormatter = xValuesNumberFormatter

这是我创建的ChartXAxisFormatter类:

import Foundation
import Charts

class ChartXAxisFormatter: NSObject {
    var dateFormatter: DateFormatter?
}

extension ChartXAxisFormatter: IAxisValueFormatter {

    func stringForValue(_ value: Double, axis: AxisBase?) -> String {
        if let dateFormatter = dateFormatter {

            let date = Date(timeIntervalSince1970: value)
            return dateFormatter.string(from: date)
        }

        return ""
    }

}

因此,这里的值是正确的,格式是正确的,图表的形状是正确的,但标签与相应图的对齐并不好。 谢谢你的帮助

4 个答案:

答案 0 :(得分:14)

好的,明白了!

您必须定义参考时间间隔(" 0"表示x轴)。然后计算每个x值的附加时间间隔。

ChartXAxisFormatter变为:

import Foundation
import Charts

class ChartXAxisFormatter: NSObject {
    fileprivate var dateFormatter: DateFormatter?
    fileprivate var referenceTimeInterval: TimeInterval?

    convenience init(referenceTimeInterval: TimeInterval, dateFormatter: DateFormatter) {
        self.init()
        self.referenceTimeInterval = referenceTimeInterval
        self.dateFormatter = dateFormatter
    }
}


extension ChartXAxisFormatter: IAxisValueFormatter {

    func stringForValue(_ value: Double, axis: AxisBase?) -> String {
        guard let dateFormatter = dateFormatter,
        let referenceTimeInterval = referenceTimeInterval
        else {
            return ""
        }

        let date = Date(timeIntervalSince1970: value * 3600 * 24 + referenceTimeInterval)
        return dateFormatter.string(from: date)
    }

}

然后,当我创建数据条目时,它的工作原理如下:

// (objects is defined as an array of struct with date and value)

// Define the reference time interval
var referenceTimeInterval: TimeInterval = 0
if let minTimeInterval = (objects.map { $0.date.timeIntervalSince1970 }).min() {
        referenceTimeInterval = minTimeInterval
    }


    // Define chart xValues formatter
    let formatter = DateFormatter()
    formatter.dateStyle = .short
    formatter.timeStyle = .none
    formatter.locale = Locale.current

    let xValuesNumberFormatter = ChartXAxisFormatter(referenceTimeInterval: referenceTimeInterval, dateFormatter: xValuesFormatter)



    // Define chart entries
    var entries = [ChartDataEntry]()
    for object in objects {
        let timeInterval = object.date.timeIntervalSince1970
        let xValue = (timeInterval - referenceTimeInterval) / (3600 * 24)

        let yValue = object.value
        let entry = ChartDataEntry(x: xValue, y: yValue)
        entries.append(entry)
    }

// Pass these entries and the formatter to the Chart ...

结果更好(我顺便删除了立方体): enter image description here

答案 1 :(得分:2)

如果您确切知道x轴需要多少标签,可以编写此代码来解决它。例如,如果我需要在x轴上出现七个标签,那么这应该就够了。原因是图表库没有正确计算两个x轴点之间的间隔,因此绘图标签不匹配。当我们强制库对照给定数量的标签进行绘图时,问题似乎已经消失。

 let xAxis = chart.xAxis
 xAxis.centerAxisLabelsEnabled = false
 xAxis.setLabelCount(7, force: true) //enter the number of labels here

答案 2 :(得分:0)

这是xValuesNumberFormatter的解决方案

let xValuesFormatter = DateFormatter()
    xValuesFormatter.dateFormat = "MM/dd"
let xValuesNumberFormatter = ChartXAxisFormatter(referenceTimeInterval: referenceTimeInterval, dateFormatter: xValuesFormatter)
    xValuesNumberFormatter.dateFormatter = xValuesFormatter // e.g. "wed 26"
    xAxis.valueFormatter = xValuesNumberFormatter

答案 3 :(得分:0)

我使用此答案解决了这个问题 https://stackoverflow.com/a/44554613/2087608

我怀疑这些偏移量是由于我的情况将X轴值调整为一天中的特定时间

这是我的代码

for i in 0..<valuesViewModel.entries.count {
  let dataEntry = ChartDataEntry(x: roundDate(date: valuesViewModel.entries[i].date).timeIntervalSince1970, y: valuesViewModel.entries[i].value)
  dataEntries.append(dataEntry)
}



func roundDate(date: Date) -> Date {
  var comp: DateComponents = Calendar.current.dateComponents([.year, .month, .day], from: date)
  comp.timeZone = TimeZone(abbreviation: "UTC")!
  let truncated = Calendar.current.date(from: comp)!
  return truncated
}