今年もAppleによる年一回の祭典「WWDC」が近づいてきました!
今回は、昨年度2022年のWWDCで発表された新機能、iOS16〜使える「Charts」フレームワークについてまとめていきます。
まだチャート機能を触ったことがない方は、この機会に一緒に触れてみましょう!
本記事のソースコード
[ 本記事はこんな人におすすめ ]
・2022年度にWWDCで発表されたSwiftUIの新機能を知りたい
・SwiftUIのチャート機能について知りたい
・SwiftUIでアプリ開発をしている
新規追加された「Charts」フレームワークによって、SwiftUIでチャートビューを実装することが可能になりました。
Chartsフレームワークとは、SwiftUIにおけるグラフやチャートを作成するためのパッケージやライブラリのことを指します。
※Chartsによるチャート機能はiOS16〜使用可能です。
まずはSwiftUIのビューファイルの中でチャートフレームワークをインポートしましょう。
import Charts
チャートに使用するデータ構造体を用意します。チャート内に表示するデータ一つ分の入れ物ですね。
ここで定義するプロパティは、作成するチャートの内容によって様々です。
シンプルな設計例としては、データの名前(name)とパラメータ(value)の二つを用意しておきます。データにカラーを持たせておけば、チャート内の要素ごとに個別の配色を与えることも可能です。
// データモデル(Identifiableに準拠していること)
struct Data: Identifiable {
var id = UUID()
var name: String
var value: Int
var color: Color
}
チャートのデータ定義にはループ文を使用することができるので、Identifiable
に準拠させておきましょう。UUIDなどを使って、一意のid
を持たせておけばOKです。List
やForEachと同じ要領ですね。
Chartの基本的な書き方の流れとして、Chart
のクロージャ内に、チャートの視覚的要素となるMark
を書き込んでいきます。
import SwiftUI
import Charts
struct ChartView: View {
var body: some View {
Chart {
// in Marks...
}
}
}
「Mark」とはチャートの視覚的要素を指しており、例えば棒グラフの場合はBarMark、折れ線グラフの場合はLineMarkと、複数種類のMarkが用意されています。
Markの種類ごとで個別のプロパティを持っており、選択したMarkによって必要な値を渡すことでチャートを生成します。
例えば棒グラフを実装したいときは、Chart内にBarMarkを定義することで棒グラフチャートを生成することができます。
チャートのデータ定義にはループ文を使うことができます。(データのIdentifiable準拠が必要)
以下のように、Chartの中にForEachを定義できます。
/// ✅Chart内にForEachを定義するパターン
Chart {
ForEach(data_test) { dataRow in
BarMark(
x: .value("Name", dataRow.name),
y: .value("Value", dataRow.value)
)
}
}
また、Chart自身にデータ群を渡すこともできます。使用感はSwftUIのListと似ていますね。
/// ✅Chart自身にデータ群を渡すパターン
Chart(data_test) { dataRow in
BarMark(
x: .value("Name", dataRow.name),
y: .value("Value", dataRow.value)
)
}
では、チャートの具体的な実装を見ていきましょう。
棒グラフを使用するには、Chart
のクロージャ内に「BarMark」を定義します。
プロパティにはX軸とY軸があり、それぞれにデータのラベル(名前)とパラメータ(値)を渡します。
X・Y軸に渡すデータのラベルとパラメータを反転すれば、横型の棒グラフを実装することもできます。
チャートは渡されたラベル(例の場合name)によってデータを判別します。
データ群の中に同じラベルのパラメータが入っていた場合、チャートは複数のパラメータを一つにまとめてくれます。
同じラベル内の複数のパラメータを、個別のグラフで並べたい場合は、.positionモディファイアにパラメータのカテゴリを渡します。
BarMarkのwidthプロパティから棒グラフの幅を調節できます。
.annotationモディファイアで棒グラフにイメージやテキストの注釈を付けることができます。
また、positionプロパティから配置の変更も可能です。
ラインチャート(棒グラフ)
の生成には
「LineMark」を使用します。
X軸とY軸のプロパティにデータのラベル(名前)とパラメータ(値)を渡します。
例えば以下のように、データ構造体に「曜日(ラベル)」「売り上げ(パラメータ)」を用意することで、曜日ごとの売り上げ推移グラフを作成できます。
// データモデル
struct LineData: Identifiable {
var id = UUID()
var week: String
var sales: Int
}
※ラインチャートで実装できるのは「X軸:ラベル」、「Y軸:パラメータ」による縦型グラフのみです。
データにカテゴリを付与してチャートに渡すことで、チャートがカテゴリを判別して複数の折れ線グラフを生成してくれます。
複数の折れ線グラフを表示する際のデータフローは様々あります。例えば以下のように、データ構造体にカテゴリを持たせます。
struct LineData: Identifiable {
var id = UUID()
var week: String
var sales: Int
var category: String // カテゴリを追加
}
あとは.forgroundstyleモディファイアにカテゴリを渡すことでチャートが複数のグラフを生成してくれます。
「ラーメン」と「ハンバーグ」、二つのカテゴリを判別してグラフを生成してくれていますね。
また、カテゴリ別でデータを分けて、カテゴリ個数分のLineMarkをベタ書きすることでも同様の実装が可能です。
また、データを後からカテゴリ付きの配列に加工して、一つのデータグループとしてまとめて使用するといった方法も可能です。
この場合ForEachを重ねてデータを取り出していくような形になります。
ラインチャートではforegroundStyleによってカテゴリごとにデータを分けることができますが、カラーの指定はできません。
ラインごとにカラー指定をしたい場合はchartForgroundStyleScaleを使います。
Chart(lineData_test) { dataRow in
// ...
}
.chartForegroundStyleScale(["ラーメン": .orange, "ハンバーグ": .pink])
.symbolモディファイアを設定すれば、データごとに個別のポイント装飾による区別化ができます。
.interpolationMethodモディファイアでラインを滑らかにすることができます。
前項目のLineMarkをPointMarkに変更すれば、ポイントチャートを生成できます。
Chart(lineData_test) { dataRow in
PointMark( // ⬅︎
x: .value("Week", dataRow.week),
y: .value("Sales", dataRow.sales)
)
.foregroundStyle(by: .value("Category", dataRow.category))
}
LineMarkとPointMarkを組み合わせることも可能です。
SwiftUIのチャートは各機能の様々な組み合わせを可能としており、組み合わせ次第でより高度なチャートを作成することが可能です。
WWDCの解説動画を参考に、チャートの組み合わせ例を一つ試してみましょう。
以下のコードは、1週間の中で1日ごとの売り上げ平均をグラフにしたものです。
【使用データモデル】
struct Data: Identifiable {
var id = UUID()
var week: String // 曜日
var avarageSales: Int // 平均売り上げ
}
struct CombinationChartView: View {
let data_test = [
Data(week: "月", avarageSales: 1500),
Data(week: "火", avarageSales: 2500),
Data(week: "水", avarageSales: 1800),
...
]
var body: some View {
Chart {
ForEach(data_test) { dataRow in
LineMark(
x: .value("Week", dataRow.week),
y: .value("Avarage", dataRow.avarageSales)
)
}
}
.frame(height: 300)
}
}
では、ここからさらに機能を追加してみます。
上記のチャートに、より極端な値によるヒントを得るため「最大売り上げ」と「最小売り上げ」の情報を追加してみます。
今回は新たにチャート要素AreaMark
を組み合わせて実装します。
データ内に新しく追加した最大売り上げと最小売り上げを、AreaMarkのプロパティYstartとYEndに渡します。
struct Data: Identifiable {
var id: String = UUID().uuidString
var week: String
var avarageSales: Int
var maxSales: Int // 最大売り上げ
var minSales: Int // 最小売り上げ
}
struct CombinationChartView: View {
let data_test = [
Data(week: "月", avarageSales: 1500, maxSales: 2500, minSales: 1000),
Data(week: "火", avarageSales: 2500, maxSales: 3000, minSales: 1200),
Data(week: "水", avarageSales: 1800, maxSales: 2400, minSales: 1500),
...
]
var body: some View {
Chart {
ForEach(data_test) { dataRow in
// ✅最大値、最小値をエリアで表示
AreaMark(x: .value("Week", dataRow.week),
yStart: .value("MinSales", dataRow.minSales),
yEnd: .value("MaxSales", dataRow.maxSales)
)
.opacity(0.3)
LineMark(
x: .value("Week", dataRow.week),
y: .value("Avarage", dataRow.avarageSales)
)
}
}
.frame(height: 300)
}
}
1日の売り上げ平均値を表す折れ線グラフに加えて、売り上げの最小値と最大値をエリアで可視化することができました。
SwiftUIのチャートは、視覚要素を簡単に組み替えることができます。
上記で作った折れ線グラフのチャートを、棒グラフ型の表現に変えてみましょう。
このように、Mark要素を切り替えるだけでチャートの視覚要素を簡単に組み替えることができます。
Chartsには他にも様々なカスタマイズオプションがあります。
Chartsはデータを渡すことで適切なチャート軸を自動で生成してくれましたね。
これらの軸も明示的なカスタマイズが可能です。見ていきましょう。
【使用データモデル】
struct CustomizeData: Identifiable {
var id = UUID()
var month: Date
var sales: Int
}
今回はDate型の毎月データと売り上げを持たせたデータを使います。
.chartXAxisモディファイアの中にAxisMarksを定義することで、X軸のカスタマイズができます。
AxisMarksにパラメータの指定がない場合、Chartsはデフォルトの軸を生成します。
AxisMarksにパラメータを渡してみましょう。
例えば以下のようにパラメータを渡すことで、デフォルトでは段階的なラベル表示だったのが、網羅的な形でラベル表示に切り替わります。
また、AxisMarksのクロージャにAxisGridLineを定義することでデータ領域のガイドにオプションを付与できます。
AxisMarksのクロージャ引数valueには現在の軸の値に関する情報が格納されます。
.chartXAxis {
AxisMarks(values: .stride(by: .month)) { value in
AxisGridLine().foregroundStyle(.black) // ⬅︎
}
}
AxisTickとAxisValueLabelを定義することでラベルに境界線を付与できたりもします。
.chartXAxis {
AxisMarks(values: .stride(by: .month)) { value in
AxisGridLine().foregroundStyle(.black)
AxisTick().foregroundStyle(.black) // ⬅︎
AxisValueLabel( // ⬅︎
format: .dateTime.month(.narrow)
)
}
}
.chartYAxisモディファイアを使えばY軸のカスタマイズが可能です。
axisMarksのpositionプロパティを.leadingに指定すれば、Y軸のガイドを左側へ持ってくることができます。
axisMarksのpresetプロパティから表示の微調整ができます。
.chartYScaleモディファイアでパラメータガイドの上限値を明示的に設定できます。デフォルトでは渡されたデータ群から適切な上限値が設定されます。
以下のように記述することでガイドが非表示になります。
Chart {
...
}
.chartYAxis(.hidden)
.chartXAxis(.hidden)
以上、SwiftUIのChartsフレームワークについてでした!
今回ご紹介したものはチャート機能のほんの一部です。さらに詳しい機能を知りたい場合は、ぜひWWDC2022の解説動画などを参考にしてみてください👍
\ SHARE /
アプリ開発が学べる勉強会を開催中!
CodeCandyではアプリ開発を学ぶための勉強会を定期開催しています。
学習する習慣を身につけたい、他の参加者と作業したい、アプリ開発の基本をマスターしたい、という方のために無料で学べる勉強会です。
グループにメンバー登録して頂くと、イベント開催時にメールで通知されます。
徹底した基礎学習からマスターするiPhoneアプリ開発集中オンライン講座開講!
本書「iPhoneアプリ開発集中講座」を執筆している現役エンジニア講師陣が直接に指導!
基礎、課題実習で実践力を鍛えて、オリジナルアプリ公開までチャレンジ!
充実した転職支援もあるので、エンジニアへ転職したい人にもおすすめです!
まずは、現役エンジニアに相談できる無料相談をご利用ください。
2022年2月よりSwift学習を始め、4月からiOSアプリ開発オンラインスクール「CodeCandy」にてアプリ開発を学ぶ。 2023年10月に個人開発アプリ「unico」をリリース。現在はアプリの機能アップデートをしながら、スクール運営の技術ブログの執筆や、出版書籍の入稿チェック・デバッグにも携わる。