Slide 1

Slide 1 text

CGAffineTransform ࣮ફೖ໳ for BUKURO.swift x AKIBA.swift ߹ಉษڧձ

Slide 2

Slide 2 text

override init() { super.init() emplyedBy = "MAGES. 5pb. Game div" job = "iOS Developer" twitter = "@lovee" Qiita = "@lovee" github = "el-hoshino" additionalInfo = "HITMAN͸ΑϓϨΠ͍ͨ͠" class Speaker: Developer { } }

Slide 3

Slide 3 text

ςʔϚ͕ܾ·Δ·ͰͷาΈ

Slide 4

Slide 4 text

ςʔϚ͕ܾ·Δ·ͰͷาΈ

Slide 5

Slide 5 text

ςʔϚ͕ܾ·Δ·ͰͷาΈ

Slide 6

Slide 6 text

ςʔϚ͕ܾ·Δ·ͰͷาΈ

Slide 7

Slide 7 text

ςʔϚ͕ܾ·Δ·ͰͷาΈ ͳʹ࿩ͤ͹͍͍͔શવΘ͔ΒΜ! ͍ܰϊϦͰςʔϚΛܾΊͯ͠·͕ͬͨ

Slide 8

Slide 8 text

Now Loading... Α͠ɺ͜Ε࡞Ζ͏ɻ ※ը໘͸ΠϝʔδͰ͢ɻ ※ঁͷࢠͷը૾͸ https://www.ac-illust.com/main/detail.php?id=121046 ͔Βμ΢ϯϩʔυͨ͠΋ͷͰ͢ɻ

Slide 9

Slide 9 text

਺ֶλΠϜ

Slide 10

Slide 10 text

਺ֶλΠϜ

Slide 11

Slide 11 text

਺ֶλΠϜ

Slide 12

Slide 12 text

਺ֶλΠϜ

Slide 13

Slide 13 text

਺ֶλΠϜ

Slide 14

Slide 14 text

਺ֶλΠϜ

Slide 15

Slide 15 text

਺ֶλΠϜ ಉ͡ ٯ֯౓

Slide 16

Slide 16 text

਺ֶλΠϜ y

Slide 17

Slide 17 text

਺ֶλΠϜ y z 0 D 6?C 8 0 ) 5 = 0 1

Slide 18

Slide 18 text

਺ֶλΠϜ y z 0 D 6?C 8 0 ) 5 = 0 1 *" +

Slide 19

Slide 19 text

਺ֶλΠϜ y z 0 D 6?C 8 0 ) 5 = 0 1 7? 0 ' 0 ' 7?

Slide 20

Slide 20 text

਺ֶλΠϜ y z 0 D 6?C 8 0 ) 5 = 0 ' 7? 7? 0 '

Slide 21

Slide 21 text

਺ֶλΠϜ y z 0 D 6?C 8 0 ) 5 = 0 ' 7? 7? 0 ' 0 ' x 5 0 ' 0 ' ' ' 0 ' 7? ೘࢘倔ඔƂ✣Ƒź✣ ţƄŘ₍₍ ง盲ȼ盲 ว⁾⁾ţƄŘ

Slide 22

Slide 22 text

਺ֶλΠϜ y z 0 D 6?C 8 0 ) 5 = 0 ' 7? 7? 0 ' 0 ' x 5 0 '

Slide 23

Slide 23 text

਺ֶλΠϜ y z 0 D 6?C 8 0 ) 5 = 0 ' 7? 7? 0 ' 0 ' x 5 0 ' C r 0 +-( 2 0 2 0 0 0 +-( 0 3 58 5

Slide 24

Slide 24 text

਺ֶλΠϜ y z 0 D 6?C 8 0 ) 5 = 0 ' 7? 7? 0 ' 0 ' x 5 0 ' +-( 0 ) 0 ' )

Slide 25

Slide 25 text

਺ֶλΠϜ y z 0 D 6?C 8 0 ) 0 ' ) 5 = 0 ' 7? 7? 0 ' 0 ' x 5 0 ' +-( 0 มܗઃఆ쏤쏎쏧ɿ มܗج४఺쏕Ұ൪Լ ௕쎻쏕ݩ쏔 DPT К ഒ쏑쏐쏱 ճస֯౓쏕 К

Slide 26

Slide 26 text

ίʔσΟϯάλΠϜ มܗઃఆ쏤쏎쏧ɿ มܗج४఺쏕Ұ൪Լ ௕쎻쏕ݩ쏔 DPT К ഒ쏑쏐쏱 ճస֯౓쏕К // ϕʔεϏϡʔΛ࡞Δ let view = UIView(frame: CGRect(x: 0, y: 0, width: 480, height: 640)) view.backgroundColor = .white // ը૾Λදࣔ͢ΔϏϡʔΛ࡞Δ let image = #imageLiteral(resourceName: "girl.png") let imageView = UIImageView(image: image) // ը૾ϏϡʔΛઃఆ͢Δ imageView.layer.anchorPoint.y = 1 imageView.center = CGPoint(x: 240, y: 640) view.addSubview(imageView) // ը૾ϏϡʔΛมܗͤ͞Δ imageView.transform = imageView.transform.rotated(by: .pi / -12) imageView.transform = imageView.transform.scaledBy(x: 1, y: 1 / cos(.pi / -12)) 5*14transform쏸ઃఆ쎽쏅UIView쏕௚઀frame쏸ઃఆ쎿쏱쏔쏍쏕쏐쎵ɺ ୅쏵쏰쏑center쏎bounds.size쏸ઃఆ쎿쏱쎹쏎ɻ

Slide 27

Slide 27 text

DEMO

Slide 28

Slide 28 text

.transform.rotated(by: .pi / -3) .transform.scaledBy(x: 1, y: 1 / cos(.pi / -3)) .transform.scaledBy(x: 1, y: 1 / cos(.pi / -3)) .transform.rotated(by: .pi / -3)

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

܅쏐쏹쎱 ࣸਅ쏎ҧ쏵쏐쎪ʁ

Slide 31

Slide 31 text

extension UIView { //... open var transform: CGAffineTransform // default is CGAffineTransformIdentity. animatable } ͦ΋ͦ΋ΞϑΟϯม׵ͬͯԿ"

Slide 32

Slide 32 text

public struct CGAffineTransform { public var a: CGFloat public var b: CGFloat public var c: CGFloat public var d: CGFloat public var tx: CGFloat public var ty: CGFloat public init() public init(a: CGFloat, b: CGFloat, c: CGFloat, d: CGFloat, tx: CGFloat, ty: CGFloat) } ͳΔ΄ͲɺΘ͔ΒΜ! શͬવΘ͔Μͳ͍ΑʂabcdͬͯͳΜͳͷʁͳΜͰ͍͖ͳΓtxty͕ग़ͯ͘ΔΜͩΑʂ scaleͱ͔rotateͱ͔Ͳ͜ߦͬͨΜͩΑʂ͜Ε͡ΌͲ͏΍ͬͯมܗͤͯ͞Δ͔Θ͔Μ ͳ͍ΑʂΞϑΟϯม׵ͷ͜ͱ͸ੲ͔ΒԿҰͭɺ͜ΕͬΆͬͪ΋ɺΘ͔Μͳ͍ͷΑʔʂ

Slide 33

Slide 33 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ O P(x, y) x y ΞϑΟϯม׵ O P'(x', y') x' y' 0 5 6 0 7 8

Slide 34

Slide 34 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ O P(x, y) x y ΞϑΟϯม׵ O P'(x, y) x y 5 0 ) 6 0 ( 0 ( 7 0 ( 8 0 ) 0 ( 0 ) ( ( 0 ( ) ( 0 0 CGAffineTransform.identity 0 5 6 0 7 8

Slide 35

Slide 35 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ O P(x, y) x y ΞϑΟϯม׵ 5 0 ) 6 0 ( 0 ) 7 0 ( 8 0 ) 0 0 ) ( ) 0 ( ) 0 ) 0 CGAffineTransform(translationX: t1, y: t2) 0 5 6 0 7 8 O P'(x+t1, y+t2 ) x y t1 t2

Slide 36

Slide 36 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ O P(x, y) x y ΞϑΟϯม׵ 5 0 ) 6 0 ( 0 ( 7 0 ( 8 0 0 ( 0 ) ( ( 0 ( ( 0 ) 0 CGAffineTransform(scaleX: s1, y: s2) 0 5 6 0 7 8 O P'(s1x, s2y) x y s1x s2y

Slide 37

Slide 37 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ O P(x, y) x y ΞϑΟϯม׵ 5 0 7? 6 0 0 ( 7 0 8 0 7? 0 ( 0 7? ( 0 7? ( CGAffineTransform(rotationAngle: theta) 0 5 6 0 7 8 O P'(x', y') x y x' y' φ 0 ' 7? 0 ' θ 0 7? 0 7? 7? 0 7? 7? 0 7? ⃪岳梃㡑؊▁㾶⹻䛧 0 0 7? 7? 0 7? 7? 0 7? ⃪岳梃㡑؊▁㾶⹻䛧

Slide 38

Slide 38 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ O P(x, y) x y ΞϑΟϯม׵ O P'(x', y') x' y' 0 5 6 0 7 8 &(')# $ % !

Slide 39

Slide 39 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ O P(x, y) x y ΞϑΟϯม׵ O P'(x', y') x' y' 0 5 6 0 7 8 (scaleX: 1, y: 2) (rotationAngle: .pi / 3) 5 0 ) 6 0 ( 0 ( 7 0 ( 8 0 0 ( 5 0 ( 6 0 ( /-- 0 ( 7 0 ( /-- 8 0 ( 0 ( 0 ) 0 ) 0 ) 0 0 ) + 0 ) /--

Slide 40

Slide 40 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ O P(x, y) x y ΞϑΟϯม׵ O P'(x', y') x' y' 0 5 6 0 7 8 (scaleX: 1, y: 2) (rotationAngle: .pi / 3) 5 0 ) 6 0 ( 0 ( 7 0 ( 8 0 0 ( 5 0 ( 6 0 ( /-- 0 ( 7 0 ( /-- 8 0 ( 0 ( 0 ( +-- 0 ) +-- 0 ) + 0 ) /-- 0 ( +-- 0 .+ 0 ) 0 )

Slide 41

Slide 41 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ O P(x, y) x y ΞϑΟϯม׵ O P'(x', y') x' y' 0 5 6 0 7 8 scale ͱ rotate ͷॱ൪ަ׵ͨ͠Β
 ҧ͏݁Ռʹͳͬͨ! 0 ) + 0 ) /-- 0 ( +-- 0 .+

Slide 42

Slide 42 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ O 0 5 6 0 7 8

Slide 43

Slide 43 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ O 0 5 6 0 7 8 scale

Slide 44

Slide 44 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ O 0 5 6 0 7 8 rotate

Slide 45

Slide 45 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ 0 5 6 0 7 8 O O

Slide 46

Slide 46 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ 0 5 6 0 7 8 O rotate O

Slide 47

Slide 47 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ 0 5 6 0 7 8 O O scale

Slide 48

Slide 48 text

O ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ 0 5 6 0 7 8 &(')# ! O

Slide 49

Slide 49 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ 0 5 6 0 7 8 5 6 7 8 0

Slide 50

Slide 50 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ 0 5 6 0 7 8 5 6 7 8 0 ) ( ( ) )

Slide 51

Slide 51 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ 0 5 6 0 7 8 5 6 7 8 0 ) ( ( ) ) 5 6 7 8 ( ( )

Slide 52

Slide 52 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ 0 5 6 0 7 8 5 6 7 8 0 ) ( ( ) ) 5 6 7 8 ( ( ) ߦྻͷֻ͚ࢉ͕࢖͑Δ ߦྻͷֻ͚ࢉ΋ަ׵ଇ͕ޮ͔ͳ͍ ※ৄ͘͠͸ https://ja.wikipedia.org/wiki/ߦྻͷ৐๏ Λ͝ΒΜ͍ͩ͘͞ɻ

Slide 53

Slide 53 text

ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ 0 5 6 0 7 8 // false transform.rotated(by: .pi) == transform * CGAffineTransform(rotationAngle: .pi) // true transform.rotated(by: .pi) == CGAffineTransform(rotationAngle: .pi) * transform CGAffineTransform ͷ xxedBy(_:) ܥ໋ྩͷ ॱ൪ʹ͸ཁ஫ҙ!

Slide 54

Slide 54 text

.transform.rotated(by: .pi / -3) .transform.scaledBy(x: 1, y: 1 / cos(.pi / -3)) .transform.scaledBy(x: 1, y: 1 / cos(.pi / -3)) .transform.rotated(by: .pi / -3)

Slide 55

Slide 55 text

ʲ࿕ใʳFramework࡞Γ·ͨ͠ʂ

Slide 56

Slide 56 text

Danbo

Slide 57

Slide 57 text

DEMO

Slide 58

Slide 58 text

ϑΝΠφϧϛογϣϯɿ ΞχϝʔγϣϯΛ࡞Δ

Slide 59

Slide 59 text

ίʔσΟϯάλΠϜ 쏻쐤쐺쎦쐐쑀쑌ઃఆ쏤쏎쏧ɿ Bࠨ쏑౗쎿 Cݩ쏑໭쏱 Dӈ쏑౗쎿 EDdCdB쏑쑃쐩쎦쐒 FCdDdE쏸쑄쎦쐰

Slide 60

Slide 60 text

ίʔσΟϯάλΠϜ 쏻쐤쐺쎦쐐쑀쑌ઃఆ쏤쏎쏧ɿ Bࠨ쏑౗쎿 Cݩ쏑໭쏱 Dӈ쏑౗쎿 EDdCdB쏑쑃쐩쎦쐒 FCdDdE쏸쑄쎦쐰 let rotation: Rotation = .degree(15) let duration: TimeInterval = 0.5 func rotate(_ view: UIView, onGroundBy rotation: Rotation) { view.danbo.transform { $0 .reset() .scaleBy(dy: 1 / cos(rotation)) .rotate(by: rotation) .commit() } } func reset(_ view: UIView) { view.danbo.transform { $0 .reset() .commit() } } func loop() { UIView.animateKeyframes(withDuration: duration * 2, delay: 0, options: [.calculationModeLinear, .autoreverse, .repeat], animations: { UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.5, animations: { reset(imageView) }) UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.5, animations: { rotate(imageView, onGroundBy: rotation) }) }, completion: nil) } func animate() { UIView.animate(withDuration: duration, delay: 0, options: .curveEaseOut, animations: { rotate(imageView, onGroundBy: -rotation) }) { (_) in loop() } } animate()

Slide 61

Slide 61 text

DEMO