View in English

  • メニューを開く メニューを閉じる
  • Apple Developer
検索
検索を終了
  • Apple Developer
  • ニュース
  • 見つける
  • デザイン
  • 開発
  • 配信
  • サポート
  • アカウント
次の内容に検索結果を絞り込む

クイックリンク

5 クイックリンク

ビデオ

メニューを開く メニューを閉じる
  • コレクション
  • トピック
  • すべてのビデオ
  • 利用方法

WWDC25に戻る

  • 概要
  • トランスクリプト
  • コード
  • Swift Chartsの3次元変換

    Chart3Dを使って2D Swift Chartsを3次元に変換し、まったく新しい視点からデータセットを可視化する方法を説明します。3Dでデータをプロットし、数学的サーフェスを可視化し、カメラからマテリアルまですべてをカスタマイズして、より直感的で楽しい3Dチャートを作成しましょう。 このセッションの内容を十分理解できるよう、2D Swift Chartsの作成方法を確認しておくことをおすすめします。

    関連する章

    • 0:00 - イントロダクション
    • 1:54 - 3Dでのプロット
    • 5:05 - サーフェスのプロット
    • 7:03 - カスタマイズ

    リソース

    • Swift Charts
    • Swift Charts updates
      • HDビデオ
      • SDビデオ

    関連ビデオ

    WWDC24

    • Swift Charts:ベクトルプロットと関数プロット

    WWDC22

    • グラフを使ったApp体験のデザイン
    • 効果的なグラフのデザイン
  • このビデオを検索

    こんにちはMikeです System Experienceチームでエンジニアをしています 本日はSwift Chartsの素晴らしい新機能 について説明したいと思います Swift Chartsはわかりやすく魅力的な グラフを作成するためのフレームワークです

    グラフはAppleプラットフォーム全体で使われています 「天気」での気温の確認

    「設定」でのバッテリー使用状況の表示 「計算メモ」での数学関数のグラフ化などに 利用されています

    Swift Chartsに用意されている 構成要素を利用すると 軸の目盛り ラベル 折れ線グラフなどの コンポーネントを使って 2Dグラフを作成できます

    もっと魅力的なグラフを作ることもできます iOS macOS visionOS 26の新機能により Swift Chartsは3Dグラフに対応できます そうです ユーザーはまったく新しい 視点からデータセットを調べ 理解できるようになるのです

    このセッションでは 2Dグラフのセットを3Dでプロットして 3次元化する方法を紹介します またサーフェスプロットを使って 3次元の数学関数をグラフ化する 方法を説明します 最後にグラフをより直感的で 魅力的なものにするための カスタマイズ方法を説明します その前に重要なお知らせがあります

    私はペンギンが大好きです

    実はお気に入りのデータセットの1つには 南極のパーマー諸島に生息する 何百羽ものペンギンの観察データが 含まれているのです

    このデータには各ペンギンの くちばしや翼の長さと体重が含まれており

    ヒゲペンギン ジェンツーペンギン アデリーペンギンという種類ごとに

    分類されています

    Swift Chartsを使ってこのデータから 詳細情報を引き出し 3Dでプロットすることで ペンギンの種類の違いを視覚化する方法を 紹介します

    ペンギンの翼の長さと 体重の関係を示す 2Dグラフを作成しました PointMarkを使って各ペンギンの 翼の長さと体重をプロットし foregroundStyleによって 種類ごとにポイントの色分けをして 隅に凡例を作成します

    これは素晴らしいグラフです Swift Chartsを 使えばグラフを簡単に作成できます このグラフでは ヒゲペンギンとアデリーペンギンの 翼の長さと体重は似ているが ジェンツーペンギンは翼が長く 体重も重いことを示しています

    ペンギンデータセットには くちばしの長さも含まれており くちばしの長さと体重をプロットした グラフも作成しました

    このグラフはヒゲペンギンとジェンツー ペンギンのくちばしの長さは似ているが アデリーペンギンのくちばしは短いことを 示しています

    最後にくちばしと翼の長さの グラフを作成しました くちばしが長いペンギンは 翼も長い傾向があります

    これらはどちらも優れた 2Dグラフで 一度に2つの特徴間の関係について 有用な詳細情報を提供します

    Swift Chartsではこれらのグラフを 次のレベルに引き上げることができます 1つのグラフにすべてのデータを 含めることができるのです

    それはChart3Dと呼ばれています Chart3Dは 散布図などの2Dグラフで よく知られている概念を採用しており それをフル3Dのグラフに適用します

    3Dグラフを使うために ChartをChart3Dに変更します

    PointMarkはChart3Dで有用であり Z値も指定できるようになりました ここでは「Beak Length」を使用します

    Z軸のラベルも 「Beak Length」に設定して以上で完了です

    数行のコードとChart3Dにより ペンギンの種類ごとの違いを 楽しくてインタラクティブな方法で はっきり表現できるようになりました

    単純なジェスチャーで チャートを正確な角度まで回転させて データポイントの 3つのクラスタを確認できます

    チャートは側面からも表示でき 一度に2つの特徴を比較できます グラフを2D表示する場合と似ています

    3Dグラフが特に有効なのは 正確な数値よりも データの形状が重要な場合です これは当然ながら データ自体が3次元の場合であり 特に データが3D空間の物理的な位置を 表す場合に当てはまります

    またインタラクティブ性は 3次元データセットを理解する際に重要です アプリの体験を向上させるために インタラクションが必要な場合にのみ 3Dチャートを検討してください データセットの最適な表現について 2Dと3Dのどちらを選択したら良いかは 一概には決められません

    PointMarkやRuleMark RectangleMarkはすべて3Dグラフ用に 更新されています そしてChart3Dに固有の機能として SurfacePlotがあるのです

    次にSurfacePlotの仕組みを 詳しく見ていきましょう

    SurfacePlotはLinePlotの3次元拡張機能です 最大2つの変数を含む数学的なサーフェスを 3次元でプロットします

    新しいSurfacePlot APIは LinePlot APIに似ています

    2つのdoubleを受け取り 1つのdoubleを返す クロージャを受け入れます

    クロージャに数式を入力すると SurfacePlotはさまざまな XとZの値で式を評価し 計算されたYの値から 連続したサーフェスを作成します これらのサーフェスは必要に応じて 複雑にしたり シンプルにしたりできます

    LinePlot APIを介した関数プロットの 詳細については WWDC24の 「Swift Charts:ベクトルプロットと関数プロット」 をご覧ください

    お気づきでしょうか ペンギンのデータセットを改めて見ると ペンギンのくちばしと翼の長さ および体重の間には線形関係があるようです これは妥当な推測のように思えますが 一時的な対処で済ませずに SurfacePlotを使って データの線形回帰を示します

    独立したx変数とz変数に 基づいてy値を推定する LinearRegressionクラスを定義しました 具体的には 翼の長さとくちばしの長さに基づいて ペンギンの体重を推定する 線形回帰を設定します

    この線形回帰はSurfacePlotで使われ 推定された体重を連続したサーフェスとして プロットします

    素晴らしいですね このデータには線形関係があるようです SurfacePlotは翼の長さと体重の間に 正の相関関係があることを示しています また くちばしの長さと体重の間にも わずかに正の相関関係が見られます

    では Chart3Dのスタイルや動作を カスタマイズするための 優れた方法を説明します

    先ほどペンギンのデータセットを 操作していましたが グラフの角度が変わるとデータの外観も 変更されることに気づきました

    この角度はデータポイントの クラスタを表示するのに最適です この角度は線形関係を示すのに 適しています

    これらの角度はグラフのポーズと呼ばれます

    最初のポーズを選択することが重要です これによりデータを適切に表現できます

    事前に値がわからない動的データの場合 その種類の代表的なデータセットを 適切に表す初期ポーズを選んでください

    グラフのポーズはChart3DPose修飾子を 使って調整され この修飾子はChart3DPoseの値を 受け取ります

    ポーズをfrontなどの特定の値に 設定できます

    カスタムポーズを定義することもできます このイニシャライザは2つのパラメータを 取ります グラフを左右に回転させるazimuthと

    上下に傾けるinclinationです

    次に グラフの奥にあるポイントと 手前にあるポイントが 同じサイズであることに注目してください

    これにより 奥行きに関係なく グラフ全体でサイズや距離を 比較しやすくなります

    またグラフを横から見るのにも適しており 3Dグラフを実質的に2Dグラフに変換できます

    これは正投影カメラ投影と呼ばれます

    Chart3Dには2つのカメラ投影があります デフォルトの動作である正投影と 透視投影です 透視投影では 遠くにあるデータポイントは小さく表示され 平行線は収束します これによりイマーシブな体験が可能になり 奥行きの認識に役立ちます

    カメラ投影はchart3DCameraProjection 修飾子を使って設定されます

    SurfacePlotsにはサーフェスのスタイルを カスタマイズするオプションがあります

    ForegroundStyleはLinearGradientや EllipticalGradientなどのグラデーションを 受け取り 次の2つの新しい値をサポートします 各ポイントのサーフェスの高さに基づいて サーフェス上のポイントを着色する heightBasedと

    各ポイントのサーフェスの角度に基づいて サーフェス上のポイントを着色する normalBasedです

    Chart3Dでは他にも多くの修飾子を利用でき その中には2Dグラフで よく使われているものもあります これらを使って サーフェスのスタイル PointMarkのシンボル グラフのドメインと軸の目盛り 選択時の動作をカスタマイズします

    これらのビュー修飾子をPointMark RuleMark RectangleMark SurfacePlotと 組み合わせることで さまざまな種類の 魅力的なグラフを作成できます これはほんの一例にすぎません

    また3DグラフはVision Proで動作し 見た目も優れており 3次元データセットに自然に適合します

    これらはSwift Chartsに導入される 新しい3D機能の一部です

    3Dがデータの適切な表現方法であると 判断したら Chart3Dでプロットして グラフに新たなレベルの奥行きを加え Swift ChartsのカスタマイズAPIを使って わかりやすく魅力的なグラフを 独自にデザインしてみてください

    Swift Chartsをアプリに組み込む場合の ベストプラクティスについては WWDC22の「グラフを使った App体験のデザイン」をご覧ください

    ご視聴ありがとうございました 皆さんが3次元で作るグラフを 楽しみにしています

    • 2:03 - A scatterplot of a penguin's flipper length and weight

      // A scatterplot of a penguin's flipper length and weight
      
      import SwiftUI
      import Charts
      
      struct PenguinChart: View {
        var body: some View {
          Chart(penguins) { penguin in
            PointMark(
              x: .value("Flipper Length", penguin.flipperLength),
              y: .value("Weight", penguin.weight)
            )
            .foregroundStyle(by: .value("Species", penguin.species))
          }
          .chartXAxisLabel("Flipper Length (mm)")
          .chartYAxisLabel("Weight (kg)")
          .chartXScale(domain: 160...240)
          .chartYScale(domain: 2...7)
          .chartXAxis {
            AxisMarks(values: [160, 180, 200, 220, 240]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
          .chartYAxis {
            AxisMarks(values: [2, 3, 4, 5, 6, 7]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
        }
      }
    • 2:39 - A scatterplot of a penguin's beak length and weight

      // A scatterplot of a penguin's beak length and weight
      
      import SwiftUI
      import Charts
      
      struct PenguinChart: View {
        var body: some View {
          Chart(penguins) { penguin in
            PointMark(
              x: .value("Beak Length", penguin.beakLength),
              y: .value("Weight", penguin.weight)
            )
            .foregroundStyle(by: .value("Species", penguin.species))
          }
          .chartXAxisLabel("Beak Length (mm)")
          .chartYAxisLabel("Weight (kg)")
          .chartXScale(domain: 30...60)
          .chartYScale(domain: 2...7)
          .chartXAxis {
            AxisMarks(values: [30, 40, 50, 60]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
          .chartYAxis {
            AxisMarks(values: [2, 3, 4, 5, 6, 7]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
        }
      }
    • 2:51 - A scatterplot of a penguin's beak length and flipper length

      // A scatterplot of a penguin's beak length and flipper length
      
      import SwiftUI
      import Charts
      
      struct PenguinChart: View {
        var body: some View {
          Chart(penguins) { penguin in
            PointMark(
              x: .value("Beak Length", penguin.beakLength),
              y: .value("Flipper Length", penguin.flipperLength)
            )
            .foregroundStyle(by: .value("Species", penguin.species))
          }
          .chartXAxisLabel("Beak Length (mm)")
          .chartYAxisLabel("Flipper Length (mm)")
          .chartXScale(domain: 30...60)
          .chartYScale(domain: 160...240)
          .chartXAxis {
            AxisMarks(values: [30, 40, 50, 60]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
          .chartYAxis {
            AxisMarks(values: [160, 180, 200, 220, 240]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
        }
      }
    • 3:28 - A scatterplot of a penguin's flipper length, beak length, and weight

      // A scatterplot of a penguin's flipper length, beak length, and weight
      
      import SwiftUI
      import Charts
      
      struct PenguinChart: View {
        var body: some View {
          Chart3D(penguins) { penguin in
            PointMark(
              x: .value("Flipper Length", penguin.flipperLength),
              y: .value("Weight", penguin.weight),
              z: .value("Beak Length", penguin.beakLength)
            )
            .foregroundStyle(by: .value("Species", penguin.species))
          }
          .chartXAxisLabel("Flipper Length (mm)")
          .chartYAxisLabel("Weight (kg)")
          .chartZAxisLabel("Beak Length (mm)")
          .chartXScale(domain: 160...240, range: -0.5...0.5)
          .chartYScale(domain: 2...7, range: -0.5...0.5)
          .chartZScale(domain: 30...60, range: -0.5...0.5)
          .chartXAxis {
            AxisMarks(values: [160, 180, 200, 220, 240]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
          .chartYAxis {
            AxisMarks(values: [2, 3, 4, 5, 6, 7]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
          .chartZAxis {
            AxisMarks(values: [30, 40, 50, 60]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
        }
      }
    • 5:19 - A surface plot showing mathematical functions (x * z)

      // A surface plot showing mathematical functions
      
      import SwiftUI
      import Charts
      
      var SurfacePlotChart: View {
        var body: some View {
          Chart3D {
            SurfacePlot(x: "X", y: "Y", z: "Z") { x, z in
              // (Double, Double) -> Double
              x * z
            }
          }
        }
      }
    • 5:43 - A surface plot showing mathematical functions

      // A surface plot showing mathematical functions
      
      import SwiftUI
      import Charts
      
      var SurfacePlotChart: View {
        var body: some View {
          Chart3D {
            SurfacePlot(x: "X", y: "Y", z: "Z") { x, z in
              // (Double, Double) -> Double
              (sin(5 * x) + sin(5 * z)) / 2
            }
          }
        }
      }
    • 5:46 - A surface plot showing mathematical functions (-z)

      // A surface plot showing mathematical functions
      
      import SwiftUI
      import Charts
      
      var SurfacePlotChart: View {
        var body: some View {
          Chart3D {
            SurfacePlot(x: "X", y: "Y", z: "Z") { x, z in
              // (Double, Double) -> Double
              -z
            }
          }
        }
      }
    • 6:19 - Present a linear regression of the penguin data

      // Present a linear regression of the penguin data
      
      import SwiftUI
      import Charts
      import CreateML
      import TabularData
      
      final class LinearRegression: Sendable {
        let regressor: MLLinearRegressor
      
        init(
          _ data: Data,
          x xPath: KeyPath,
          y yPath: KeyPath,
          z zPath: KeyPath
        ) {
          let x = Column(name: "X", contents: data.map { $0[keyPath: xPath] })
          let y = Column(name: "Y", contents: data.map { $0[keyPath: yPath] })
          let z = Column(name: "Z", contents: data.map { $0[keyPath: zPath] })
          let data = DataFrame(columns: [x, y, z].map { $0.eraseToAnyColumn() })
          regressor = try! MLLinearRegressor(trainingData: data, targetColumn: "Y")
        }
      
        func callAsFunction(_ x: Double, _ z: Double) -> Double {
          let x = Column(name: "X", contents: [x])
          let z = Column(name: "Z", contents: [z])
          let data = DataFrame(columns: [x, z].map { $0.eraseToAnyColumn() })
          return (try? regressor.predictions(from: data))?.first as? Double ?? .nan
        }
      }
      
      let linearRegression = LinearRegression(
        penguins,
        x: \.flipperLength,
        y: \.weight,
        z: \.beakLength
      )
      
      struct PenguinChart: some View {
        var body: some View {
          Chart3D {
            ForEach(penguins) { penguin in
              PointMark(
                x: .value("Flipper Length", penguin.flipperLength),
                y: .value("Weight", penguin.weight),
                z: .value("Beak Length", penguin.beakLength),
              )
              .foregroundStyle(by: .value("Species", penguin.species))
            }
      
            SurfacePlot(x: "Flipper Length", y: "Weight", z: "Beak Length") { flipperLength, beakLength in
              linearRegression(flipperLength, beakLength)
            }
            .foregroundStyle(.gray)
          }
          .chartXAxisLabel("Flipper Length (mm)")
          .chartYAxisLabel("Weight (kg)")
          .chartZAxisLabel("Beak Length (mm)")
          .chartXScale(domain: 160...240, range: -0.5...0.5)
          .chartYScale(domain: 2...7, range: -0.5...0.5)
          .chartZScale(domain: 30...60, range: -0.5...0.5)
          .chartXAxis {
            AxisMarks(values: [160, 180, 200, 220, 240]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
          .chartYAxis {
            AxisMarks(values: [2, 3, 4, 5, 6, 7]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
          .chartZAxis {
            AxisMarks(values: [30, 40, 50, 60]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
        }
      }
    • 7:50 - Adjust the initial chart pose (Default)

      // Adjust the initial chart pose
      
      import SwiftUI
      import Charts
      
      struct PenguinChart: View {
        @State var pose: Chart3DPose = .default
      
        var body: some View {
          Chart3D(penguins) { penguin in
            PointMark(
              x: .value("Flipper Length", penguin.flipperLength),
              y: .value("Weight", penguin.weight),
              z: .value("Beak Length", penguin.beakLength)
            )
            .foregroundStyle(by: .value("Species", penguin.species))
          }
          .chart3DPose($pose)
          .chartXAxisLabel("Flipper Length (mm)")
          .chartYAxisLabel("Weight (kg)")
          .chartZAxisLabel("Beak Length (mm)")
          .chartXScale(domain: 160...240, range: -0.5...0.5)
          .chartYScale(domain: 2...7, range: -0.5...0.5)
          .chartZScale(domain: 30...60, range: -0.5...0.5)
          .chartXAxis {
            AxisMarks(values: [160, 180, 200, 220, 240]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
          .chartYAxis {
            AxisMarks(values: [2, 3, 4, 5, 6, 7]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
          .chartZAxis {
            AxisMarks(values: [30, 40, 50, 60]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
        }
      }
    • 8:02 - Adjust the initial chart pose (Front)

      // Adjust the initial chart pose
      
      import SwiftUI
      import Charts
      
      struct PenguinChart: View {
        @State var pose: Chart3DPose = .front
      
        var body: some View {
          Chart3D(penguins) { penguin in
            PointMark(
              x: .value("Flipper Length", penguin.flipperLength),
              y: .value("Weight", penguin.weight),
              z: .value("Beak Length", penguin.beakLength)
            )
            .foregroundStyle(by: .value("Species", penguin.species))
          }
          .chart3DPose($pose)
          .chartXAxisLabel("Flipper Length (mm)")
          .chartYAxisLabel("Weight (kg)")
          .chartZAxisLabel("Beak Length (mm)")
          .chartXScale(domain: 160...240, range: -0.5...0.5)
          .chartYScale(domain: 2...7, range: -0.5...0.5)
          .chartZScale(domain: 30...60, range: -0.5...0.5)
          .chartXAxis {
            AxisMarks(values: [160, 180, 200, 220, 240]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
          .chartYAxis {
            AxisMarks(values: [2, 3, 4, 5, 6, 7]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
          .chartZAxis {
            AxisMarks(values: [30, 40, 50, 60]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
        }
      }
    • 8:09 - Adjust the initial chart pose (Custom)

      // Adjust the initial chart pose
      
      import SwiftUI
      import Charts
      
      struct PenguinChart: View {
        @State var pose = Chart3DPose(
          azimuth: .degrees(20),
          inclination: .degrees(7)
        )
      
        var body: some View {
          Chart3D(penguins) { penguin in
            PointMark(
              x: .value("Flipper Length", penguin.flipperLength),
              y: .value("Weight", penguin.weight),
              z: .value("Beak Length", penguin.beakLength)
            )
            .foregroundStyle(by: .value("Species", penguin.species))
          }
          .chart3DPose($pose)
          .chartXAxisLabel("Flipper Length (mm)")
          .chartYAxisLabel("Weight (kg)")
          .chartZAxisLabel("Beak Length (mm)")
          .chartXScale(domain: 160...240, range: -0.5...0.5)
          .chartYScale(domain: 2...7, range: -0.5...0.5)
          .chartZScale(domain: 30...60, range: -0.5...0.5)
          .chartXAxis {
            AxisMarks(values: [160, 180, 200, 220, 240]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
          .chartYAxis {
            AxisMarks(values: [2, 3, 4, 5, 6, 7]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
          .chartZAxis {
            AxisMarks(values: [30, 40, 50, 60]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
        }
      }
    • 9:15 - Adjust the initial chart pose and camera projection

      // Adjust the initial chart pose and camera projection
      
      import SwiftUI
      import Charts
      
      struct PenguinChart: View {
        @State var pose = Chart3DPose(
          azimuth: .degrees(20),
          inclination: .degrees(7)
        )
      
        var body: some View {
          Chart3D(penguins) { penguin in
            PointMark(
              x: .value("Flipper Length", penguin.flipperLength),
              y: .value("Weight", penguin.weight),
              z: .value("Beak Length", penguin.beakLength)
            )
            .foregroundStyle(by: .value("Species", penguin.species))
          }
          .chart3DPose($pose)
          .chart3DCameraProjection(.perspective)
          .chartXAxisLabel("Flipper Length (mm)")
          .chartYAxisLabel("Weight (kg)")
          .chartZAxisLabel("Beak Length (mm)")
          .chartXScale(domain: 160...240, range: -0.5...0.5)
          .chartYScale(domain: 2...7, range: -0.5...0.5)
          .chartZScale(domain: 30...60, range: -0.5...0.5)
          .chartXAxis {
            AxisMarks(values: [160, 180, 200, 220, 240]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
          .chartYAxis {
            AxisMarks(values: [2, 3, 4, 5, 6, 7]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
          .chartZAxis {
            AxisMarks(values: [30, 40, 50, 60]) {
              AxisTick()
              AxisGridLine()
              AxisValueLabel()
            }
          }
        }
      }
    • 9:24 - Customize the surface styles for a sinc function

      // Customize the surface styles for a sinc function
      
      import SwiftUI
      import Charts
      
      struct SurfacePlotChart: View {
        var body: some View {
          Chart3D {
            SurfacePlot(x: "X", y: "Y", z: "Z") { x, z in
              let h = hypot(x, z)
              return sin(h) / h
            }
          }
          .chartXScale(domain: -10...10, range: -0.5...0.5)
          .chartZScale(domain: -10...10, range: -0.5...0.5)
          .chartYScale(domain: -0.23...1, range: -0.5...0.5)
        }
      }
    • 9:29 - Customize the surface styles for a sinc function (EllipticalGradient)

      // Customize the surface styles for a sinc function
      
      import SwiftUI
      import Charts
      
      struct SurfacePlotChart: View {
        var body: some View {
          Chart3D {
            SurfacePlot(x: "X", y: "Y", z: "Z") { x, z in
              let h = hypot(x, z)
              return sin(h) / h
            }
            .foregroundStyle(EllipticalGradient(colors: [.red, .orange, .yellow, .green, .blue, .indigo, .purple]))
          }
          .chartXScale(domain: -10...10, range: -0.5...0.5)
          .chartZScale(domain: -10...10, range: -0.5...0.5)
          .chartYScale(domain: -0.23...1, range: -0.5...0.5)
        }
      }
    • 9:38 - Customize the surface styles for a sinc function (heightBased)

      // Customize the surface styles for a sinc function
      
      import SwiftUI
      import Charts
      
      struct SurfacePlotChart: View {
        var body: some View {
          Chart3D {
            SurfacePlot(x: "X", y: "Y", z: "Z") { x, z in
              let h = hypot(x, z)
              return sin(h) / h
            }
            .foregroundStyle(.heightBased)
          }
          .chartXScale(domain: -10...10, range: -0.5...0.5)
          .chartZScale(domain: -10...10, range: -0.5...0.5)
          .chartYScale(domain: -0.23...1, range: -0.5...0.5)
        }
      }
    • 9:47 - Customize the surface styles for a sinc function (normalBased)

      // Customize the surface styles for a sinc function
      
      import SwiftUI
      import Charts
      
      struct SurfacePlotChart: View {
        var body: some View {
          Chart3D {
            SurfacePlot(x: "X", y: "Y", z: "Z") { x, z in
              let h = hypot(x, z)
              return sin(h) / h
            }
            .foregroundStyle(.normalBased)
          }
          .chartXScale(domain: -10...10, range: -0.5...0.5)
          .chartZScale(domain: -10...10, range: -0.5...0.5)
          .chartYScale(domain: -0.23...1, range: -0.5...0.5)
        }
      }

Developer Footer

  • ビデオ
  • WWDC25
  • Swift Chartsの3次元変換
  • メニューを開く メニューを閉じる
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    メニューを開く メニューを閉じる
    • アクセシビリティ
    • アクセサリ
    • App Extension
    • App Store
    • オーディオとビデオ(英語)
    • 拡張現実
    • デザイン
    • 配信
    • 教育
    • フォント(英語)
    • ゲーム
    • ヘルスケアとフィットネス
    • アプリ内課金
    • ローカリゼーション
    • マップと位置情報
    • 機械学習
    • オープンソース(英語)
    • セキュリティ
    • SafariとWeb(英語)
    メニューを開く メニューを閉じる
    • 英語ドキュメント(完全版)
    • 日本語ドキュメント(一部トピック)
    • チュートリアル
    • ダウンロード(英語)
    • フォーラム(英語)
    • ビデオ
    Open Menu Close Menu
    • サポートドキュメント
    • お問い合わせ
    • バグ報告
    • システム状況(英語)
    メニューを開く メニューを閉じる
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles(英語)
    • フィードバックアシスタント
    メニューを開く メニューを閉じる
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program(英語)
    • News Partner Program(英語)
    • Video Partner Program(英語)
    • セキュリティ報奨金プログラム(英語)
    • Security Research Device Program(英語)
    Open Menu Close Menu
    • Appleに相談
    • Apple Developer Center
    • App Store Awards(英語)
    • Apple Design Awards
    • Apple Developer Academy(英語)
    • WWDC
    Apple Developerアプリを入手する
    Copyright © 2025 Apple Inc. All rights reserved.
    利用規約 プライバシーポリシー 契約とガイドライン