3
2

【SwiftUI】Chartの棒グラフでグラデーションを設定した際にグラデーションの終点を揃える

Last updated at Posted at 2024-01-14

はじめに

SwiftUIのChartを極めようの会を1人でしてます。

解決したい課題

棒グラフにグラデーションを設定します。

import SwiftUI
import Charts

struct Temperature {
    let day: Int
    let max: Double
    let min: Double
}

struct ContentView: View {
    @State private var temperatures: [Temperature] = [
        .init(day: 1, max: 17, min: 13),
        .init(day: 2, max: 25, min: 10),
        .init(day: 3, max: 12, min: 11),
        .init(day: 4, max: 21, min: 11),
        .init(day: 5, max: 10, min: 6)
    ]
    
    var body: some View {
        Chart {
            ForEach(temperatures, id: \.day) { temperature in
                BarMark(
                    x: .value("day", temperature.day),
                    y: .value("max", temperature.max),
                    width: 30
                )
                .foregroundStyle(by: .value("max", "最高気温"))
            }
        }
        .chartForegroundStyleScale(["最高気温": LinearGradient(colors: [.purple, .red, .orange, .yellow], startPoint: .top, endPoint: .bottom)])
        .frame(width: 300, height: 300)
    }
}

上記のコードで実行すると以下のようなUIになります。

スクリーンショット 2024-01-14 21.45.51.png

まぁ悪くないですが、グラデーションの終点が揃っていなので色から高い低いが分かりにくいです。

以下のようにグラデーションの始点と終点を揃えることによって、色からも高い低いが理解しやすいです。

スクリーンショット 2024-01-14 21.47.54.png

ではSwiftUIのChartでどのように実装するのでしょうか?

実装

import SwiftUI
import Charts

struct Temperature {
    let day: Int
    let max: Double
    let min: Double
}

struct ContentView: View {
    @State private var temperatures: [Temperature] = [
        .init(day: 1, max: 17, min: 13),
        .init(day: 2, max: 25, min: 10),
        .init(day: 3, max: 12, min: 11),
        .init(day: 4, max: 21, min: 11),
        .init(day: 5, max: 10, min: 6)
    ]
    
    var body: some View {
        Chart {
            ForEach(temperatures, id: \.day) { temperature in
                BarMark(
                    x: .value("day", temperature.day),
                    y: .value("max", temperature.max),
                    width: 30
                )
                .foregroundStyle(by: .value("max", "最高気温"))
+               .alignsMarkStylesWithPlotArea()
            }
        }
        .chartForegroundStyleScale(["最高気温": LinearGradient(colors: [.purple, .red, .orange, .yellow], startPoint: .top, endPoint: .bottom)])
        .frame(width: 300, height: 300)
    }
}

おわり

alignsMarkStylesWithPlotAreaを付与することによってグラデーションの終点が揃えられました。

公式ドキュメント

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2