Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CGAffineTransform 実践入門

CGAffineTransform 実践入門

Af64bc38c0ffcfcabdf430759ee491ce?s=128

Elvis Shi

May 15, 2017
Tweet

More Decks by Elvis Shi

Other Decks in Programming

Transcript

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

  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 { } }
  3. ςʔϚ͕ܾ·Δ·ͰͷาΈ

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

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

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

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

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

  9. ਺ֶλΠϜ

  10. ਺ֶλΠϜ

  11. ਺ֶλΠϜ

  12. ਺ֶλΠϜ

  13. ਺ֶλΠϜ

  14. ਺ֶλΠϜ

  15. ਺ֶλΠϜ ಉ͡ ٯ֯౓

  16. ਺ֶλΠϜ y

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

    = 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*14transform쏸ઃఆ쎽쏅UIView쏕௚઀frame쏸ઃఆ쎿쏱쏔쏍쏕쏐쎵ɺ ୅쏵쏰쏑center쏎bounds.size쏸ઃఆ쎿쏱쎹쏎ɻ
  27. DEMO

  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
  30. ܅쏐쏹쎱 ࣸਅ쏎ҧ쏵쏐쎪ʁ

  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 .+
  42. ղઆλΠϜ 쏻쐮쏼쑌ม׵쏕࠲ඪม׵ɻ O 0 5 6 0 7 8

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

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

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

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

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

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

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

    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)
  55. ʲ࿕ใʳFramework࡞Γ·ͨ͠ʂ

  56. Danbo

  57. DEMO

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

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

  60. ίʔσΟϯάλΠϜ 쏻쐤쐺쎦쐐쑀쑌ઃఆ쏤쏎쏧ɿ 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()
  61. DEMO