ios 图表 3.0 - 将 x 标签(日期)与图表对齐
ios Charts 3.0 - Align x labels (dates) with plots
我很难将图表库(来自 Daniel Gindi)从版本 2 (Swift 2.3) 迁移到版本 3 (Swift 3)。
基本上,我无法将 x 标签(日期)与相应的图正确对齐。
这是我之前的版本2:
在版本 2 中,我有第 7、8、10 和 11 天的值。
所以我在中间错过了一天,但标签与地块正确对齐。
这是我在版本 3 中的内容:
在版本 3 中,x 轴中的 "labels" 现在已替换为双精度(对于日期,它是自 1970 年以来的 timeInterval),并通过格式化程序进行格式化。
所以,不可否认,图表现在更多 "correct",因为图表正确地推断了第 9 个值,但我找不到如何将标签放在相应的图下。
这是我的 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 class:
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 ""
}
}
所以,这里的值是正确的,格式是正确的,图表的形状是正确的,但是标签与相应图表的对齐不好。
感谢您的帮助
好的,知道了!
您必须定义参考时间间隔(x 轴的“0”)。然后计算每个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 { [=11=].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: formatter)
// 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 ...
结果好多了(顺便去掉了cubic):
如果你确切地知道你需要在x轴上有多少个标签,你可以写这个代码来解决it.For例子,如果我需要七个标签出现在x轴上,那么这应该是 enough.The 原因是图表库没有正确计算两个 x 轴点之间的间隔,因此绘图标签 mismatch.When 我们强制图表库根据给定数量的标签进行绘图,问题好像没了
let xAxis = chart.xAxis
xAxis.centerAxisLabelsEnabled = false
xAxis.setLabelCount(7, force: true) //enter the number of labels here
我用这个答案解决了这个问题
我怀疑这些偏移量来自将 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
}
@IBOutlet weak var tView:UIView!
@IBOutlet weak var lineChartView:LineChartView!{
didSet{
lineChartView.xAxis.labelPosition = .bottom
lineChartView.xAxis.granularityEnabled = true
lineChartView.xAxis.granularity = 1.0
let xAxis = lineChartView.xAxis
// xAxis.axisMinimum = 0.0
// xAxis.granularity = 1.0
// xaAxis.setLabelCount(6, force: true)
}
}
@IBOutlet weak var back: UIButton?
@IBAction func back(_ sender: Any) {
self.navigationController?.popViewController(animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
self.lineChartView.delegate = self
self.lineChartView.chartDescription?.textColor = UIColor.white
let months = ["Jan" , "Feb", "Mar"]
let dollars1 = [1453.0,2352,5431]
setChart(months, values: dollars1)
}
func setChart(_ dataPoints: [String], values: [Double]) {
var dataEntries: [ChartDataEntry] = []
for i in 0 ..< dataPoints.count {
dataEntries.append(ChartDataEntry(x: Double(i), y: values[i]))
}
let lineChartDataSet = LineChartDataSet(entries: dataEntries, label: nil)
lineChartDataSet.axisDependency = .left
lineChartDataSet.setColor(UIColor.black)
lineChartDataSet.setCircleColor(UIColor.black) // our circle will be dark red
lineChartDataSet.lineWidth = 1.0
lineChartDataSet.circleRadius = 3.0 // the radius of the node circle
lineChartDataSet.fillAlpha = 1
lineChartDataSet.fillColor = UIColor.black
lineChartDataSet.highlightColor = UIColor.white
lineChartDataSet.drawCircleHoleEnabled = true
var dataSets = [LineChartDataSet]()
dataSets.append(lineChartDataSet)
let lineChartData = LineChartData(dataSets: dataSets)
lineChartView.data = lineChartData
lineChartView.rightAxis.enabled = false
lineChartView.xAxis.drawGridLinesEnabled = false
lineChartView.xAxis.labelPosition = .bottom
lineChartView.xAxis.valueFormatter = IndexAxisValueFormatter(values: dataPoints)
}
func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
print(entry)
}
我很难将图表库(来自 Daniel Gindi)从版本 2 (Swift 2.3) 迁移到版本 3 (Swift 3)。
基本上,我无法将 x 标签(日期)与相应的图正确对齐。
这是我之前的版本2:
在版本 2 中,我有第 7、8、10 和 11 天的值。
所以我在中间错过了一天,但标签与地块正确对齐。
这是我在版本 3 中的内容:
在版本 3 中,x 轴中的 "labels" 现在已替换为双精度(对于日期,它是自 1970 年以来的 timeInterval),并通过格式化程序进行格式化。
所以,不可否认,图表现在更多 "correct",因为图表正确地推断了第 9 个值,但我找不到如何将标签放在相应的图下。
这是我的 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 class:
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 ""
}
}
所以,这里的值是正确的,格式是正确的,图表的形状是正确的,但是标签与相应图表的对齐不好。 感谢您的帮助
好的,知道了!
您必须定义参考时间间隔(x 轴的“0”)。然后计算每个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 { [=11=].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: formatter)
// 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 ...
结果好多了(顺便去掉了cubic):
如果你确切地知道你需要在x轴上有多少个标签,你可以写这个代码来解决it.For例子,如果我需要七个标签出现在x轴上,那么这应该是 enough.The 原因是图表库没有正确计算两个 x 轴点之间的间隔,因此绘图标签 mismatch.When 我们强制图表库根据给定数量的标签进行绘图,问题好像没了
let xAxis = chart.xAxis
xAxis.centerAxisLabelsEnabled = false
xAxis.setLabelCount(7, force: true) //enter the number of labels here
我用这个答案解决了这个问题
我怀疑这些偏移量来自将 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
}
@IBOutlet weak var tView:UIView!
@IBOutlet weak var lineChartView:LineChartView!{
didSet{
lineChartView.xAxis.labelPosition = .bottom
lineChartView.xAxis.granularityEnabled = true
lineChartView.xAxis.granularity = 1.0
let xAxis = lineChartView.xAxis
// xAxis.axisMinimum = 0.0
// xAxis.granularity = 1.0
// xaAxis.setLabelCount(6, force: true)
}
}
@IBOutlet weak var back: UIButton?
@IBAction func back(_ sender: Any) {
self.navigationController?.popViewController(animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
self.lineChartView.delegate = self
self.lineChartView.chartDescription?.textColor = UIColor.white
let months = ["Jan" , "Feb", "Mar"]
let dollars1 = [1453.0,2352,5431]
setChart(months, values: dollars1)
}
func setChart(_ dataPoints: [String], values: [Double]) {
var dataEntries: [ChartDataEntry] = []
for i in 0 ..< dataPoints.count {
dataEntries.append(ChartDataEntry(x: Double(i), y: values[i]))
}
let lineChartDataSet = LineChartDataSet(entries: dataEntries, label: nil)
lineChartDataSet.axisDependency = .left
lineChartDataSet.setColor(UIColor.black)
lineChartDataSet.setCircleColor(UIColor.black) // our circle will be dark red
lineChartDataSet.lineWidth = 1.0
lineChartDataSet.circleRadius = 3.0 // the radius of the node circle
lineChartDataSet.fillAlpha = 1
lineChartDataSet.fillColor = UIColor.black
lineChartDataSet.highlightColor = UIColor.white
lineChartDataSet.drawCircleHoleEnabled = true
var dataSets = [LineChartDataSet]()
dataSets.append(lineChartDataSet)
let lineChartData = LineChartData(dataSets: dataSets)
lineChartView.data = lineChartData
lineChartView.rightAxis.enabled = false
lineChartView.xAxis.drawGridLinesEnabled = false
lineChartView.xAxis.labelPosition = .bottom
lineChartView.xAxis.valueFormatter = IndexAxisValueFormatter(values: dataPoints)
}
func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
print(entry)
}