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

UIViewPropertyAnimatorで実現するリッチなアニメーション表現

Jiro Nagashima
September 02, 2018

 UIViewPropertyAnimatorで実現するリッチなアニメーション表現

iOSDC 2018 9/2 14:40~ Track D で登壇した内容です

https://fortee.jp/iosdc-japan-2018/proposal/5a1a99cb-9b59-4d94-a655-49ffe3e7b91b

Jiro Nagashima

September 02, 2018
Tweet

More Decks by Jiro Nagashima

Other Decks in Technology

Transcript

  1. ©2018 Wantedly, Inc.
    2018.9.2 -
    UIViewPropertyAnimator Ͱ
    ࣮ݱ͢ΔϦονͳΞχϝʔγϣϯදݱ
    iOSDC 2018
    Jiro @hedjirog

    View Slide

  2. ©2018 Wantedly, Inc.
    Jiro
    Wantedly, Inc. / Engineer
    ΤϯδχΞɻελʔτΞοϓͷॳظ։ൃɺສϢʔβʔΛ๊͑ΔΞϓϦͷ
    ಺੡Խɺάϩʔεظʹ͓͚Δࢪࡦ࣮ࢪͳͲɺJ04ΞϓϦ։ൃΛத৺ʹ༷ʑͳ
    ։ൃϑΣʔζΛܦݧɻϑϦʔϥϯεظʹܞΘͬͨWantedlyͰάϩʔενʔ
    ϜΛϦʔυ͢Δཱ৔ͱͯ͠౓໨ͷ௅ઓʂ
    Twitter: @hedjirog

    View Slide

  3. ©2018 Wantedly, Inc.
    αϯϓϧίʔυ

    View Slide

  4. ©2018 Wantedly, Inc.
    https://github.com
    /hedjirog/CustomPresentation

    View Slide

  5. ©2018 Wantedly, Inc.
    αϯϓϧίʔυ
    ը໘ભҠͷΞχϝʔγϣϯΛ࣮૷
    w ෳ਺ͷUIViewPropertyAnimatorΛ࿈ಈ
    w WWDC 2017 Session 230 “Advanced Animations with UIKit” Ͱఏࣔ͞Εͨख๏
    w ख๏ͷվྑΛՃ࣮͑૷Λࢼͨ͠΋ͷ
    https://github.com
    /hedjirog/CustomPresentation

    View Slide

  6. ©2018 Wantedly, Inc.
    Demo

    View Slide

  7. ©2018 Wantedly, Inc.

    View Slide

  8. ©2018 Wantedly, Inc.
    1
    3
    6
    4
    5
    2

    View Slide

  9. ©2018 Wantedly, Inc.
    1
    3
    6
    4
    5
    2
    ෳ਺ͷUIViewPropertyAnimator ͕࿈ಈ
    γʔτͱϥϕϧͷҠಈ ֦େॖখ

    γʔτͷؙ֯
    ϥϕϧͷೱ୶
    ϥϕϧͷೱ୶
    Ϙλϯͷೱ୶
    എܠͷೱ୶

    View Slide

  10. ©2018 Wantedly, Inc.
    UIViewPropertyAnimatorͷ֓ཁ

    View Slide

  11. ©2018 Wantedly, Inc.
    Ξχϝʔγϣϯ࣮૷ͷͨΊͷΫϥε
    w Ξχϝʔγϣϯͷऴྃ·Ͱʹಈ࡞Λಈతʹมߋ͢Δ͜ͱ͕Ͱ͖Δ
    w ϓϩύςΟͷ஋
    w ΞχϝʔγϣϯΧʔϒ
    w ਐߦ౓߹͍
    w ਐߦํ޲
    w ΠϯλϥΫςΟϒͳΞχϝʔγϣϯʹస׵Մೳ
    UIViewPropertyAnimator

    View Slide

  12. ©2018 Wantedly, Inc.
    ը໘ભҠͷ࣮૷ʹར༻͢ΔAPI

    View Slide

  13. ©2018 Wantedly, Inc.
    UIViewControllerTransitioningDelegate
    w 3ͭͷ DPOUSPMMFS Λܾఆ͢ΔϝιουΛ࣋ͭϓϩτίϧ
    • Presentation Controller
    • Animation Controller
    • Interaction Controller
    w ભҠઌͷ view controller ͷ transitioningDelegate ϓϩύςΟʹઃఆ
    ը໘ભҠͷ࣮૷ʹར༻͢ΔAPI

    View Slide

  14. ©2018 Wantedly, Inc.
    UIViewController
    TransitioningDelegate
    Presentation Controller
    Animation Controller
    Interaction Controller
    Protocol

    View Slide

  15. ©2018 Wantedly, Inc.
    UIPresentationController
    w ભҠݩͱભҠઌͷview controllerͷදࣔΛ؅ཧ͢ΔΫϥε
    w ΧελϜͷϏϡʔΛࠩ͠ࠐΉ͜ͱ͕Ͱ͖Δ
    ը໘ભҠͷ࣮૷ʹར༻͢ΔAPI

    View Slide

  16. ©2018 Wantedly, Inc.
    UIViewController
    TransitioningDelegate
    Presentation Controller
    Animation Controller
    Interaction Controller
    UIPresentationController
    Protocol
    Class

    View Slide

  17. ©2018 Wantedly, Inc.
    UIViewControllerAnimatedTransitioning
    w ભҠͷΞχϝʔγϣϯΛܾఆ͢ΔϝιουΛ࣋ͭϓϩτίϧ
    w ϓϩτίϧʹ४ڌͨ͠ animation controller Λఆٛɺtransitioning delegateͰฦ٫
    w ભҠઌͷview controllerͷදࣔɾඇදࣔͦΕͧΕͷBOJNBUJPO controllerΛࢦఆՄೳ
    ը໘ભҠͷ࣮૷ʹར༻͢ΔAPI

    View Slide

  18. ©2018 Wantedly, Inc.
    UIViewController
    TransitioningDelegate
    Presentation Controller
    Animation Controller
    Interaction Controller
    UIViewController
    AnimatedTransitioning
    UIPresentationController
    Protocol
    Class

    View Slide

  19. ©2018 Wantedly, Inc.
    UIViewControllerInteractiveTransitioning
    w ΞχϝʔγϣϯͷΠϯλϥΫςΟϒʹ͢Δࡍʹར༻͞ΕΔ
    w ϓϩτίϧʹ४ڌͨ͠ interaction controller Λఆٛɺtransitioning delegateͰฦ٫
    w ϓϩτίϧʹ४ڌͨ͠UIPercentDrivenInteractiveTransitionΫϥε͕ఏڙ͞Ε͍ͯΔ
    w ભҠઌͷview controllerͷදࣔɾඇදࣔͦΕͧΕͷJOUFSBDUJPO controllerΛࢦఆՄೳ
    ը໘ભҠͷ࣮૷ʹར༻͢ΔAPI

    View Slide

  20. ©2018 Wantedly, Inc.
    UIViewController
    TransitioningDelegate
    Presentation Controller
    Animation Controller
    Interaction Controller
    UIViewController
    AnimatedTransitioning
    UIPresentationController
    UIPercentDrivenInteractiveTransition
    UIViewController
    InteractiveTransitioning
    Protocol
    Class

    View Slide

  21. ©2018 Wantedly, Inc.
    αϯϓϧίʔυͷ࣮૷

    View Slide

  22. ©2018 Wantedly, Inc.
    present
    dismiss
    ભҠૢ࡞ͷఆٛ

    View Slide

  23. ©2018 Wantedly, Inc.
    ભҠૢ࡞ͷఆٛ
    enum PresentationOperation {
    case present
    case dismiss
    var duration: TimeInterval { return 0.6 }
    }

    View Slide

  24. ©2018 Wantedly, Inc.
    PresentationController ͷ࣮૷
    ੹຿Λҙࣝͨ͠Ϋϥεͷ෼ׂ

    View Slide

  25. ©2018 Wantedly, Inc.
    Ϋϥεͷ෼ׂ

    View Slide

  26. ©2018 Wantedly, Inc.
    جຊͷ3ͭͷΫϥε
    1. PresentationController
    • UIPresentationController ͷαϒΫϥε
    • ભҠݩͱભҠઌͷը໘ؒʹΧελϜͷϏϡʔΛࠩ͠ࠐΉ
    2. PresentationAnimationController
    • UIViewControllerAnimatedTransitioning ʹ४ڌ
    • ΞχϝʔγϣϯΛू໿ͤͯ͞ભҠΞχϝʔγϣϯΛఆٛ͢Δ
    3. PresentationInteractionController
    • UIPercentDrivenInteractiveTransition ͷαϒΫϥε
    • δΣενϟΛײ஌ͯ͠ΞχϝʔγϣϯͷਐߦΛ੍ޚ͢Δ
    Ϋϥεͷ෼ׂ
    PresentationController
    (UIPresentationController)
    PresentationAnimationController
    PresentationInteractionController
    (UIPercentDrivenInteractiveTransition)

    View Slide

  27. ©2018 Wantedly, Inc.
    UIViewController
    TransitioningDelegate
    PresentationController
    (UIPresentationController)
    PresentationInteractionController
    (UIPercentDrivenInteractiveTransition
    )
    UIViewController
    InteractiveTransitioning
    Protocol
    Class
    PresentationAnimationController
    UIViewController
    AnimatedTransitioning

    View Slide

  28. ©2018 Wantedly, Inc.
    Ξχϝʔγϣϯͷఆٛ

    View Slide

  29. ©2018 Wantedly, Inc.
    Ξχϝʔγϣϯͷఆٛ
    Wiew Λอ࣋͢Δ controller ͰఆٛՄೳʹ͢Δ
    w Ξχϝʔγϣϯͷఆٛʹ͸WJFXͷࢀর͕ඞཁ
    w action controller͕ભҠݩ΍ભҠઌͷviewͷߏ଄Λ஌Βͳͯ͘΋ྑ͍Α͏ʹ͍ͨ͠
    w Ξχϝʔγϣϯ͸controllerͰఆٛΛͯ͠ϓϩτίϧΛհͯ͠ू໿Մೳʹ͢Δ
    Presentation
    AnimatedTransitioning

    View Slide

  30. ©2018 Wantedly, Inc.
    UIViewController
    TransitioningDelegate
    PresentationController
    (UIPresentationController)
    PresentationInteractionController
    (UIPercentDrivenInteractiveTransition
    )
    UIViewController
    InteractiveTransitioning
    Protocol
    Class
    PresentationAnimationController
    UIViewController
    AnimatedTransitioning
    Presentation
    AnimatedTransitioning
    Presentation
    AnimatedTransitioning
    Presentation
    AnimatedTransitioning

    View Slide

  31. ©2018 Wantedly, Inc.
    protocol PresentationAnimatedTransitioning {
    func prepareForTransition(using operation: PresentationOperation)
    func transitionAnimators(operation: PresentationOperation,
    duration: TimeInterval) -> [UIViewPropertyAnimator]
    }
    Ξχϝʔγϣϯͷఆٛ
    Presentation
    AnimatedTransitioning

    View Slide

  32. ©2018 Wantedly, Inc.
    δΣενϟͷఆٛ

    View Slide

  33. ©2018 Wantedly, Inc.
    δΣενϟͷఆٛ
    Wiew Λอ࣋͢Δ controller ͰఆٛՄೳʹ͢Δ
    w δΣενϟʔͷఆٛʹ͸WJFXͷࢀর͕ඞཁ
    w interaction controller͕ભҠݩ΍ભҠઌͷviewͷߏ଄Λ஌Βͳͯ͘΋ྑ͍Α͏ʹ͍ͨ͠
    w δΣενϟʔ͸controllerͰఆٛΛͯ͠ϓϩτίϧΛհͯ͠ू໿Մೳʹ͢Δ
    Presentation
    InteractiveTransitioning

    View Slide

  34. ©2018 Wantedly, Inc.
    UIViewController
    TransitioningDelegate
    PresentationController
    (UIPresentationController)
    PresentationInteractionController
    (UIPercentDrivenInteractiveTransition
    )
    UIViewController
    InteractiveTransitioning
    Protocol
    Class
    PresentationAnimationController
    UIViewController
    AnimatedTransitioning
    Presentation
    AnimatedTransitioning
    Presentation
    AnimatedTransitioning
    Presentation
    AnimatedTransitioning
    Presentation
    InteractiveTransitioning
    Presentation
    InteractiveTransitioning

    View Slide

  35. ©2018 Wantedly, Inc.
    protocol PresentationInteractiveTransitioning {
    var interactivePanGestureRecognizer: UIPanGestureRecognizer { get }
    }
    Ξχϝʔγϣϯͷఆٛ
    Presentation
    InteractiveTransitioning

    View Slide

  36. ©2018 Wantedly, Inc.
    ϓϩτίϧʹ४ڌ͢Δ͜ͱͷอূ

    View Slide

  37. ©2018 Wantedly, Inc.
    ϓϩτίϧʹ४ڌ͢Δ͜ͱͷอূ
    PresentationController ͷΠχγϟϥΠβΛ޻෉͢Δ
    w ΠχγϟϥΠβҾ਺ͷܕΛϓϩτίϧʹ४ڌ͢Δ͜ͱΛཁٻ͢ΔΑ͏ʹ͢Δ
    w PresentationControllerࣗ਎ΛભҠσϦήʔτʹ͢Δ
    w UIViewControllerTransitioningDelegate ʹ४ڌͤ͞Δ
    PresentationController
    (UIPresentationController)
    UIViewController
    TransitioningDelegate

    View Slide

  38. ©2018 Wantedly, Inc.
    PresentationInteractionController
    (UIPercentDrivenInteractiveTransition
    )
    UIViewController
    InteractiveTransitioning
    Protocol
    Class
    PresentationAnimationController
    UIViewController
    AnimatedTransitioning
    Presentation
    AnimatedTransitioning
    Presentation
    AnimatedTransitioning
    Presentation
    InteractiveTransitioning
    Presentation
    InteractiveTransitioning
    UIViewController
    TransitioningDelegate
    Presentation
    AnimatedTransitioning
    PresentationController
    (UIPresentationController)

    View Slide

  39. ©2018 Wantedly, Inc.
    typealias PresentableViewController
    = UIViewController
    & PresentationAnimatedTransitioning
    & PresentationInteractiveTransitioning
    class PresentationController: UIPresentationController {
    init(presentedViewController: PresentableViewController,
    presentingViewController: PresentableViewController) {
    super.init(presentedViewController: presentedViewController,
    presenting: presentingViewController)
    presentedViewController.modalPresentationStyle = .custom
    }
    ϓϩτίϧʹ४ڌ͢Δ͜ͱͷอূ PresentationController
    (UIPresentationController)
    UIViewController
    TransitioningDelegate

    View Slide

  40. ©2018 Wantedly, Inc.
    extension PresentationController: UIViewControllerTransitioningDelegate {
    func presentationController(forPresented presented: UIViewController,
    presenting: UIViewController?,
    source: UIViewController
    ) -> UIPresentationController? {
    return self
    }
    func animationController(forPresented presented: UIViewController,
    presenting: UIViewController,
    source: UIViewController
    ) -> UIViewControllerAnimatedTransitioning? {
    return PresentationAnimationController(operation: .present)
    }
    func animationController(forDismissed dismissed: UIViewController
    ) -> UIViewControllerAnimatedTransitioning? {
    return PresentationAnimationController(operation: .dismiss)
    }
    }
    ϓϩτίϧʹ४ڌ͢Δ͜ͱͷอূ PresentationController
    (UIPresentationController)
    UIViewController
    TransitioningDelegate

    View Slide

  41. ©2018 Wantedly, Inc.
    private func presentSecondViewController() {
    let presentationController
    = PresentationController(presentedViewController: secondViewController,
    presentingViewController: self)
    secondViewController.transitioningDelegate = presentationController
    present(secondViewController, animated: true)
    }
    ϓϩτίϧʹ४ڌ͢Δ͜ͱͷอূ PresentationController
    (UIPresentationController)
    UIViewController
    TransitioningDelegate

    View Slide

  42. ©2018 Wantedly, Inc.
    AnimationController ͷ࣮૷
    ෳ਺ͷΞχϝʔγϣϯΛ࿈ಈͤ͞Δ

    View Slide

  43. ©2018 Wantedly, Inc.
    Ξχϝʔγϣϯͷ࣮૷

    View Slide

  44. ©2018 Wantedly, Inc.
    extension PresentationController: PresentationAnimatedTransitioning {
    func transitionAnimators(operation: PresentationOperation,
    duration: TimeInterval) -> [UIViewPropertyAnimator] {
    let curve: UIViewAnimationCurve = operation == .present ? .easeIn : .easeOut
    let dimmingAnimator = UIViewPropertyAnimator(duration: duration, curve: curve) {
    self.dimmingView.alpha = self.dimmingViewAlpha(for: operation)
    }
    return [dimmingAnimator]
    }
    private func dimmingViewAlpha(for operation: PresentationOperation) -> CGFloat {
    return operation == .present ? 0.2 : 0
    }
    }
    Ξχϝʔγϣϯͷ࣮૷
    Presentation
    AnimatedTransitioning
    PresentationController
    (UIPresentationController)

    View Slide

  45. ©2018 Wantedly, Inc.
    Ξχϝʔγϣϯͷू໿

    View Slide

  46. ©2018 Wantedly, Inc.
    UIViewController
    TransitioningDelegate
    PresentationInteractionController
    (UIPercentDrivenInteractiveTransition
    )
    UIViewController
    InteractiveTransitioning
    Protocol
    Class
    PresentationAnimationController
    UIViewController
    AnimatedTransitioning
    Presentation
    AnimatedTransitioning
    Presentation
    AnimatedTransitioning
    Presentation
    InteractiveTransitioning
    Presentation
    InteractiveTransitioning
    Presentation
    AnimatedTransitioning
    PresentationController
    (UIPresentationController)

    View Slide

  47. ©2018 Wantedly, Inc.
    PresentationInteractionController
    (UIPercentDrivenInteractiveTransition
    )
    UIViewController
    InteractiveTransitioning
    Protocol
    Class
    PresentationAnimationController
    UIViewController
    AnimatedTransitioning
    Presentation
    AnimatedTransitioning
    Presentation
    AnimatedTransitioning
    Presentation
    InteractiveTransitioning
    Presentation
    InteractiveTransitioning
    1 3
    4
    5
    2
    UIViewController
    TransitioningDelegate
    Presentation
    AnimatedTransitioning
    6
    PresentationController
    (UIPresentationController)

    View Slide

  48. ©2018 Wantedly, Inc.
    PresentationInteractionController
    (UIPercentDrivenInteractiveTransition
    )
    UIViewController
    InteractiveTransitioning
    Protocol
    Class
    PresentationAnimationController
    UIViewController
    AnimatedTransitioning
    Presentation
    AnimatedTransitioning
    Presentation
    AnimatedTransitioning
    Presentation
    InteractiveTransitioning
    Presentation
    InteractiveTransitioning
    UIViewController
    TransitioningDelegate
    1
    3
    6
    4
    5
    2
    Presentation
    AnimatedTransitioning
    PresentationController
    (UIPresentationController)

    View Slide

  49. ©2018 Wantedly, Inc.
    class PresentationAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
    private var transitionAnimator: CoordinatedAnimator?
    func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning
    ) -> UIViewImplicitlyAnimating {
    if let transitionAnimator = transitionAnimator {
    return transitionAnimator
    }
    let duration = transitionDuration(using: transitionContext)
    var animators: [UIViewPropertyAnimator] = []
    [fromViewController, toViewController, presentationController].forEach {
    animators += $0.transitionAnimators(operation: operation,
    duration: duration)
    }

    Ξχϝʔγϣϯͷू໿ PresentationAnimationController
    UIViewController
    AnimatedTransitioning
    1
    3
    6
    4
    5
    2

    View Slide

  50. ©2018 Wantedly, Inc.
    ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ

    View Slide

  51. ©2018 Wantedly, Inc.
    class PresentationAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
    private var transitionAnimator: CoordinatedAnimator?
    func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning
    ) -> UIViewImplicitlyAnimating {
    if let transitionAnimator = transitionAnimator {
    return transitionAnimator
    }
    let duration = transitionDuration(using: transitionContext)
    var animators: [UIViewPropertyAnimator] = []
    [fromViewController, toViewController, presentationController].forEach {
    animators += $0.transitionAnimators(operation: operation,
    duration: duration)
    }

    ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ PresentationAnimationController
    UIViewController
    AnimatedTransitioning
    1
    3
    6
    4
    5
    2

    View Slide

  52. ©2018 Wantedly, Inc.
    ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ
    UIViewImplicitlyAnimating ʹ४ڌͨ͠Ξχϝʔγϣϯ͕ඞཁ
    w ΧελϜͷΞχϝʔγϣϯΛఆٛ
    w ෳ਺ͷUIViewPropertyAnimatorΛΠχγϟϥΠβҾ਺Ͱड͚औΔ
    w Ξχϝʔγϣϯͷ੍ޚ໋ྩʹैͬͯू໿ͨ͠ΞχϝʔγϣϯΛ࿈ಈͤͯ͞ಈ͔͢
    PresentationAnimationController
    UIViewController
    AnimatedTransitioning
    1
    3
    6
    4
    5
    2

    View Slide

  53. ©2018 Wantedly, Inc.
    class CoordinatedAnimator: NSObject, UIViewImplicitlyAnimating {
    private let primaryAnimator: UIViewPropertyAnimator
    private var animators: [UIViewPropertyAnimator]
    init(primaryAnimator: UIViewPropertyAnimator, secondaryAnimators: [UIViewPropertyAnimator]) {
    self.primaryAnimator = primaryAnimator
    self.animators = [primaryAnimator] + secondaryAnimators
    }

    ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ PresentationAnimationController
    UIViewController
    AnimatedTransitioning
    1
    3
    6
    4
    5
    2

    View Slide

  54. ©2018 Wantedly, Inc.
    class CoordinatedAnimator: NSObject, UIViewImplicitlyAnimating {

    func startAnimation() {
    animators.forEach { $0.startAnimation() }
    }
    func pauseAnimation() {
    animators.forEach { $0.pauseAnimation() }
    }
    func finishAnimation(at finalPosition: UIViewAnimatingPosition) {
    animators.forEach { $0.finishAnimation(at: finalPosition) }
    }

    ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ PresentationAnimationController
    UIViewController
    AnimatedTransitioning
    1
    3
    6
    4
    5
    2

    View Slide

  55. ©2018 Wantedly, Inc.
    class PresentationAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
    func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning
    ) -> UIViewImplicitlyAnimating {

    var animators: [UIViewPropertyAnimator] = []

    let prioritizedAnimators = self.prioritizedAnimators(from: animators)
    let animator = CoordinatedAnimator(primaryAnimator: prioritizedAnimators.primary,
    secondaryAnimators: prioritizedAnimators.secondary)
    animator.addCompletion { position in
    let didComplete = position == .end
    transitionContext.completeTransition(didComplete)
    }
    transitionAnimator = animator
    return animator
    }

    ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ PresentationAnimationController
    UIViewController
    AnimatedTransitioning
    1
    3
    6
    4
    5
    2

    View Slide

  56. ©2018 Wantedly, Inc.
    ͦͷଞ
    w Interaction Controllerͷ࣮૷
    w ભҠલޙͷviewͷؔ࿈෇͚
    w ભҠ։࢝લͷviewͷߋ৽
    w ΩʔϑϨʔϜΞχϝʔγϣϯͷఆٛ
    https://github.com
    /hedjirog/CustomPresentation

    View Slide

  57. ©2018 Wantedly, Inc.
    ·ͱΊ
    w ੹຿Λҙࣝͨ͠Ϋϥεͷ෼ׂ
    w viewΛอ࣋ͨ͠controllerͰΞχϝʔγϣϯͱδΣενϟΛఆٛՄೳʹ͢Δ޻෉
    w view controller͕ϓϩτίϧʹ४ڌ͢Δ͜ͱΛอূͤ͞ΔͨΊ޻෉
    w action controllerʹ͓͚ΔΞχϝʔγϣϯͷू໿ͷख๏
    w ू໿ͨ͠ΞχϝʔγϣϯΛ࿈ಈ੍ͤͯ͞ޚ͢Δख๏

    View Slide

  58. ©2018 Wantedly, Inc.

    View Slide