Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Bézier Curves
Search
Ben Scheirman
March 02, 2018
Programming
1
5.4k
Bézier Curves
Presented at try! Swift Tokyo 2018
Ben Scheirman
March 02, 2018
Tweet
Share
More Decks by Ben Scheirman
See All by Ben Scheirman
A Promise for a Better Future
subdigital
0
160
Buckets of Code
subdigital
0
2k
Building 5 Calls for iOS
subdigital
0
130
Swift on Linux
subdigital
1
860
tvOS Workshop
subdigital
1
150
Swift Solutions
subdigital
2
460
iOS 8 Networking
subdigital
4
930
iOS 8 App Extensions
subdigital
1
370
Effective Networking with iOS 8 and Swift
subdigital
4
1.7k
Other Decks in Programming
See All in Programming
Amazon Bedrock Knowledge Bases Hands-on
konny0311
0
150
複数チーム並行開発下でのコード移行アプローチ ~手動 Codemod から「生成AI 活用」への進化
andpad
0
170
Vueで学ぶデータ構造入門 リンクリストとキューでリアクティビティを捉える / Vue Data Structures: Linked Lists and Queues for Reactivity
konkarin
1
300
SUZURIの規約違反チェックにおけるクリエイタフィードバックの試⾏錯誤/Trial and Error in Creator Feedback for SUZURI's Terms of Service Violation Checks
ae14watanabe
1
150
知られているようで知られていない JavaScriptの仕様 4選
syumai
0
610
ノーコードからの脱出 -地獄のデスロード- / Escape from Base44
keisuke69
0
710
DartASTとその活用
sotaatos
2
130
予防に勝る防御なし(2025年版) - 堅牢なコードを導く様々な設計のヒント / Growing Reliable Code PHP Conference Fukuoka 2025
twada
PRO
39
12k
スタートアップを支える技術戦略と組織づくり
pospome
3
1.2k
アーキテクチャと考える迷子にならない開発者テスト
irof
8
3k
AIの弱点、やっぱりプログラミングは人間が(も)勉強しよう / YAPC AI and Programming
kishida
9
4.8k
「10分以内に機能を消せる状態」 の実現のためにやっていること
togishima
1
480
Featured
See All Featured
Thoughts on Productivity
jonyablonski
73
4.9k
Bash Introduction
62gerente
615
210k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.3k
The Power of CSS Pseudo Elements
geoffreycrofte
80
6.1k
Embracing the Ebb and Flow
colly
88
4.9k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
670
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
118
20k
Fireside Chat
paigeccino
41
3.7k
Principles of Awesome APIs and How to Build Them.
keavy
127
17k
Building an army of robots
kneath
306
46k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
127
54k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
231
22k
Transcript
Bézier Curves Ben Scheirman nsscreencast.com @subdigital
None
None
None
let path = UIBezierPath() path.move(to: startPoint) path.addCurve(to: endPoint, controlPoint1: c1,
controlPoint2: c2) context.addPath(path.cgPath) context.strokePath()
Control points?!
Paul de Casteljau
None
None
None
None
None
None
None
None
None
None
None
None
class BezierView : UIView { var startPoint: CGPoint? var endPoint:
CGPoint? var control1: CGPoint? var control2: CGPoint? ...
func drawPoint(_ context: CGContext, p: CGPoint, color: UIColor, radius: CGFloat)
{ color.setFill() context.addArc(center: p, radius: radius, startAngle: 0, endAngle: .pi * 2, clockwise: true) context.fillPath() }
Demo
class BezierView : UIView { var startPoint: CGPoint? var endPoint:
CGPoint? var control1: CGPoint? var control2: CGPoint? ...
class BezierView : UIView { var points: [CGPoint] ...
if points.count >= 2 { drawLinesBetween(context, points) }
func drawLinesBetween(_ context: CGContext, _ points: [CGPoint]) { }
func drawLinesBetween(_ context: CGContext, _ points: [CGPoint]) { points.first.flatMap {
context.move(to: $0) } points.dropFirst().forEach { context.addLine(to: $0 ) } context.setLineWidth(3) context.setLineDash(phase: 0, lengths: [2]) UIColor.lightGray.setStroke() context.strokePath() }
func drawLinesBetween(_ context: CGContext, _ points: [CGPoint]) { points.first.flatMap {
context.move(to: $0) } points.dropFirst().forEach { context.addLine(to: $0 ) } context.setLineWidth(3) context.setLineDash(phase: 0, lengths: [2]) UIColor.lightGray.setStroke() context.strokePath() }
func drawLinesBetween(_ context: CGContext, _ points: [CGPoint]) { points.first.flatMap {
context.move(to: $0) } points.dropFirst().forEach { context.addLine(to: $0 ) } context.setLineWidth(3) context.setLineDash(phase: 0, lengths: [2]) UIColor.lightGray.setStroke() context.strokePath() }
func drawLinesBetween(_ context: CGContext, _ points: [CGPoint]) { points.first.flatMap {
context.move(to: $0) } points.dropFirst().forEach { context.addLine(to: $0 ) } context.setLineWidth(3) context.setLineDash(phase: 0, lengths: [2]) UIColor.lightGray.setStroke() context.strokePath() if timeValue > 0 { interpolateBetween(context, points) } }
func interpolateBetween(_ context: CGContext, _ points: [CGPoint]) { guard points.count
>= 2 else { return } var interpolated: [CGPoint] = [] for i in 0 ..< points.count-1 { let p1 = points[i] let p2 = points[i+1] let t = p1.lerp(p2, t: timeValue) interpolated.append(t) drawPoint(context, p: t, color: .lightGray, radius: 6) } }
func interpolateBetween(_ context: CGContext, _ points: [CGPoint]) { guard points.count
>= 2 else { return } var interpolated: [CGPoint] = [] for i in 0 ..< points.count-1 { let p1 = points[i] let p2 = points[i+1] let t = p1.lerp(p2, t: timeValue) interpolated.append(t) drawPoint(context, p: t, color: .lightGray, radius: 6) } }
func interpolateBetween(_ context: CGContext, _ points: [CGPoint]) { guard points.count
>= 2 else { return } var interpolated: [CGPoint] = [] for i in 0 ..< points.count-1 { let p1 = points[i] let p2 = points[i+1] let t = p1.lerp(p2, t: timeValue) interpolated.append(t) drawPoint(context, p: t, color: .lightGray, radius: 6) } }
func interpolateBetween(_ context: CGContext, _ points: [CGPoint]) { guard points.count
>= 2 else { return } var interpolated: [CGPoint] = [] for i in 0 ..< points.count-1 { let p1 = points[i] let p2 = points[i+1] let t = p1.lerp(p2, t: timeValue) interpolated.append(t) drawPoint(context, p: t, color: .lightGray, radius: 6) } }
func interpolateBetween(_ context: CGContext, _ points: [CGPoint]) { guard points.count
>= 2 else { return } var interpolated: [CGPoint] = [] for i in 0 ..< points.count-1 { let p1 = points[i] let p2 = points[i+1] let t = p1.lerp(p2, t: timeValue) interpolated.append(t) drawPoint(context, p: t, color: .lightGray, radius: 6) } }
func interpolateBetween(_ context: CGContext, _ points: [CGPoint]) { guard points.count
>= 2 else { return } var interpolated: [CGPoint] = [] for i in 0 ..< points.count-1 { let p1 = points[i] let p2 = points[i+1] let t = p1.lerp(p2, t: timeValue) interpolated.append(t) drawPoint(context, p: t, color: .lightGray, radius: 6) } }
func interpolateBetween(_ context: CGContext, _ points: [CGPoint]) { guard points.count
>= 2 else { return } var interpolated: [CGPoint] = [] for i in 0 ..< points.count-1 { let p1 = points[i] let p2 = points[i+1] let t = p1.lerp(p2, t: timeValue) interpolated.append(t) drawPoint(context, p: t, color: .lightGray, radius: 6) } if interpolated.count >= 2 { drawLinesBetween(context, interpolated) } }
zip(sequence1, sequence2)
sequence1 Sequence2
sequence1 Sequence2 zip
sequence1 Sequence2 zip
sequence1 Sequence2 P1 P2 P3 P4 P5 P2 P3 P4
P5 zip
sequence1 Sequence2 P1 P2 P3 P4 P5 P2 P3 P4
P5 zip
func interpZip(points: [CGPoint]) -> (CGFloat) -> [CGPoint] { return {
t in let pairs = zip(points, points.dropFirst()) return pairs.map { pair in return lerp(pair.0, pair.1, t) } } }
func interpZip(points: [CGPoint]) -> (CGFloat) -> [CGPoint] { return {
t in let pairs = zip(points, points.dropFirst()) return pairs.map { pair in return lerp(pair.0, pair.1, t) } } }
func interpZip(points: [CGPoint]) -> (CGFloat) -> [CGPoint] { return {
t in let pairs = zip(points, points.dropFirst()) return pairs.map { pair in return lerp(pair.0, pair.1, t) } } }
func interpZip(points: [CGPoint]) -> (CGFloat) -> [CGPoint] { return {
t in let pairs = zip(points, points.dropFirst()) return pairs.map { pair in return pair.0.lerp(pair.1, t: timeValue) } } }
None
Rapid Feedback
Explore! Experiment!
Thank you ! Ben Scheirman nsscreencast.com @subdigital
Thank you ! Ben Scheirman nsscreencast.com @subdigital Ask me for
a sticker! ステッカーが欲しかったら話 しかけてください!
Thank you ! Ben Scheirman nsscreencast.com @subdigital Ask me for
a sticker! ステッカーが欲しかったら話 しかけてください!