【Swift UI】Swift Chartsでラベルをカスタマイズする方法!chartXAxis/chartYAxis/AxisMarks
この記事からわかること
- Swift UIで使えるSwift Chartsフレームワークの使い方
- グラフの実装方法
- ラベルをカスタマイズするには?
- AxisMarks構造体の使い方
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
環境
- Xcode:15.0.1
- iOS:17.1
- Swift:5.9
- macOS:Sonoma 14.1
Swift UIでグラフを実装するためのフレームワークがiOS16から公式より提供されるようになったので実装方法や使い方についてまとめていきたいと思います。
Swift Chartsフレームワークとは?
「Swift Charts」はSwift UIで使用できるフレームワークでグラフを簡単に作成、カスタマイズすることが可能です。Apple公式から提供されているので導入作業などは必要なく、import Charts
と記述することで使用できるようになります。
詳細な実装方法などは以下の記事を参考にしてください。
Swift Chartsのラベル
Swift Chartsのラベルは基本的にグラフを実装する際の引数x
とy
に渡した値が自動で反映されます。
Chart {
ForEach(list) { subject in
BarMark(
x: .value("教科名", subject.name),
y: .value("点数", subject.score)
).foregroundStyle(subject.color)
}
}
X軸のラベルをカスタマイズする方法
X軸のラベルは値に応じて自動的に良い感じに配置してくれます。Date
型を渡すと自動でX軸を時間軸にしてくれますが以下のように自動で間引きされるせいで期待通りに表示させられない場合もあります。
struct Record: Identifiable {
var id: UUID = UUID()
let date: Date
let score: Int
}
struct ContentView: View {
var records: [Record] = [
Record(date: DateComponents(calendar: .current, year: 2024, month: 2, day: 1).date!, score: 10),
Record(date: DateComponents(calendar: .current, year: 2024, month: 2, day: 2).date!, score: 30),
Record(date: DateComponents(calendar: .current, year: 2024, month: 2, day: 3).date!, score: 80),
Record(date: DateComponents(calendar: .current, year: 2024, month: 2, day: 4).date!, score: 50),
Record(date: DateComponents(calendar: .current, year: 2024, month: 2, day: 5).date!, score: 14),
Record(date: DateComponents(calendar: .current, year: 2024, month: 2, day: 6).date!, score: 20),
Record(date: DateComponents(calendar: .current, year: 2024, month: 2, day: 7).date!, score: 35),
Record(date: DateComponents(calendar: .current, year: 2024, month: 2, day: 8).date!, score: 70),
Record(date: DateComponents(calendar: .current, year: 2024, month: 2, day: 9).date!, score: 90)
]
var body: some View {
Chart(records) { record in
BarMark(
x: .value("年月日", record.date),
y: .value("点数", record.score)
).foregroundStyle(.gray)
}.padding()
}
}
このX軸のラベル周りを調整できるのがchartXAxis
モディファイアとAxisMarks
構造体です。
chartXAxisモディファイア
func chartXAxis(Visibility) -> some View
func chartXAxis<Content>(@AxisContentBuilder content: () -> Content) -> some View where Content : AxisContent
chartXAxis
はグラフのX軸を構成するためのモディファイアです。引数違いで2種類用意されており、Visibility
の方は単に表示/非表示を切り替える役割を持っています。
.chartXAxis(.hidden) // X軸ラベル非表示
2つ目の方はAxisMarks
構造体を引数に渡すことでX軸の構成要素を自由にカスタマイズすることができます。初期値はAxisMarks(values: .automatic)
になっており、明示的に以下を指定してもデフォルトの表示と変化はありません。
.chartXAxis {
AxisMarks(values: .automatic)
}
AxisMarksでカスタマイズする方法
AxisMarks
の中に要素を追加することで表示するグラフのUIやラベル数などをコントロールすることができるようになります。AxisMarks
構造体の中には表示させたいコンテンツを渡していきます。
.chartXAxis {
// stride:ラベルの表示間隔
AxisMarks(values: .stride(by: .day)) {
// グリッドライン
AxisGridLine()
// 目盛り
AxisTick()
// ラベルの値
AxisValueLabel(format: .dateTime.year().month().day())
}
}
ラベルの表示間隔を調整する
データのラベルを間引きせずに全て表示させたい場合はAxisMarks
の引数Values
にAxisMarkValues.stride
を渡します。引数by
には表示させたい年月日をday()
やmonth()
などで指定します。day()
を指定すれば1日ごとに表示されるようになります。
AxisMarks(values: .stride(by: .day)) { // コンテンツ }
static func stride(
by component: Calendar.Component,
count: Int = 1,
roundLowerBound: Bool? = nil,
roundUpperBound: Bool? = nil,
calendar: Calendar? = nil
) -> AxisMarkValues
2日おきに表示させたい場合はcount
に2
を渡します。
AxisMarks(values: .stride(by: .day, count: 2)) { // コンテンツ }
ラベルの日付を調整する
ラベルに表示させる日付情報はAxisValueLabel(format:)
にdateTime
を指定することで調整することができます。年月日を表示させたければyear().month().day()
のように続けて指定すればOKです。
AxisValueLabel(format: .dateTime.year().month().day())
デフォルトだとFeb 1, 2024
と表示されましたが、defaultDigits
などを指定することで2024/02/01
というように表示を変更させることができます。
AxisValueLabel(format: .dateTime.year().month(.defaultDigits).day())
ラベルの表示位置を上に設定する
X軸のラベルはデフォルトではbottom
に配置されていますが、上配置に変更したい場合は引数position
にtop
を渡します。
.chartXAxis {
AxisMarks(position: .top)
}
X軸のラベルカテゴリ名を指定する
X軸のラベルの大元カテゴリ名を指定するにはchartXAxisLabel
モディファイアを使用します。
.chartXAxisLabel("年月日", position: .bottom, alignment: .top, spacing: 10)
また以下のようにViewを指定することも可能です。
.chartXAxisLabel(position: .bottom, alignment: .top, spacing: 10) {
Text("年月日")
.foregroundStyle(.brown)
}
Y軸のラベルをカスタマイズする方法
Y軸ラベルのカスタマイズ方法も基本的にはX軸と同じです。Y軸用のchartYAxis
モディファイアが用意されているのでそれを使用してカスタマイズしていきます。非表示にする方法も変わりません。
.chartYAxis(.hidden) // Y軸ラベル非表示
ラベルの最小値/最大値を指定する
ラベルの最小値/最大値を指定するにはchartYScale(domain:)
を使用します。これはChart
から呼び出すので注意してください。例えば最小を0最大を120にしたい場合は以下のようになります。
.chartYScale(domain: 0...120)
ラベルの表示位置を左に設定する
Y軸のラベルはデフォルトではtrailing
に配置されていますが、左配置に変更したい場合は引数position
にleading
を渡します。
.chartYAxis {
AxisMarks(position: .leading)
}
Y軸のラベルカテゴリ名を指定する
Y軸のラベルの大元カテゴリ名を指定するにはchartYAxisLabel
モディファイアを使用します。
.chartYAxisLabel("点数", position: .trailing, alignment: .center, spacing: 10)
X軸同様にViewを渡すことが可能です。
.chartYAxisLabel(position: .leading, alignment: .center, spacing: 10) {
Text("点数")
.foregroundStyle(.brown)
}
Y軸の値に単位をつける
Y軸に表示させている数値に単位をつけたい場合はAxisMarks
の引数からvalue
を受け取り以下のように実装することで自由にカスタマイズした文字ラベルを実装することができます。
.chartYAxis {
AxisMarks(position: .leading) { value in
AxisValueLabel {
if let intValue = value.as(Int.self) {
Text("\(intValue) 点")
}
}
}
}
ラベルやグリッド線の表示間隔を調整する
ラベルやグリッド線の表示間隔を調整するにはAxisMarks
の引数values
に明示的に値を渡すことで実装することができます。
.chartYAxis {
AxisMarks(position: .leading, values: [0, 20, 40, 60, 80, 100]) { value in
AxisGridLine()
AxisValueLabel {
if let intValue = value.as(Int.self) {
Text("\(intValue) 点")
}
}
}
}
またAxisMarks
を2つ実装することで異なる間隔でのコンテンツの設定を変更することもできます。
.chartYAxis {
AxisMarks(position: .leading, values: [0, 20, 40, 60, 80, 100]) { value in
AxisGridLine()
}
AxisMarks(position: .leading, values: [0, 50, 100]) { value in
AxisValueLabel {
if let intValue = value.as(Int.self) {
Text("\(intValue) 点")
}
}
}
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。