今年もAppleによる年一回の祭典「WWDC」が近づいてきました!

今回は、昨年度2022年のWWDCで発表された新機能、iOS16〜使える「Charts」フレームワークについてまとめていきます。

まだチャート機能を触ったことがない方は、この機会に一緒に触れてみましょう!

What's new in SwiftUI2022

本記事のソースコード

本記事で使用しているサンプルコードはGitHubにて公開されています。

コード内容の確認にぜひご利用ください🍎

GitHubのソースコードを見る>>

[ 本記事はこんな人におすすめ ]

・2022年度にWWDCで発表されたSwiftUIの新機能を知りたい

・SwiftUIのチャート機能について知りたい

・SwiftUIでアプリ開発をしている

Swift Charts

新規追加された「Charts」フレームワークによって、SwiftUIでチャートビューを実装することが可能になりました。

Chartsフレームワークとは、SwiftUIにおけるグラフやチャートを作成するためのパッケージやライブラリのことを指します。

※Chartsによるチャート機能はiOS16〜使用可能です。

What's new in SwiftUI2022

下準備

1. チャートフレームワークのインポート

まずはSwiftUIのビューファイルの中でチャートフレームワークをインポートしましょう。

				
					import Charts
				
			

2. データ構造体(struct)の準備

チャートに使用するデータ構造体を用意します。チャート内に表示するデータ一つ分の入れ物ですね。

ここで定義するプロパティは、作成するチャートの内容によって様々です。

シンプルな設計例としては、データの名前(name)とパラメータ(value)の二つを用意しておきます。データにカラーを持たせておけば、チャート内の要素ごとに個別の配色を与えることも可能です。

				
					// データモデル(Identifiableに準拠していること)
struct Data: Identifiable {
    var id = UUID()
    var name: String
    var value: Int
    var color: Color
}
				
			

チャートのデータ定義にはループ文を使用することができるので、Identifiableに準拠させておきましょう。UUIDなどを使って、一意のidを持たせておけばOKです。ListForEachと同じ要領ですね。

Chartの基本的な記述法

Chartの基本的な書き方の流れとして、Chartのクロージャ内に、チャートの視覚的要素となるMarkを書き込んでいきます。

				
					import SwiftUI
import Charts

struct ChartView: View {

    var body: some View {

        Chart {
        
         // in Marks... 
         
        }
    }
}
				
			

チャートの視覚的要素「Mark」

Mark」とはチャートの視覚的要素を指しており、例えば棒グラフの場合はBarMark、折れ線グラフの場合はLineMarkと、複数種類のMarkが用意されています。

Markの種類ごとで個別のプロパティを持っており、選択したMarkによって必要な値を渡すことでチャートを生成します。

What's new in SwiftUI2022
What's new in SwiftUI2022

例えば棒グラフを実装したいときは、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)
            )
        }
				
			
ループを用いたデータ定義

では、チャートの具体的な実装を見ていきましょう。

棒グラフ(BarMark)

棒グラフを使用するには、Chartのクロージャ内に「BarMark」を定義します。

プロパティにはX軸とY軸があり、それぞれにデータのラベル(名前)パラメータ(値)を渡します。

縦グラフと横グラフ

X・Y軸に渡すデータのラベルとパラメータを反転すれば、横型の棒グラフを実装することもできます。

同じラベルに複数のパラメータを追加する

チャートは渡されたラベル(例の場合name)によってデータを判別します。

データ群の中に同じラベルのパラメータが入っていた場合、チャートは複数のパラメータを一つにまとめてくれます。

同カテゴリ「Akiko」の複数パラメータを自動でまとめる

同じラベル内に複数のグラフを表示する

同じラベル内の複数のパラメータを、個別のグラフで並べたい場合は、.positionモディファイアにパラメータのカテゴリを渡します。

棒グラフの装飾

・グラフの幅を変更する(width)

BarMarkwidthプロパティから棒グラフの幅を調節できます。

・グラフに注釈を付ける(annotation)

.annotationモディファイアで棒グラフにイメージやテキストの注釈を付けることができます。

また、positionプロパティから配置の変更も可能です。

ラインチャート(LineMark)

ラインチャート(棒グラフ)の生成には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をベタ書きすることでも同様の実装が可能です。

カテゴリごとのデータ群
データごとにLineMarkを定義

また、データを後からカテゴリ付きの配列に加工して、一つのデータグループとしてまとめて使用するといった方法も可能です。

後からカテゴリをつけてまとめる

この場合ForEachを重ねてデータを取り出していくような形になります。

ラインチャートの色指定

ラインチャートではforegroundStyleによってカテゴリごとにデータを分けることができますが、カラーの指定はできません。

ラインごとにカラー指定をしたい場合はchartForgroundStyleScaleを使います。

				
					Chart(lineData_test) { dataRow in

    // ...

}
.chartForegroundStyleScale(["ラーメン": .orange, "ハンバーグ": .pink])
				
			

ラインチャートの装飾

・データごとで個別のポイント装飾

.symbolモディファイアを設定すれば、データごとに個別のポイント装飾による区別化ができます。

ラーメンは「◯」、ハンバーグは「□」にポイント装飾される

・ラインを滑らかにする

.interpolationMethodモディファイアでラインを滑らかにすることができます。

ポイントチャート(PointMark)

前項目のLineMarkPointMarkに変更すれば、ポイントチャートを生成できます。

				
					Chart(lineData_test) { dataRow in

    PointMark( // ⬅︎
        x: .value("Week", dataRow.week),
        y: .value("Sales", dataRow.sales)
    )
    .foregroundStyle(by: .value("Category", dataRow.category))
}
				
			

ポイントとラインの組み合わせ

LineMarkPointMarkを組み合わせることも可能です。

チャートの組み合わせによるカスタマイズ

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)
    }
}
				
			

では、ここからさらに機能を追加してみます。

Markの組み合わせで複雑なチャートを作る

上記のチャートに、より極端な値によるヒントを得るため「最大売り上げ」「最小売り上げ」の情報を追加してみます。

今回は新たにチャート要素AreaMarkを組み合わせて実装します。

データ内に新しく追加した最大売り上げと最小売り上げを、AreaMarkのプロパティYstartYEndに渡します。

				
					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要素を切り替えるだけでチャートの視覚要素を簡単に組み替えることができます。

より細かなカスタマイズ(axisMarks)

Chartsには他にも様々なカスタマイズオプションがあります。

Chartsはデータを渡すことで適切なチャート軸を自動で生成してくれましたね。

これらの軸も明示的なカスタマイズが可能です。見ていきましょう。

【使用データモデル】

				
					struct CustomizeData: Identifiable {
    var id = UUID()
    var month: Date
    var sales: Int
}
				
			

今回はDate型の毎月データと売り上げを持たせたデータを使います。

チャートのX軸をカスタマイズする(chartXAxis)

.chartXAxisモディファイアの中にAxisMarksを定義することで、X軸のカスタマイズができます。

AxisMarksにパラメータの指定がない場合、Chartsはデフォルトの軸を生成します。

AxisMarksにパラメータを渡してみましょう。

例えば以下のようにパラメータを渡すことで、デフォルトでは段階的なラベル表示だったのが、網羅的な形でラベル表示に切り替わります。

また、AxisMarksのクロージャにAxisGridLineを定義することでデータ領域のガイドにオプションを付与できます。

AxisMarksのクロージャ引数valueには現在の軸の値に関する情報が格納されます。

				
					.chartXAxis {
            AxisMarks(values: .stride(by: .month)) { value in
                AxisGridLine().foregroundStyle(.black) // ⬅︎
            }
        }
				
			

AxisTickAxisValueLabelを定義することでラベルに境界線を付与できたりもします。

				
					.chartXAxis {
            AxisMarks(values: .stride(by: .month)) { value in
                AxisGridLine().foregroundStyle(.black)
                AxisTick().foregroundStyle(.black) // ⬅︎
                AxisValueLabel( // ⬅︎
                    format: .dateTime.month(.narrow)
                )
            }
        }
				
			

チャートのY軸をカスタマイズする(chartYAxis)

.chartYAxisモディファイアを使えばY軸のカスタマイズが可能です。

・パラメータガイドの表示を変更する

axisMarkspositionプロパティを.leadingに指定すれば、Y軸のガイドを左側へ持ってくることができます。

・パラメータガイドの表示を変更する

axisMarkspresetプロパティから表示の微調整ができます。

・パラメータガイドの上限値を設定する

.chartYScaleモディファイアでパラメータガイドの上限値を明示的に設定できます。デフォルトでは渡されたデータ群から適切な上限値が設定されます。

チャートのガイドを非表示にする

以下のように記述することでガイドが非表示になります。

				
					Chart {
    ...
}
.chartYAxis(.hidden)
.chartXAxis(.hidden)

				
			

まとめ

以上、SwiftUIのChartsフレームワークについてでした!

今回ご紹介したものはチャート機能のほんの一部です。さらに詳しい機能を知りたい場合は、ぜひWWDC2022の解説動画などを参考にしてみてください👍

動画の紹介

\  SHARE  /

Twitter
Facebook
Email

✏️ アプリ開発が学べる勉強会を開催中! 

CodeCandyではアプリ開発を学ぶための勉強会を定期開催しています。
学習する習慣を身につけたい、他の参加者と作業したい、アプリ開発の基本をマスターしたい、という方のために無料で学べる勉強会です。
グループにメンバー登録して頂くと、イベント開催時にメールで通知されます。

▶️グループのメンバーとして参加する

徹底した基礎学習からマスターするiPhoneアプリ開発集中オンライン講座開講!

本書「iPhoneアプリ開発集中講座」を執筆している現役エンジニア講師陣が直接に指導!
基礎、課題実習で実践力を鍛えて、オリジナルアプリ公開までチャレンジ!
充実した転職支援もあるので、エンジニアへ転職したい人にもおすすめです!

まずは、現役エンジニアに相談できる無料相談をご利用ください。

\ Official /

By 中川 賢亮

2022年2月よりSwift学習を始め、4月からiOSアプリ開発オンラインスクール「CodeCandy」にてアプリ開発を学ぶ。 2023年10月に個人開発アプリ「unico」をリリース。現在はアプリの機能アップデートをしながら、スクール運営の技術ブログの執筆や、出版書籍の入稿チェック・デバッグにも携わる。