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.7k
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
なぜAI任せのゲームは面白くならないのか?
hirohasuyoutube
0
280
AIは推し活である。
kurazuuuuuu
2
1k
Antigravity SDK for the Java Developer
glaforge
0
230
「今盗んで、後で解く」に備える ― AWSのポスト量子暗号入門
yama3133
2
270
AI駆動開発で仕様はどこまで書くべきか? ― 人とAIの責務境界から考える開発プロセスの実践
takahiromatsui
1
220
セルフサービスのオブザーバビリティ基盤をOpenTelemetryで作る / Building a Self-Service Observability Platform with OpenTelemetry
ymotongpoo
3
460
AWS DevOps Agent スキルをつかいこなそう / Master AWS DevOps Agent Skills
kinunori
2
620
Snowflake Horizon Catalog と Apache Iceberg で作る オープンなデータ基盤
kitagawaz
0
320
いちAWSエンジニアのAI活用を振り返る #devio2026 / devio osaka 2026 kawahara
masahirokawahara
1
270
2026-09-26 Platform Engineering Kaigi 2026 インフラとアプリの境界線と委譲の設計 / Drawing the Infra and App Line
masasuzu
0
440
形式手法を使って仕様をコーディングしよう
mikanichinose
0
120
顧客の成果創出とプロダクトの成長を 両立するためのFDE
sansantech
PRO
0
420
Featured
See All Featured
The browser strikes back
jonoalderson
0
1.7k
Un-Boring Meetings
codingconduct
0
430
Crafting Experiences
bethany
1
360
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
470
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
480
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
560
Technical Leadership for Architectural Decision Making
baasie
3
580
A Soul's Torment
seathinner
8
3.7k
HDC tutorial
michielstock
2
920
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
690
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
550
Deep Space Network (abreviated)
tonyrice
0
330
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