Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Pathを活用してSwift Chartsの限界を超えろ / create-graph-usi...
Search
Fuya Yamada
July 14, 2023
Technology
1.8k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Pathを活用してSwift Chartsの限界を超えろ / create-graph-using-path
Fuya Yamada
July 14, 2023
More Decks by Fuya Yamada
See All by Fuya Yamada
iOS開発におけるCopilot For XcodeとCode Completion / copilot for xcode
fuyan777
1
3.3k
Other Decks in Technology
See All in Technology
20年間 SNS サービス「GREE」 を支えた技術の刷新と、長期運用サービスの Kubernetes へのリアーキテクト
gree_tech
PRO
0
110
CSS2026:OWS研究会・招待講演「世界観を、実装する」
atsush1_sada
2
220
FinOps Agentが生んだ技術負債:コスト自動調査の落とし穴と解消までの道のり
oasis1994liveforever
3
250
Tofu-Controller lightning talk @ Containerday 2026
gionn
0
180
How to Design Configuration for Rails Applications
willnet
1
1.1k
ソフトウェア ファクトリー - 再現性のあるソフトウェアの工場づくり / Software factory
iktakahiro
7
5.3k
AWSDirectConnectの構築の進め方を整理してみた
masa_my
1
150
DevelopersIO 2026 Tokyo 現時点の衛星通信サービスの現状を整理してみる
maroon1st
0
180
AWS DevOps Agentはどこまで任せられるか 〜機能の現在地と、機能拡張の実践〜
nyankotaro
0
120
How to teach your AI Agent with Agent skills
linedevth
0
100
macOS Golden Gate 時代のMac管理
tategami
0
130
フィンテック養成勉強会#68
finengine
0
210
Featured
See All Featured
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.3k
Practical Orchestrator
shlominoach
192
12k
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
Abbi's Birthday
coloredviolet
4
10k
Embracing the Ebb and Flow
colly
88
5.2k
First, design no harm
axbom
PRO
2
1.3k
How to Think Like a Performance Engineer
csswizardry
28
2.9k
Producing Creativity
orderedlist
PRO
348
41k
Into the Great Unknown - MozCon
thekraken
41
2.8k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
2
2.1k
So, you think you're a good person
axbom
PRO
2
2.2k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
4
1.2k
Transcript
PathΛ׆༻ͯ͠ Swift ChartsͷݶքΛ͑Ζ גࣜձࣾZOZO ϒϥϯυιϦϡʔγϣϯ։ൃຊ෦ / ϑϩϯτΤϯυ෦ WEAR iOSϒϩοΫ ࢁా
෨ Copyright © ZOZO, Inc.
© ZOZO, Inc. גࣜձࣾZOZO ϒϥϯυιϦϡʔγϣϯ։ൃຊ෦ / ϑϩϯτΤϯυ෦ WEAR iOSϒϩοΫ ࢁా
෨ (Fuya Yamada) ελόʹߦͬͯɺۤΈʹ͑ͳ͕Β ҿΉίʔώʔ͕͖ ʢຊίίΞ͕ྑ͍ʣ
© ZOZO, Inc. ຊ͢͜ͱ PathΛ׆༻ͯ͠ Swift Chartsʹͳ͍άϥϑΛ࡞ͯ͠Έͨ ର Կ͔͠ΒSwiftUIΛѻ͏ਓ
© ZOZO, Inc. ΞδΣϯμ • Swift Chartsͷհ • Swift Chartsͷݶք
• PathΛ༻͍ͯݶքಥഁ͢Δํ๏ • Swift Chartsʹͳ͍άϥϑͷ࣮ྫ • ·ͱΊ 4
© ZOZO, Inc. Swift Chartsͷհ Swift Chartsͱʁ ◦ iOS 16͔Βར༻Ͱ͖Δ
SwiftUI ͷάϥϑඳըϥΠϒϥϦ ◦ ɺંΕઢɺࢄਤΛ͡Ίͱ͢Δ6छྨͷඳը͕Մೳ 5
© ZOZO, Inc. Swift Chartsͷհ 6 ຌྫͷՃ ਫฏઢͷදࣔ ͜ΜͳΧελϚΠζ͕Ͱ͖·͢
© ZOZO, Inc. Swift Chartsͷݶքʢ՝ʣ ԁάϥϑϨʔμʔνϟʔτඇରԠ 7 Swift ChartsͰαϙʔτ͞Ε͍ͯͳ͍άϥϑಠࣗͰ࡞Δඞཁ͕͋Δ https://chachart.net/radar
© ZOZO, Inc. PathΛ༻͍ͯݶքಥഁ͢Δํ๏ PathΛ׆༻ͯ͠άϥϑΛ࡞ Pathͱʁ ➔ ઢɺۂઢͳͲΛΈ߹Θͤͯෳࡶͳܗঢ়Λ࡞͢ΔͨΊͷߏମ ϝϦοτ ➔
දݱͷࣗ༝ͷߴ͞ 8 Path { path in ... } ChartsͰදݱͰ͖ͳ͔ͬͨϨΠΞτΛ࣮ݱՄೳ
© ZOZO, Inc. PathͷͰ͖Δ͜ͱ Path { path in path.move(to: CGPoint(x:
0, y: 0)) path.addLine(to: CGPoint(x: 100, y: 0)) } 9 path.closeSubpath() // ύεΛด͡Δ path.addArc( center: CGPoint(x: 100, y: 100), radius: 100, startAngle: .degrees(-90), endAngle: .degrees(0), clockwise: false ) ࢝↓
© ZOZO, Inc. ShapeϓϩτίϧΛར༻ ඳըՄೳͳਤܗΛఆٛ͢ΔͨΊͷΠϯλʔϑΣʔε PathͰԁάϥϑΛ࣮ 10 public protocol Shape
: Animatable, View { func path(in rect: CGRect) -> Path } Animatable ҙͷ͕มԽͨ࣌͠ɺ ΞχϝʔγϣϯΛద༻ path(in:)ϝιου ༩͑ΒΕͨCGRect (ඳըྖҬ) ʹඳը͢ΔPath
© ZOZO, Inc. PathͰԁάϥϑΛ࣮ 11 ࡞Γ͍ͨͷ ԁހͷ࡞ 3ͭͷΈ߹Θͤ ArcView
© ZOZO, Inc. struct ArcView: Shape { var startAngle: Double
var endAngle: Double var animatableData: Double { get { endAngle } set { endAngle = newValue } } func path(in rect: CGRect) -> Path { let rotationAdjustment = Angle(degrees: 90) let adjustedStartAngle = Angle(degrees: startAngle) - rotationAdjustment let adjustedEndAngle = Angle(degrees: endAngle) - rotationAdjustment return Path { p in p.addArc( center: CGPoint(x: rect.midX, y: rect.midY), radius: rect.width / 2, startAngle: adjustedStartAngle, endAngle: adjustedEndAngle, clockwise: false ) p.addLine(to: CGPoint(x: rect.midX, y: rect.midY)) p.closeSubpath() } } } ArcViewͷ࣮ - શମ૾ 12 ArcView
© ZOZO, Inc. struct ArcView: Shape { var startAngle: Double
var endAngle: Double var animatableData: Double { get { endAngle } set { endAngle = newValue } } func path(in rect: CGRect) -> Path { let rotationAdjustment = Angle(degrees: 90) let adjustedStartAngle = Angle(degrees: startAngle) - rotationAdjustment let adjustedEndAngle = Angle(degrees: endAngle) - rotationAdjustment return Path { p in p.addArc( center: CGPoint(x: rect.midX, y: rect.midY), radius: rect.width / 2, startAngle: adjustedStartAngle, endAngle: adjustedEndAngle, clockwise: false ) p.addLine(to: CGPoint(x: rect.midX, y: rect.midY)) p.closeSubpath() } } } ArcViewͷ࣮ AnimatableData ϓϩύςΟ e.g. endAngleʢऴྃ֯ʣΛ ࢦఆ͢ΔͱArcViewͷׂ߹͕ ૿Ճ͢ΔΞχϝʔγϣϯ var animatableData: Double { get { endAngle } set { endAngle = newValue } } 13
© ZOZO, Inc. struct ArcView: Shape { var startAngle: Double
var endAngle: Double var animatableData: Double { get { endAngle } set { endAngle = newValue } } func path(in rect: CGRect) -> Path { let rotationAdjustment = Angle(degrees: 90) let adjustedStartAngle = Angle(degrees: startAngle) - rotationAdjustment let adjustedEndAngle = Angle(degrees: endAngle) - rotationAdjustment return Path { p in p.addArc( center: CGPoint(x: rect.midX, y: rect.midY), radius: rect.width / 2, startAngle: adjustedStartAngle, endAngle: adjustedEndAngle, clockwise: false ) p.addLine(to: CGPoint(x: rect.midX, y: rect.midY)) p.closeSubpath() } } } ArcViewͷ࣮ 0Λ্෦ʹ͢ΔͨΊʹ ֯ௐ let rotationAdjustment = Angle(degrees: 90) let adjustedStartAngle = Angle(degrees: startAngle) - rotationAdjustment let adjustedEndAngle = Angle(degrees: endAngle) - rotationAdjustment 14 0° 0°
© ZOZO, Inc. struct ArcView: Shape { var startAngle: Double
var endAngle: Double var animatableData: Double { get { endAngle } set { endAngle = newValue } } func path(in rect: CGRect) -> Path { let rotationAdjustment = Angle(degrees: 90) let adjustedStartAngle = Angle(degrees: startAngle) - rotationAdjustment let adjustedEndAngle = Angle(degrees: endAngle) - rotationAdjustment return Path { p in p.addArc ( center: CGPoint(x: rect.midX, y: rect.midY), radius: rect.width / 2, startAngle: adjustedStartAngle, endAngle: adjustedEndAngle, clockwise: false ) p.addLine(to: CGPoint(x: rect.midX, y: rect.midY)) p.closeSubpath() } } } ArcViewͷ࣮ ԁހͷඳը addArc + addLine & close return Path { p in p.addArc ( center: CGPoint(x: rect.midX, y: rect.midY), radius: rect.width / 2, startAngle: adjustedStartAngle, endAngle: adjustedEndAngle, clockwise: false ) p.addLine(to: CGPoint(x: rect.midX, y: rect.midY)) p.closeSubpath() } 15
© ZOZO, Inc. PathͰԁάϥϑΛ࣮ 16 ԁάϥϑ struct PieChartView: View {
var body: some View { ZStack { ArcView(startAngle: 0, endAngle: 360) .fill(Color("green")) ArcView(startAngle: 0, endAngle: 250) .fill(Color("blue")) ArcView(startAngle: 0, endAngle: 140) .fill(Color("red")) } } }
© ZOZO, Inc. PathͰԁάϥϑΛ࣮ 17 ςΩετࠞͥͯ ͜Μͳ͜ͱͰ͖Δ
© ZOZO, Inc. ͞ΒʹPathͰϨʔμʔνϟʔτ࣮Մೳ • addLine(to:), move(to:) ͷΈ • ଟ֯ܗͷ֤Λܭࢉ͠ɺ
Λͭͳ͛ͯଟ֯ܗΛඳը 18
© ZOZO, Inc. ͞ΒʹPathͰϨʔμʔνϟʔτ࣮Մೳ 19 ϕʔεͷViewͷ࡞ํ๏Λ ͬ͘͟Γ͝հ PolygonShape
© ZOZO, Inc. struct PolygonShape: Shape { let sides: Int
// ลͷ func path(in rect: CGRect) -> Path { let centerX = rect.width / 2 let centerY = rect.height / 2 let radius = min(rect.width, rect.height) / 2 let angle = .pi * 2 / Double(sides) let offsetAngle = -(Double.pi / 2) // 0Λ্෦ʹ͢ΔͨΊʹ֯ௐ return Path { path in for index in 0..<sides { let currentAngle = angle * Double(index) + offsetAngle let x = centerX + cos(currentAngle) * radius let y = centerY + sin(currentAngle) * radius if index == 0 { path.move(to: CGPoint(x: x, y: y)) } else { path.addLine(to: CGPoint(x: x, y: y)) } } path.closeSubpath() } } } Ϩʔμʔνϟʔτ - શମ૾ 20
© ZOZO, Inc. struct PolygonShape: Shape { let sides: Int
// ลͷ func path(in rect: CGRect) -> Path { let centerX = rect.width / 2 let centerY = rect.height / 2 let radius = min(rect.width, rect.height) / 2 let angle = .pi * 2 / Double(sides) let offsetAngle = -(Double.pi / 2) // 0Λ্෦ʹ͢ΔͨΊʹ֯ௐ return Path { path in for index in 0..<sides { let currentAngle = angle * Double(index) + offsetAngle let x = centerX + cos(currentAngle) * radius let y = centerY + sin(currentAngle) * radius if index == 0 { path.move(to: CGPoint(x: x, y: y)) } else { path.addLine(to: CGPoint(x: x, y: y)) } } path.closeSubpath() } } } Ϩʔμʔνϟʔτ - શମ૾ 21
© ZOZO, Inc. struct PolygonShape: Shape { let sides: Int
// ลͷ func path(in rect: CGRect) -> Path { let centerX = rect.width / 2 let centerY = rect.height / 2 let radius = min(rect.width, rect.height) / 2 let angle = .pi * 2 / Double(sides) let offsetAngle = -(Double.pi / 2) // 0Λ্෦ʹ͢ΔͨΊʹ֯ௐ return Path { path in for index in 0..<sides { let currentAngle = angle * Double(index) + offsetAngle let x = centerX + cos(currentAngle) * radius let y = centerY + sin(currentAngle) * radius if index == 0 { path.move(to: CGPoint(x: x, y: y)) } else { path.addLine(to: CGPoint(x: x, y: y)) } } path.closeSubpath() } } } Ϩʔμʔνϟʔτ - શମ૾ 22 ลͷΛఆٛ let sides: Int // ลͷ
© ZOZO, Inc. struct PolygonShape: Shape { let sides: Int
// ลͷ func path(in rect: CGRect) -> Path { let centerX = rect.width / 2 let centerY = rect.height / 2 let radius = min(rect.width, rect.height) / 2 let angle = .pi * 2 / Double(sides) let offsetAngle = -(Double.pi / 2) // 0Λ্෦ʹ͢ΔͨΊʹ֯ௐ return Path { path in for index in 0..<sides { let currentAngle = angle * Double(index) + offsetAngle let x = centerX + cos(currentAngle) * radius let y = centerY + sin(currentAngle) * radius if index == 0 { path.move(to: CGPoint(x: x, y: y)) } else { path.addLine(to: CGPoint(x: x, y: y)) } } path.closeSubpath() } } } Ϩʔμʔνϟʔτ - શମ૾ 23
© ZOZO, Inc. struct PolygonShape: Shape { let sides: Int
// ลͷ func path(in rect: CGRect) -> Path { let centerX = rect.width / 2 let centerY = rect.height / 2 let radius = min(rect.width, rect.height) / 2 let angle = .pi * 2 / Double(sides) let offsetAngle = -(Double.pi / 2) // 0Λ্෦ʹ͢ΔͨΊʹ֯ௐ return Path { path in for index in 0..<sides { let currentAngle = angle * Double(index) + offsetAngle let x = centerX + cos(currentAngle) * radius let y = centerY + sin(currentAngle) * radius if index == 0 { path.move(to: CGPoint(x: x, y: y)) } else { path.addLine(to: CGPoint(x: x, y: y)) } } path.closeSubpath() } } } Ϩʔμʔνϟʔτ - શମ૾ 24 Ҿ CGRect ͔Βத৺ɺܘɺ֯ͷࢉग़ let centerX = rect.width / 2 let centerY = rect.height / 2 let radius = min(rect.width, rect.height) / 2 let angle = .pi * 2 / Double(sides) let offsetAngle = -(Double.pi / 2)
© ZOZO, Inc. struct PolygonShape: Shape { let sides: Int
// ลͷ func path(in rect: CGRect) -> Path { let centerX = rect.width / 2 let centerY = rect.height / 2 let radius = min(rect.width, rect.height) / 2 let angle = .pi * 2 / Double(sides) let offsetAngle = -(Double.pi / 2) // 0Λ্෦ʹ͢ΔͨΊʹ֯ௐ return Path { path in for index in 0..<sides { let currentAngle = angle * Double(index) + offsetAngle let x = centerX + cos(currentAngle) * radius let y = centerY + sin(currentAngle) * radius if index == 0 { path.move(to: CGPoint(x: x, y: y)) } else { path.addLine(to: CGPoint(x: x, y: y)) } } path.closeSubpath() } } } Ϩʔμʔνϟʔτ - શମ૾ 25
© ZOZO, Inc. struct PolygonShape: Shape { let sides: Int
// ลͷ func path(in rect: CGRect) -> Path { let centerX = rect.width / 2 let centerY = rect.height / 2 let radius = min(rect.width, rect.height) / 2 let angle = .pi * 2 / Double(sides) let offsetAngle = -(Double.pi / 2) // 0Λ্෦ʹ͢ΔͨΊʹ֯ௐ return Path { path in for index in 0..<sides { let currentAngle = angle * Double(index) + offsetAngle let x = centerX + cos(currentAngle) * radius let y = centerY + sin(currentAngle) * radius if index == 0 { path.move(to: CGPoint(x: x, y: y)) } else { path.addLine(to: CGPoint(x: x, y: y)) } } path.closeSubpath() } } } Ϩʔμʔνϟʔτ - શମ૾ 26 ֤ͷ֯Λܭࢉ ࠷ॳͷͳΒύεͷ։࢝Λઃఆ ͦΕҎ֎ͳΒઢΛҾ͘ return Path { path in for index in 0..<sides { let currentAngle = angle * Double(index) + offsetAngle let x = centerX + cos(currentAngle) * radius let y = centerY + sin(currentAngle) * radius if index == 0 { path.move(to: CGPoint(x: x, y: y)) } else { path.addLine(to: CGPoint(x: x, y: y)) } } path.closeSubpath() }
© ZOZO, Inc. ͞ΒʹPathͰϨʔμʔνϟʔτ࣮Մೳ 27 PolygonShape ϕʔεͷView
© ZOZO, Inc. ͡Ό͋PathͰάϥϑͷ࡞ʹݶք͋Δͷʁʁ 2DͷඳըքͰݶքແ͍ʂʁʢFuyaௐʣ 28
© ZOZO, Inc. ·ͱΊ Swift ChartsͰαϙʔτ͞Ε͍ͯͳ͍άϥϑ PathΛ࣮ͬͯ͢Δ͜ͱ͕Մೳ 29 ৄ͍࣮͠ํ๏ͪ͜Β͔Β
https://github.com/Fuyan777/charts-sample
None