Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GWL-343] 가우시안 블러를 활용하여 Login background 화면 설정 #344

Merged
merged 10 commits into from
Dec 10, 2023
3 changes: 1 addition & 2 deletions iOS/Projects/App/WeTri/Sources/Application/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_: UIApplication,
didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? = nil
)
-> Bool {
) -> Bool {
return true
}

Expand Down
Binary file not shown.
Binary file added iOS/Projects/Features/Login/Resources/running.mp4
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

import AuthenticationServices
import AVFoundation
import Combine
import CombineCocoa
import DesignSystem
Expand All @@ -22,23 +23,38 @@ final class LoginViewController: UIViewController {
private let credentialSubject = PassthroughSubject<AuthorizationInfo, Never>()
private let loginSubject = PassthroughSubject<Void, Never>()

private var timeObserverToken: Any?
private let playerLayer: AVPlayerLayer? = {
guard
let bundle = Bundle(for: LoginViewController.self).path(forResource: "running", ofType: "mp4")
else {
return nil
}
let videoURL = URL(fileURLWithPath: bundle)
let playerItem = AVPlayerItem(url: videoURL)
let player = AVPlayer(playerItem: playerItem)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.videoGravity = .resizeAspectFill // 영상을 화면에 꽉 차게 표시
return playerLayer
}()

private lazy var logoImageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.image = .logoImage
imageView.image = .logoImageDark
imageView.contentMode = .scaleAspectFit
return imageView
}()

private lazy var appleLoginButton: ASAuthorizationAppleIDButton = {
let button = ASAuthorizationAppleIDButton(type: .signIn, style: .black)
let button = ASAuthorizationAppleIDButton(type: .signIn, style: .white)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()

private let policyTextView: UITextView = {
let attributedString = NSMutableAttributedString(string: "가입을 진행할 경우, 서비스 약관 및\n개인정보 처리방침에 동의한것으로 간주합니다.")
attributedString.addAttribute(.link, value: PrivacyLink.link, range: NSRange(location: 12, length: 15))
attributedString.addAttribute(.link, value: PrivacyLink.link, range: NSRange(location: 12, length: 18))

let textView = UITextView()
textView.translatesAutoresizingMaskIntoConstraints = false
Expand All @@ -50,7 +66,6 @@ final class LoginViewController: UIViewController {
textView.font = .systemFont(ofSize: 12, weight: .medium)
textView.textColor = DesignSystemColor.primaryText
textView.textAlignment = .center
textView.backgroundColor = DesignSystemColor.secondaryBackground
return textView
}()

Expand All @@ -64,12 +79,48 @@ final class LoginViewController: UIViewController {
fatalError("init(coder:) has not been implemented")
}

deinit {
Log.make().debug("\(Self.self) deinitialized")
if let timeObserverToken {
playerLayer?.player?.removeTimeObserver(timeObserverToken)
self.timeObserverToken = nil
}
}

override public func viewDidLoad() {
super.viewDidLoad()
configureUI()
bindViewModel()
bindUI()
}

private func setupVideoPlayerDuration() {
// 재생 종료 시점 감지
guard let duration = playerLayer?.player?.currentItem?.asset.duration
else {
return
}
let endTime = CMTimeSubtract(duration, CMTimeMake(value: 5, timescale: 1)) // 종료 5초 전
timeObserverToken = playerLayer?.player?.addBoundaryTimeObserver(forTimes: [NSValue(time: endTime)], queue: .main) {
[weak self] in
self?.slowDownPlayback()
}
}

private func slowDownPlayback() {
// 재생 속도를 점차 감소
guard var rate = playerLayer?.player?.rate else { return }
let decelerationFactor: Float = 0.98 // 감속 계수: 각 단계마다 속도를 98%로 줄임
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] timer in
if rate > 0.1 {
rate *= decelerationFactor
self?.playerLayer?.player?.rate = rate
} else {
timer.invalidate()
self?.playerLayer?.player?.pause()
}
}
}
}

// MARK: UI
Expand All @@ -80,6 +131,21 @@ private extension LoginViewController {

let safeArea = view.safeAreaLayoutGuide

// 비디오가 있으면 설정
if let playerLayer {
view.layer.addSublayer(playerLayer)
playerLayer.frame = view.bounds
playerLayer.player?.play()
// 가우시안 블러 효과 추가
addBlurEffect()

// 그라디언트 배경 추가
addGradientLayer()

// duration 설정
setupVideoPlayerDuration()
}

view.addSubview(logoImageView)
NSLayoutConstraint.activate([
logoImageView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
Expand Down Expand Up @@ -160,6 +226,21 @@ private extension LoginViewController {
authorizationController.presentationContextProvider = self
authorizationController.performRequests()
}

func addBlurEffect() {
let blurEffect = UIBlurEffect(style: .dark)
let blurredEffectView = UIVisualEffectView(effect: blurEffect)
blurredEffectView.frame = view.bounds
view.addSubview(blurredEffectView)
}

func addGradientLayer() {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = view.bounds
gradientLayer.colors = [UIColor.clear.cgColor, UIColor.black.cgColor]
gradientLayer.locations = [0.0, 1.0]
view.layer.addSublayer(gradientLayer)
}
}

// MARK: - LoginViewController + ASAuthorizationControllerDelegate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,6 @@ public final class SignUpFeatureCoordinator: SignUpFeatureCoordinating {
signUpProfileViewController: signUpProfileViewController
)

navigationController.pushViewController(signUpContainerViewController, animated: false)
navigationController.setViewControllers([signUpContainerViewController], animated: true)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "LogoForDarkModeWith75.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import UIKit

public extension UIImage {
static let logoImage: UIImage = .logo
static let logoImageDark: UIImage = .logoForDarkMode
static let pencilImage: UIImage = .pencil
static let noResultsImage: UIImage = .noResults
}