ios - graphs - swift charts animation
¿Cómo agregar cadenas en el eje X en los gráficos de iOS? (4)
Como mucha gente dijo, puede crear una clase o extenderse con el tipo IAxisValueFormatter, pero puede usar fácilmente el siguiente método que solo toma 3 líneas:
self.chartView.xAxis.valueFormatter = DefaultAxisValueFormatter(block: {(index, _) in
return xStrings[Int(index)]
})
Aquí está mi función setChart () en caso de que algunos de ustedes encuentren interesante algunas de mis personalizaciones:
func setChartView(entriesData: [entry]) {
var chartEntries: [ChartDataEntry] = []
var xStrings: [String] = []
let sortedentriesData = entriesData.sorted { (s1: entry, s2: entry) -> Bool in
return s1.timestamp < s2.timestamp
}
for (i, entry) in sortedentriesData.enumerated() {
let newEntry = ChartDataEntry(x: Double(i), y: entry.temperature)
chartEntries.append(newEntry)
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = .medium
dateFormatter.dateStyle = .none
xStrings.append("/(dateFormatter.string(from: Date.init(timeIntervalSince1970: TimeInterval(entry.timestamp))))")
}
let set: LineChartDataSet = LineChartDataSet(values: chartEntries, label: "°C")
set.setColor(NSUIColor.blue, alpha: CGFloat(1))
set.circleColors = [NSUIColor.blue]
set.circleRadius = 3
set.mode = LineChartDataSet.Mode.cubicBezier
let data: LineChartData = LineChartData(dataSet: set)
self.chartView.xAxis.labelRotationAngle = -90
self.chartView.xAxis.valueFormatter = DefaultAxisValueFormatter(block: {(index, _) in
return xStrings[Int(index)]
})
self.chartView.xAxis.setLabelCount(xStrings.count, force: true)
self.chartView.data = data
}
La entrada es una estructura que he creado:
struct entry {
var timestamp: Int
var temperature: Double
}
Con la nueva versión tuve algunos problemas para crear algunos gráficos, el código anterior era:
func setChart(dataPoints: [String], values: [Double]) {
var dataEntries: [BarChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = BarChartDataEntry(value: values[i], xIndex: i)
dataEntries.append(dataEntry)
}
let chartDataSet = BarChartDataSet(yVals: dataEntries, label: "Units Sold")
let chartData = BarChartData(xVals: months, dataSet: chartDataSet)
barChartView.data = chartData
}
Puede pasar los valores, por ejemplo, una matriz de meses usando la línea:
let chartData = BarChartData(xVals: months, dataSet: chartDataSet)
Después de la nueva versión, el código para implementar el mismo gráfico es:
func setChart(dataPoints: [String], values: [Double]) {
var dataEntries: [BarChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = BarChartDataEntry(x: Double(i+2), y:values[i], data: months )
dataEntries.append(dataEntry)
}
let chartDataSet = BarChartDataSet(values: dataEntries, label: "Units Sold")
let chartData = BarChartData()
chartData.addDataSet(chartDataSet)
barChartView.data = chartData
}
Intenté algunas horas, pero no pude encontrar una manera de modificar los valores del eje X, espero que alguien pueda ayudarme, ¡gracias!
Encontré la solución, tal vez otro pueda resolver este problema de una mejor manera, sin crear una nueva clase, bueno, esto es lo que encontré:
Primero necesita crear una nueva clase, que será su clase de formateador y agregará la interfaz IAxisValueFormater, luego use el método stringForValue para personalizar los nuevos valores, se necesitan dos parámetros, el primero es el valor real (se puede ver como el índice) y segundo es el eje donde está el valor.
import UIKit
import Foundation
import Charts
@objc(BarChartFormatter)
public class BarChartFormatter: NSObject, IAxisValueFormatter
{
var months: [String]! = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
public func stringForValue(value: Double, axis: AxisBase?) -> String
{
return months[Int(value)]
}
}
Ahora, en el archivo al comienzo de su función setChart (), debe crear dos variables, una para su clase de formateador y otra para la clase de eje:
let formato:BarChartFormatter = BarChartFormatter()
let xaxis:XAxis = XAxis()
A continuación, continúe al final del bucle for in y pase el índice y el eje a su variable de formateador:
formato.stringForValue(Double(i), axis: xaxis)
Después del bucle, agregue el formato a su variable de eje:
xaxis.valueFormatter = formato
El último paso es agregar el nuevo xaxisformatted a barChartView:
barChartView.xAxis.valueFormatter = xaxis.valueFormatter
Y esas son todas las otras líneas en la función setChart (), simplemente manténgalas donde están, espero que puedan ayudarlo.
Hola, recientemente encontré el mismo problema y lo resolví de esta manera.
class ViewController: UIViewController {
var months: [String]!
var unitsSold = [Double]()
weak var axisFormatDelegate: IAxisValueFormatter?
@IBOutlet var viewForChart: BarChartView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
axisFormatDelegate = self
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
unitsSold = [20.0, 4.0, 6.0, 3.0, 12.0, 16.0, 4.0, 18.0, 2.0, 4.0, 5.0, 4.0]
// setChart(_ dataPoints:months,_ forY: unitsSold)
setChart(dataEntryX: months, dataEntryY: unitsSold)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setChart(dataEntryX forX:[String],dataEntryY forY: [Double]) {
viewForChart.noDataText = "You need to provide data for the chart."
var dataEntries:[BarChartDataEntry] = []
for i in 0..<forX.count{
// print(forX[i])
// let dataEntry = BarChartDataEntry(x: (forX[i] as NSString).doubleValue, y: Double(unitsSold[i]))
let dataEntry = BarChartDataEntry(x: Double(i), y: Double(forY[i]) , data: months as AnyObject?)
print(dataEntry)
dataEntries.append(dataEntry)
}
let chartDataSet = BarChartDataSet(values: dataEntries, label: "Units Sold")
let chartData = BarChartData(dataSet: chartDataSet)
viewForChart.data = chartData
let xAxisValue = viewForChart.xAxis
xAxisValue.valueFormatter = axisFormatDelegate
}
}
Al final simplemente agrega la extensión para el delegado.
extension ViewController: IAxisValueFormatter {
func stringForValue(_ value: Double, axis: AxisBase?) -> String {
return months[Int(value)]
}
}
Encontré esta solución a través de este enlace https://medium.com/@skoli/using-realm-and-charts-with-swift-3-in-ios-10-40c42e3838c0#.minfe6kuk
Una forma más clara de implementar la sugerencia anterior si está subclasificando un gráfico es implementar el protocolo IAxisValueFormatter en su propia subclase.
class CustomGraphView : LineChartView, ChartViewDelegate, IAxisValueFormatter {}
Me gusta esto...
public func stringForValue(_ value: Double, axis: Charts.AxisBase?) -> String
{
return "My X Axis Label Str"; // Return you label string, from an array perhaps.
}
Luego en tu init ()
self.xAxis.valueFormatter = self;