Elvis Shi
May 15, 2017
1.4k

CGAffineTransform 実践入門

May 15, 2017

Transcript

2. override init() { super.init() emplyedBy = "MAGES. 5pb. Game div"

job = "iOS Developer" twitter = "@lovee" Qiita = "@lovee" github = "el-hoshino" additionalInfo = "HITMAN͸ΑϓϨΠ͍ͨ͠" class Speaker: Developer { } }

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

= 0 1 *" +
19. ਺ֶλΠϜ y z 0 D 6?C 8 0 ) 5

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

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

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

= 0 ' 7? 7? 0 ' 0 ' x 5 0 '   
23. ਺ֶλΠϜ 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
24. ਺ֶλΠϜ y z 0 D 6?C 8 0 ) 5

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

' ) 5 = 0 ' 7? 7? 0 ' 0 ' x 5 0 ' +-( 0 มܗઃఆ쏤쏎쏧ɿ  มܗج४఺쏕Ұ൪Լ  ௕쎻쏕ݩ쏔   DPT К   ഒ쏑쏐쏱  ճస֯౓쏕 К  
26. ίʔσΟϯάλΠϜ มܗઃఆ쏤쏎쏧ɿ มܗج४఺쏕Ұ൪Լ ௕쎻쏕ݩ쏔 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*14transform쏸ઃఆ쎽쏅UIView쏕௚઀frame쏸ઃఆ쎿쏱쏔쏍쏕쏐쎵ɺ ୅쏵쏰쏑center쏎bounds.size쏸ઃఆ쎿쏱쎹쏎ɻ

28. .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)
29. None

31. extension UIView { //... open var transform: CGAffineTransform // default

is CGAffineTransformIdentity. animatable } ͦ΋ͦ΋ΞϑΟϯม׵ͬͯԿ"
32. 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ͱ͔Ͳ͜ߦͬͨΜͩΑʂ͜Ε͡ΌͲ͏΍ͬͯมܗͤͯ͞Δ͔Θ͔Μ ͳ͍ΑʂΞϑΟϯม׵ͷ͜ͱ͸ੲ͔ΒԿҰͭɺ͜ΕͬΆͬͪ΋ɺΘ͔Μͳ͍ͷΑʔʂ
33. ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ O P(x, y) x y ΞϑΟϯม׵ O P'(x',

y') x' y' 0 5 6 0 7 8
34. ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ 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
35. ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ 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
36. ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ 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
37. ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ 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? ⃪岳梃㡑؊▁㾶⹻䛧
38. ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ O P(x, y) x y ΞϑΟϯม׵ O P'(x',

y') x' y' 0 5 6 0 7 8 &(')#  \$   % !
39. ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ 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 ) /--
40. ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ 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 )
41. ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ O P(x, y) x y ΞϑΟϯม׵ O P'(x',

y') x' y' 0 5 6 0 7 8 scale ͱ rotate ͷॱ൪ަ׵ͨ͠Β  ҧ͏݁Ռʹͳͬͨ! 0 ) + 0 ) /-- 0 ( +-- 0 .+

O

scale

! O

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

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

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

7 8 0 ) ( ( ) ) 5 6 7 8 ( ( ) ߦྻͷֻ͚ࢉ͕࢖͑Δ ߦྻͷֻ͚ࢉ΋ަ׵ଇ͕ޮ͔ͳ͍ ※ৄ͘͠͸ https://ja.wikipedia.org/wiki/ߦྻͷ৐๏ Λ͝ΒΜ͍ͩ͘͞ɻ
53. ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ 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(_:) ܥ໋ྩͷ ॱ൪ʹ͸ཁ஫ҙ!
54. .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)

60. ίʔσΟϯάλΠϜ 쏻쐤쐺쎦쐐쑀쑌ઃఆ쏤쏎쏧ɿ Bࠨ쏑౗쎿 Cݩ쏑໭쏱 Dӈ쏑౗쎿 EDdCdB쏑쑃쐩쎦쐒 FCdDdE쏸쑄쎦쐰 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()