티스토리 뷰

iOS

[iOS] UIView.animate 애니메이션 만들기

Kim_Baechu 2021. 2. 23. 12:39

아래와 같은 Live 방송 애니메이션을 만들어보겠습니다.

 

1. 3개의 뷰 준비

var view1 = UIView()
var view2 = UIView()
var view3 = UIView()

var viewStack = [UIView]()

lazy var targetSize = self.frame.size

override init(frame: CGRect) {
    super.init(frame: frame)
    self.backgroundColor = .clear
    viewStack.append(view1)
    viewStack.append(view2)
    viewStack.append(view3)
    
    setupLayout()
    viewStack.forEach { animate($0)}
    self.transform = CGAffineTransform(rotationAngle: .pi)
}

움직이는 3개의 하얀 막대기를 뷰로 만들어 주겠습니다.

animate(_ view: UIView)와 setupLayout()가 사용되겠습니다.

그리고 self.transform = CGAffineTransform(rotationAngle: .pi)를 통해 화면을 180도 돌려줬습니다.

왜냐하면 우리가 iOS 작업하실 때 x값은 커질수록 오른쪾으로가고 y값은 커질수록 밑으로 내려갔죠.

뷰의 길이를 늘리면 아래로 늘어납니다.

그래서 일단 작업을 하고 180도 돌려줬습니다.

 

2. 기본적인 레이아웃 만들기

func setupLayout() {
    viewStack.enumerated().forEach { sequence in
        let view = sequence.element
        let multiple: CGFloat = CGFloat(sequence.offset)
        
        self.addSubview(view)
        let padding = targetSize.width / 12
        let height = targetSize.height * CGFloat.random(in: 0.2...1)
        let width = (targetSize.width - padding * 2) / 3
        
        let x: CGFloat = (width + padding) * multiple
        view.backgroundColor = .white
        view.frame = CGRect(x: x, y: 0, width: width, height: height)
    }
}

처음 만들어지는 뷰의 높이를 랜덤하게 지정해서 뷰를 불러올 때 마다 서로 다르게 보이도록 했습니다.

 

3. 애니메이션 동작

func animate(_ view: UIView) {
    UIView.animate(withDuration: TimeInterval.random(in: 0.3...0.5), delay: 0, options: .curveEaseInOut, animations: { [weak self] in
        guard let self = self else { return }
        view.frame.size.height = self.targetSize.height * CGFloat.random(in: 0.1...1)
        
    }) { _ in
        self.animate(view)
    }
}

애니메이션이 동작하는 시간을 0.3~0.5초 사이로 만들었습니다.

그리고 각각의 뷰의 높이를 램덤하게 변하게 했습니다.

한번의 애니메이션이 끝나면 다시 애니메이션을 실행하도록 했습니다.

 

이제 아래처럼 사용하시면 됩니다.

class ViewController: UIViewController {
    let animationView = AnimationView(frame: CGRect(x: 200, y: 100, width: 50, height: 50))
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(animationView)
    }
}

 

4. 전체코드

//
//  AnimationView.swift
//  LiveAnimation
//
//  Created by Beomcheol Kwon on 2021/02/05.
//

import Foundation
import UIKit

class AnimationView: UIView {
    
    var view1 = UIView()
    var view2 = UIView()
    var view3 = UIView()
    
    var viewStack = [UIView]()
    
    lazy var targetSize = self.frame.size
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = .clear
        viewStack.append(view1)
        viewStack.append(view2)
        viewStack.append(view3)
        
        setupLayout()
        viewStack.forEach { animate($0)}
        self.transform = CGAffineTransform(rotationAngle: .pi)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func setupLayout() {
        viewStack.enumerated().forEach { sequence in
            let view = sequence.element
            let multiple: CGFloat = CGFloat(sequence.offset)
            
            self.addSubview(view)
            let padding = targetSize.width / 12
            let height = targetSize.height * CGFloat.random(in: 0.2...1)
            let width = (targetSize.width - padding * 2) / 3
            
            let x: CGFloat = (width + padding) * multiple
            view.backgroundColor = .white
            view.frame = CGRect(x: x, y: 0, width: width, height: height)
        }
    }
    
    func animate(_ view: UIView) {
        UIView.animate(withDuration: TimeInterval.random(in: 0.3...0.5), delay: 0, options: .curveEaseInOut, animations: { [weak self] in
            guard let self = self else { return }
            view.frame.size.height = self.targetSize.height * CGFloat.random(in: 0.1...1)
            
        }) { _ in
            self.animate(view)
        }
    }
}

 

5개의 애니메이션이 각각 독립적으로 다르게 움직이는 것을 보실 수 있습니다.

댓글
공지사항