ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [iOS] Animation with SwiftUI
    Programing/iOS 2020. 8. 28. 13:22

    안녕하세요~! 5anniversary입니다~!

     

    이번 시간에는 SwiftUI에서는 Animation 효과를 어떻게 주는지 알아볼거에요~!

     

    www.raywenderlich.com/5815412-getting-started-with-swiftui-animations

     

    Getting Started with SwiftUI Animations

    In this tutorial, you’ll learn how to add fancy animations with SwiftUI. You’ll go from basic animations to complex and custom spring animations.

    www.raywenderlich.com

    를 참고해서 공부했어요!!

     

    SwiftUI에서 기본적인 애니메이션을 다루는 방법은 SwiftUI에 포함되어 있는Animation API를 이용하는거에요

     

     기존의 iOS에서의 프로그래밍에서도 애니메이션을 다룰 수 있는 방법이 두 가지가 있었는데요, UIView에 있는 .animate API를 사용하는 것, Core Animation에 있는 Animation API를 이용하는 것이 있었어요.

     

     

     그리고 SwiftIUI에서는 이와 비슷하게 애니메이션을 다룰 수 있는 Animation 구조체가 있어요!!

     

    이런 Animation 구조체가 가지고 있는 속성들과 사용하는 방법에 대해 알아보도록 하겠습니다!!

     

     

    기본적으로 Animation 구조체에는 animation Timing에 대해 관리를 할 수 있는 Type 메소드와 Type Properties가 있습니다.

     

    easyInOut / easeIn / easeOut / linear / timingCurve 로 제공 되는 API인데요 

     

    easyInOut / easeIn / easeOut / linear 의 경우에는 duration을 조정할수있는 메소드가 함께 있어 함께 시간을 조절해 사용가능해요~!

     

    그리고 timingCurve로 Animation Timing에 대해 custom으로 사용이 가능한 방법이에요

     

    extension Animation {
    
        public static let `default`: Animation
    }
    
    @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
    extension Animation {
    
        public static func easeInOut(duration: Double) -> Animation
    
        public static var easeInOut: Animation { get }
    
        public static func easeIn(duration: Double) -> Animation
    
        public static var easeIn: Animation { get }
    
        public static func easeOut(duration: Double) -> Animation
    
        public static var easeOut: Animation { get }
    
        public static func linear(duration: Double) -> Animation
    
        public static var linear: Animation { get }
    
        public static func timingCurve(_ c0x: Double, _ c0y: Double, _ c1x: Double, _ c1y: Double, duration: Double = 0.35) -> Animation
    }
    

    이렇게 애플 SwiftUI 공식문서에 적혀있어요!!

     

    그리고 spring / interactiveSpring 이라는 메소드도 포함 되어있어요 이런 메소드를 사용하면 스프링 애니메이션을 조절할수있습니다!!

     

    @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
    extension Animation {
    
        /// A persistent spring animation. When mixed with other `spring()`
        /// or `interactiveSpring()` animations on the same property, each
        /// animation will be replaced by their successor, preserving
        /// velocity from one animation to the next. Optionally blends the
        /// response values between springs over a time period.
        ///
        /// - Parameters:
        ///   - response: The stiffness of the spring, defined as an
        ///     approximate duration in seconds. A value of zero requests
        ///     an infinitely-stiff spring, suitable for driving
        ///     interactive animations.
        ///   - dampingFraction: The amount of drag applied to the value
        ///     being animated, as a fraction of an estimate of amount
        ///     needed to produce critical damping.
        ///   - blendDuration: The duration in seconds over which to
        ///     interpolate changes to the response value of the spring.
        /// - Returns: a spring animation.
        public static func spring(response: Double = 0.55, dampingFraction: Double = 0.825, blendDuration: Double = 0) -> Animation
    
        /// A convenience for a `spring()` animation with a lower
        /// `response` value, intended for driving interactive animations.
        public static func interactiveSpring(response: Double = 0.15, dampingFraction: Double = 0.86, blendDuration: Double = 0.25) -> Animation
    }
    
    
    @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
    extension Animation {
    
        /// An interpolating spring animation that uses a damped spring
        /// model to produce values in the range [0, 1] that are then used
        /// to interpolate within the [from, to] range of the animated
        /// property. Preserves velocity across overlapping animations by
        /// adding the effects of each animation.
        ///
        /// - Parameters:
        ///   - mass: The mass of the object attached to the spring.
        ///   - stiffness: The stiffness of the spring.
        ///   - damping: The spring damping value.
        ///   - initialVelocity: the initial velocity of the spring, as
        ///     a value in the range [0, 1] representing the magnitude of
        ///     the value being animated.
        /// - Returns: a spring animation.
        public static func interpolatingSpring(mass: Double = 1.0, stiffness: Double, damping: Double, initialVelocity: Double = 0.0) -> Animation
    }
    

     

    그리고 또!!  조절할수있는 메소드가 delay / speed가 있는데요!! 

    @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
    extension Animation {
    
        public func delay(_ delay: Double) -> Animation
    }
    
    @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
    extension Animation {
    
        /// Returns an animation that has its speed multiplied by `speed`. For
        /// example, if you had `oneSecondAnimation.speed(0.25)`, it would be at
        /// 25% of its normal speed, so you would have an animation that would last
        /// 4 seconds.
        public func speed(_ speed: Double) -> Animation
    }
    

    전부 직관적으로 조절이 가능해 보여요

     

    마지막으로 

     

    @available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
    extension Animation {
    
        public func repeatCount(_ repeatCount: Int, autoreverses: Bool = true) -> Animation
    
        public func repeatForever(autoreverses: Bool = true) -> Animation
    }
    

    반복에 대한 메소드도 정의가 되어있어요

     

    자 이렇게 여러가지의 프로퍼티와 메소드들이 있어요!!

     

    이런 메소드들을 모두 객체로 만들어줘 사용을 할 수 있어요!!

     

    재사용하는데 간단히 사용할수가 있어서 좋은 거 같아요!!

     

    그리고 @State 프로퍼티 래퍼를 통해서 animation을 처리할수도 있어요!

     

    예시로 설명해드릴게요!!

     

    @State private var startAnimation: Bool = false
    
    // 아래처럼 미리 선언을 해준 뒤에 
    private var animation: Animation = Animation.easeInOut(duration: 1)
            .repeatForever(autoreverses: true)
    
    
    // 이처럼 애니메이션을 다시 넣어주면 선언했던 애니메이션 그대로 재사용이 가능하더라구요!!
    var body: some View {
            VStack {
                // 2.
                Button("Start Animation") {
                    withAnimation(self.animation) {
                        self.startAnimation.toggle()
                    }
                }
                
                HStack {
                    Spacer()
                    // 3.
                    Text("🚚")
                        .font(.custom("Arial", size: 100))
                        // 4.
                        .offset(x: self.startAnimation ? 0 - UIScreen.main.bounds.width + 100: 0)
                }
            }
        }
    

     

     

     

    마지막으로 animation.default의 값이 궁금해서 한번 로그를 찍어봤어요!!

     

    아래와 같이 구성되어있네요!!

     

    BezierAnimation(duration: 0.35, curve: SwiftUI.(unknown context at $7fff2c9dfd28).BezierTimingCurve(ax: 0.52, bx: -0.78, cx: 1.26, ay: -2.0, by: 3.0, cy: 0.0))

     

    댓글

Designed by Tistory.