์ฐจํธ๋ฅผ ๋ฒ์ 2(Swift 2.3)์์ 3(Swift 3)์ผ๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๋ ๋ฐ ์ด๋ ค์์ ๊ฒช๊ณ ์์ต๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก x ๋ ์ด๋ธ(๋ ์ง)์ ํด๋น ํ๋กฏ๊ณผ ์ฌ๋ฐ๋ฅด๊ฒ ์ ๋ ฌํ ์ ์์ต๋๋ค.
์ด๊ฒ์ ๋ด๊ฐ ์ด์ ์ ๋ฒ์ 2์์ ๊ฐ์ง๊ณ ์๋ ๊ฒ์
๋๋ค:
https://i.stack.imgur.com/wOL3t.png
๋ฒ์ 2์์๋ 7, 8, 10 ๋ฐ 11์ผ์ ๋ํ ๊ฐ์ด ์์์ต๋๋ค. ๊ทธ๋์ ์ค๊ฐ์ ํ๋ฃจ๊ฐ ๋๋ฝ๋์์ง๋ง ๋ ์ด๋ธ์ด ํ๋กฏ๊ณผ ์ฌ๋ฐ๋ฅด๊ฒ ์ ๋ ฌ๋์์ต๋๋ค.
๋ค์์ ๋ฒ์ 3์ ์๋ ๋ด์ฉ์
๋๋ค.
https://i.stack.imgur.com/arIL2.png
๋ฒ์ 3์์ x ์ถ์ "๋ ์ด๋ธ"์ ์ด์ ์ด์ค์ผ๋ก ๋์ฒด๋์์ผ๋ฉฐ(๋ ์ง์ ๊ฒฝ์ฐ 1970๋ ์ดํ์ timeInterval์) ํฌ๋งทํฐ๋ฅผ ํตํด ํ์์ด ์ง์ ๋์์ต๋๋ค. ๋ฐ๋ผ์ ์ฐจํธ๊ฐ 9๋ฒ์งธ ๊ฐ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ธ์ฝํ๋ฏ๋ก ์ด์ ๊ทธ๋ํ๊ฐ ๋ "์ ํ"ํ์ง๋ง ํด๋น ํ๋กฏ ์๋์ ๋ ์ด๋ธ์ ๋ฐฐ์นํ๋ ๋ฐฉ๋ฒ์ ์ฐพ์ ์ ์์์ ๋ถ์ธํ ์ ์์ต๋๋ค.
์ด๊ฒ์ x ์ถ์ ๋ํ ๋ด ์ฝ๋์ ๋๋ค.
```
chartView = LineChartView() ํ์
...
xAxis = chartView.xAxis ํ์
xAxis.labelPosition = .bottom
xAxis.labelCount = ํญ๋ชฉ ์
xAxis.drawLabelsEnabled = true
xAxis.drawLimitLinesBehindDataEnabled = true
xAxis.avoidFirstLastClippingEnabled = true
// x ๊ฐ ๋ ์ง ํฌ๋งทํฐ ์ค์
let xValuesNumberFormatter = ChartXAxisFormatter()
xValuesNumberFormatter.dateFormatter = dayNumberAndShortNameFormatter // ์: "์ 26"
xAxis.valueFormatter = xValuesNumberFormatter
Here is the ChartXAxisFormatter class I created:
์์
์ฌ๋จ
์ฐจํธ ๊ฐ์ ธ์ค๊ธฐ
ํด๋์ค ChartXAxisFormatter: NSObject {
var dateFormatter: DateFormatter?
}
ํ์ฅ 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์ถ์์ ๋ ๋๋ง๋๋ ๊ฒ์ด ๋ณด๊ฐ๋ ํ์์คํฌํ์ด๊ธฐ ๋๋ฌธ์ ๋ฐ์ํฉ๋๋ค. ์ด๊ฒ์ ๊ธฐ๋ณธ์ ์ผ๋ก dateFormatter๋ฅผ ์ฌ์ฉํ์ฌ ๋ ์ด๋ธ์ ์์ฑํ๋ ํ์์คํฌํ๊ฐ _์ ์์ ๋ํ ํ์์คํฌํ๊ฐ ์๋๋ฏ๋ก_ ๋ ์ด๋ธ์ด ์ผ์นํ์ง ์์์ ์๋ฏธํฉ๋๋ค.
์๋ฅผ ๋ค์ด x ๊ฐ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]์ด ์๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. x-์ถ ๋ ๋๋ฌ๋ ํน์ x-๊ฐ์ด ๋ฐ์ดํฐ์ธํธ์์ _not_์ด๋๋ผ๋ x-์ถ์ ๋ ์ด๋ธ์ ๊ณ ๋ฅด๊ฒ ๋ฐฐํฌํ๋ ค๊ณ ํ๋ ๋ ์ด๋ธ๋ก ์ค์ ๋ก 2.5๋ฅผ ์ธ์ํ ์ ์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ํ์์คํฌํ๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค๊ณ ์๊ฐํ๋ฉด dateFormatter๊ฐ ์ผ๋ถ ์ค๊ฐ ํ์์คํฌํ๋ฅผ ๋ ์ง๋ก ํ์ํํ ์ ์์์ ์๋ฏธํฉ๋๋ค. ๋ ์ง๋ฅผ ๊ธฐ์ค์ผ๋ก ํ์์ ์ง์ ํ๋ฉด ๋ ์ด๋ธ์ด ์ ํํ๋๋ผ๋(๊ธฐ๋ณธ์ ์ผ๋ก ๋ ์ง๋ฅผ ๋ฐ์ฌ๋ฆผํ๋ฏ๋ก) ๋ ์ด๋ธ์ด ์ ์์ ์ผ์นํ์ง ์๊ฒ ๋ฉ๋๋ค. _day hour:minute_ ์ผ๋ก ํ์์ ์ง์ ํ๋ฉด ๋ ์ด๋ธ์ด ์ค์ ๋ก ๋ณด๊ฐ๋ ๋ ์ง
x์ถ์ ํ์์คํฌํ๋ฅผ ์ฌ์ฉํ๊ณ ์ฌ์ฉ์ ์ง์ X์ถ ํฌ๋งทํฐ๋ฅผ ์ฌ์ฉํ๋ ๋์ ๋ฐฐ์ด ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒฐ๊ตญ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ต๋๋ค.
import Foundation
import Charts
class MyCustomBottomAxisFormatter: NSObject, IAxisValueFormatter {
private var scores: [MyScoreObject]?
lazy private var dateFormatter: DateFormatter = {
// set up date formatter using locale
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale.current
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .none
return dateFormatter
}()
convenience init(usingScores scores: [MyScoreObject]) {
self.init()
self.scores = scores
}
func stringForValue(_ value: Double, axis: AxisBase?) -> String {
let index = Int(value)
guard let scores = scores, index < scores.count, let date = scores[index].date else {
return "?"
}
return dateFormatter.string(from: date)
}
}
๋ต๋ณ ๊ฐ์ฌํฉ๋๋ค!
๊ทธ๋ฆฌ๊ณ ๋ณด๊ฐ๋๋ ํ์์คํฌํ์ ๋ํ ๋งค์ฐ ๋ช
ํํ ์ค๋ช
์ ์ ๋ง ์๋ฏธ๊ฐ ์์ต๋๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์๋ํด ๋ณด๊ณ ์๋ ค ๋๋ฆฌ๊ฒ ์ต๋๋ค.
๊ฐ์ฌ ํด์!
@4np ๊ทธ๋ฌ๋ฉด ์๊ฐ ๊ฐ๊ฒฉ ๋์ xValues๋ฅผ ์ธ๋ฑ์ค๋ก ์ฌ์ฉํ์ฌ ChartDataEntry ๋ฐฐ์ด์ ์ ์ํด์ผ ํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋ง์ต๋๊น?
๊ทธ๋ ๊ฒ :
// Define chart yValues
var entries = [ChartDataEntry]()
for (index, score) in scores.enumerated() {
let yValue = score.value
let entry = ChartDataEntry(x: Double(index), y: yValue)
entries.append(entry)
}
@4np ์๊ฒ ์ต๋๋ค. ์ฑ๊ณต ํ์ต๋๋ค! ๋ด ์ฐจํธ๋ ์ด์ ๋ฒ์ 2์ ๋์ผํฉ๋๋ค.
ํ์ง๋ง xAxis์ 2๊ฐ์ง๋ฅผ ๋ ์ถ๊ฐํด์ผ ํ์ต๋๋ค.
// Show the limit lines behind each plot
xAxis.drawLimitLinesBehindDataEnabled = true
// Make sure that only 1 x-label per index is shown
xAxis.granularityEnabled = true
xAxis.granularity = 1
๋น์ ์ ๋์์ ์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค.
๋ํ StackOverflow์์ ๋ฌธ์ ๋ฅผ ์ด์์ต๋๋ค.
http://stackoverflow.com/questions/41720445/ios-charts-3-0-align-x-labels-dates-with-plots
SO ๊ณ์ ์ด ์๊ณ ๊ฑฐ๊ธฐ์ ๋ต์ ๋ณต์ฌ/๋ถ์ฌ๋ฃ๊ธฐ ํ๋ ค๋ ๊ฒฝ์ฐ์๋ ๊ฑฐ๊ธฐ์์ ๊ทํ์ ๋ต๋ณ์ ์๋ฝํ๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค.
๊ฐ์ฌ ํด์
ํ๋ ๋
๋ํ Charts ๊ฐ๋ฐ์๊ฐ ๋ณผ ๊ธฐํ๊ฐ ์์ ๋๊น์ง ์ด ๋ฌธ์ ๋ฅผ ์ด์ด๋๊ณ ๋ ์ด๋ธ์ ์ ๋ ฌํ๋ ๋ฐฉ๋ฒ์ ์ ํํ๋ ๋ฐฉ๋ฒ์ ์๊ฐํ ์ ์์ต๋๋ค.
์ด์ 2๊ฐ์ ์ข์ง ์์ ์๋ฃจ์ ์ค์์ ์ ํํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ด๋ป๊ฒ ์๊ฐํ๋์ง ์๋ ค์ฃผ์ธ์.
@frederic-adda
๋๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ์ฑ๊ณตํ๋ค
XAxis.granularity = 1.0์ 1์ผ์ด์ด์ผ ํฉ๋๋ค. ๊ทธ๊ฒ์ด ๊ฐ์ฅ ์ค์ํ๋ค
๊ฐ์ฅ ์์ ๋ ์ง๋ 0์ด์ด์ผ ํฉ๋๋ค.
(TimeInSeconds - miniDate) / (3600.0 * 24.0)
๊ทธ๋ฆฌ๊ณ ๋ชจ๋ ํธ๋ฆญ์ ํฌ๋งทํฐ์ ์์ต๋๋ค
๋ ์ง๋ฅผ ๊ฒ์ํ๊ธฐ ์ํด ๋ฐ๋ ์์
์ ์ํํฉ๋๋ค.
date2 = ๋ ์ง(timeIntervalSince1970: (๊ฐ * 3600 * 24) + miniTime)๋ผ๊ณ ํฉ์๋ค.
dateFormatter.string ๋ฐํ(from: date2)
์์ง ๋ง์
DateFormatter.timeZone = NSTimeZone(์ฝ์ด: "GMT + 0:00")์ TimeZone์ผ๋ก!
๋ฐ๋ชจ๋ macOS์
๋๋ค.
๋งํฌ๋ https://github.com/thierryH91200/Charts-log์
๋๋ค.
๋ผ์ธ ๋ ์ง ํญ
@hierryH91200 ํฐ์๋ฆฌ ๊ฐ์ฌํฉ๋๋ค!
๊ทํ์ ์๋ฃจ์
์ ์ฆ์ ๊ตฌํํ๋๋ก ๋
ธ๋ ฅํ๊ฒ ์ต๋๋ค.
ํจ๊ณผ๊ฐ ์์๋ค! ํ์์ ์ด์ผ!
๋น์ ์ ๋์์ ์ฃผ์
์ ๊ฐ์ฌํฉ๋๋ค!
๋ฉ์ ธ์ @thierryH91200 ์ ๋ง ์์ผ๋ก ๋์๊ฐ์ผ ํ ๊ธธ์ด ๋ณด์ด๋ค์ ๐
์ด๊ฒ์ ๋๋ฅผ ์ํด ์๋ํ์ง ์์ต๋๋ค
@frederic-adda ๋ฌธ์ ์ ๋ํ ํด๊ฒฐ์ฑ
์ ์ฐพ์์ต๋๊น?
์ค์ ๋ก X์ถ์ ๋ ์ง๋ฅผ ํ์ํ ๋ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ChartDataEntry์ X ๊ฐ์ TimeInterval๋ก ์ค์ ํ์ฌ X์ถ์ ๋ ์ง๋ฅผ ํ์ํ๊ณ ์๋๋ฐ ์ฐจํธ์ ๋ฐ์ดํฐ๊ฐ ์ ๋๋ก ํ์๋์ง ์์ต๋๋ค. ChartDataEntry์ X ๊ฐ์ ๋ฐฐ์ด ์ธ๋ฑ์ค๋ก ์ค์ ํ๋ฉด ๋ฐ์ดํฐ๊ฐ ํ์๋ฉ๋๋ค.
๋ค์์ ChartDataEntry์ X ๊ฐ์ TimeInterval๋ก ์ค์ ํ๋ ์ฝ๋์
๋๋ค.
for (int i = 0; i < self.temperatureUpdates.count; i++)
{
SFTemperatureUpdate * temperatureUpdate = [self.temperatureUpdates ๊ฐ์ฒด ctAtIndex:i ];
์ด์ค yVal = [์จ๋ ์
๋ฐ์ดํธ ๊ฐ floatValue];
NSTimeInterval timeInterval = [temperatureUpdate.careatedAt timeIntervalSince1970];
๋๋ธ xVal = timeInterval;
[yVals1 addObject:[[ChartDataEntry ํ ๋น] initWithX:xVal y:yVal]];
}
ํ๋์ ๊ทธ๋ํ์์ ์ฌ๋ฌ LineChartDataSets๋ฅผ ์ฌ์ฉํ ๋ ์์ ์๋ฃจ์ ์ ์๋์ํค๋ ค๊ณ ํ ๋ ์ฑ๊ณต์ ์ผ๋ก ์๋ํ๊ฒ ํ ์ฌ๋์ด ์์ต๋๊น?
ํ๋์ ๋ฐ์ดํฐ ์ธํธ๊ฐ ๋ค๋ฅธ ๋ฐ์ดํฐ ์ธํธ์ ํฌ๊ธฐ๊ฐ ๋ค๋ฅผ ๋ ์๋ฃจ์
์ ์ฐพ๋ ๋ฐ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
์ฆ
let x = LineChartDataSet(values: values1, label: "test 1") // count 5
let y = LineChartDataSet(values: values2, label: "test 2") // count 8
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
์ด์ ์ ํ์์คํฌํ๋ฅผ ์ฌ์ฉํ์ฌ ๋์ผํ ๋ฌธ์ ์์ ์คํํ๋๋ฐ x์ถ์์ ๋ ๋๋ง๋๋ ๊ฒ์ด ๋ณด๊ฐ๋ ํ์์คํฌํ์ด๊ธฐ ๋๋ฌธ์ ๋ฐ์ํฉ๋๋ค. ์ด๊ฒ์ ๊ธฐ๋ณธ์ ์ผ๋ก dateFormatter๋ฅผ ์ฌ์ฉํ์ฌ ๋ ์ด๋ธ์ ์์ฑํ๋ ํ์์คํฌํ๊ฐ _์ ์์ ๋ํ ํ์์คํฌํ๊ฐ ์๋๋ฏ๋ก_ ๋ ์ด๋ธ์ด ์ผ์นํ์ง ์์์ ์๋ฏธํฉ๋๋ค.
์๋ฅผ ๋ค์ด x ๊ฐ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]์ด ์๋ค๊ณ ๊ฐ์ ํด ๋ณด๊ฒ ์ต๋๋ค. x-์ถ ๋ ๋๋ฌ๋ ํน์ x-๊ฐ์ด ๋ฐ์ดํฐ์ธํธ์์ _not_์ด๋๋ผ๋ x-์ถ์ ๋ ์ด๋ธ์ ๊ณ ๋ฅด๊ฒ ๋ฐฐํฌํ๋ ค๊ณ ํ๋ ๋ ์ด๋ธ๋ก ์ค์ ๋ก 2.5๋ฅผ ์ธ์ํ ์ ์์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ํ์์คํฌํ๋ฅผ ์ฌ์ฉํ๊ณ ์๋ค๊ณ ์๊ฐํ๋ฉด dateFormatter๊ฐ ์ผ๋ถ ์ค๊ฐ ํ์์คํฌํ๋ฅผ ๋ ์ง๋ก ํ์ํํ ์ ์์์ ์๋ฏธํฉ๋๋ค. ๋ ์ง๋ฅผ ๊ธฐ์ค์ผ๋ก ํ์์ ์ง์ ํ๋ฉด ๋ ์ด๋ธ์ด ์ ํํ๋๋ผ๋(๊ธฐ๋ณธ์ ์ผ๋ก ๋ ์ง๋ฅผ ๋ฐ์ฌ๋ฆผํ๋ฏ๋ก) ๋ ์ด๋ธ์ด ์ ์์ ์ผ์นํ์ง ์๊ฒ ๋ฉ๋๋ค. _day hour:minute_ ์ผ๋ก ํ์์ ์ง์ ํ๋ฉด ๋ ์ด๋ธ์ด ์ค์ ๋ก ๋ณด๊ฐ๋ ๋ ์ง
x์ถ์ ํ์์คํฌํ๋ฅผ ์ฌ์ฉํ๊ณ ์ฌ์ฉ์ ์ง์ X์ถ ํฌ๋งทํฐ๋ฅผ ์ฌ์ฉํ๋ ๋์ ๋ฐฐ์ด ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒฐ๊ตญ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ต๋๋ค.