상세 컨텐츠

본문 제목

[로티파일즈] 간단하게 모션 애니메이션 적용해 보기

컨퍼런스

by Atlas 2024. 9. 19. 10:00

본문

728x90
반응형

시나리오 :  로티파일즈와 함께 쉽게 모션 애니메이션을 적용해 보자.
 
모바일 환경에서 모션 애니메이션을 적용하는 방법을 알아보고 간단하게 로티파일즈를 통해서도 적용해 보자.
 

1. GIF(Graphics Interchange Format)

여러 정지 이미지 프레임을 픽셀 기반으로 저장하여 연속적으로 재생하는 방식으로, 간단한 애니메이션을 표현하는 파일 형식

 
디자인팀에서 GIF 리소스를 전달받아 적용할 수 있는 방법도 있다. 
안드로이드의 경우 Glide 라이브러리나, iOS의 경우 Gifu 라이브러리 등이 구글에서 검색 시 상위 노출되는 방법들이다.
 

resource: LottieFiles

 
서드파티에 경우 중요시 봐야 하는 것 중 하나는 이 라이브러리가 장기적으로 지원가능유무이다. 
사용자들이 많고 커뮤니티가 활발한 경우에는 장기적으로 지원이 가능할 수도 있지만 자칫하면 업데이트 시에 라이브러리 자체를 제거하고 다른 방법을 찾아야 하는 경우도 고려해야 한다. 
 

Glide (왼쪽) , Gifu(오른쪽) 2024년 9월 기준

 
Glide, Gifu 두 라이브러리의 업데이트 시기를 보니 나쁘지는 않을 것 같다. 
안드로이드의 경우 Glide는 워낙 유명한 라이브러리이기도 하고 글라이드를 구글이 인수하였기 때문에 안정적으로 생각하고 사용할 것이다. 
 
Glide의 경우는 이미지 로딩 및 캐싱 즉, 주로 이미지 다운로드, 표시, 캐싱기능들을 같이 사용하는 경우는 좋은 선택지이다.  
 

2. Frame Animation

여러 이미지 프레임(정지 이미지)을 일정한 시간 간격으로 교체하며 재생하는 방식으로, GIF처럼 보이도록 하는 기법
resource: LottieFiles

 
 
GIF의 경우 디자인팀에게 완성된 형태로 전달을 받다 보니 제어의 제한이 있고 개발적인 측면에서는 압축률이 낮고 파일 크기가 큰 편이다.
이 부분을 프레임 애니메이션을 통해서 진행 볼 수 있다. 
 
프레임 애니메이션의 장점은 모든 플랫폼에서 기본적으로 지원한다는 장점과 커스터마이징이 가능하다는 것이다. 
 
각 모바일 플랫폼에서 적용해 보자. 

안드로이드 전체 코드 

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            Lottifiles_androidTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    ImageAnimation(
                        modifier = Modifier.padding(innerPadding)
                    )
                }
            }
        }
    }
}


@Composable
fun ImageAnimation(
    modifier: Modifier
) {
    // 이미지 리소스를 리스트로 정의
    val imageList = listOf(
        R.drawable.loading01,
        R.drawable.loading02,
        R.drawable.loading03,
        R.drawable.loading04,
        R.drawable.loading05,
        R.drawable.loading06,
        R.drawable.loading07,
        R.drawable.loading08,
        R.drawable.loading09,
        R.drawable.loading10
    )

    var currentIndex by remember { mutableStateOf(0) }
    var isVisible by remember { mutableStateOf(true) }

    LaunchedEffect(currentIndex) {
        while (true) {
            delay(200)
            isVisible = false
            delay(0)
            currentIndex = (currentIndex + 1) % imageList.size // 다음 이미지로 변경
            isVisible = true
        }
    }

    // 이미지 애니메이션
    Box(
        modifier = modifier.fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        AnimatedVisibility(
            visible = isVisible,
            enter = androidx.compose.animation.fadeIn(animationSpec = tween(500)), // 페이드 인 애니메이션
            exit = androidx.compose.animation.fadeOut(animationSpec = tween(500)) // 페이드 아웃 애니메이션
        ) {
            Image(
                painter = painterResource(id = imageList[currentIndex]),
                contentDescription = "Animated Image"
            )
        }
    }
}

 
 

iOS 전체 코드 

import SwiftUI

struct ContentView: View {
    // 이미지 파일 이름 리스트
    let imageList = [
        "loading01",
        "loading02",
        "loading03",
        "loading04",
        "loading05",
        "loading06",
        "loading07",
        "loading08",
        "loading09",
        "loading10"
    ]
    // 현재 인덱스를 기억하는 상태 변수
    @State private var currentIndex = 0
    @State private var isVisible = true
    
    // 애니메이션 타이머 (0.2초마다 업데이트)
    let timer = Timer.publish(every: 0.2, on: .main, in: .common).autoconnect()
    
    var body: some View {
        ZStack {
            if isVisible {
                Image(imageList[currentIndex])
                    .resizable()
                    .scaledToFit()
                    .transition(.opacity) // 페이드 인, 페이드 아웃 효과
            }
        }
        .onReceive(timer) { _ in
            withAnimation(.easeInOut(duration: 0.5)) {
                isVisible = false
            }
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                currentIndex = (currentIndex + 1) % imageList.count
                isVisible = true
            }
        }
    }
}

 

3. Lottie JSON

벡터 기반의 애니메이션을 JSON 형식으로 저장하여, 고해상도에서도 작은 용량으로 복잡한 애니메이션을 구현하는 방식

 
 
프레임 애니메이션의 경우 간단하지만 직접 구현을 해야 하다 보니 필요한 모든 것을 개발자가 직접 작성해야 한다. 
직접적으로 이미지를 다루다 보니 메모리 사용량이 높을 수도 있다는 점도 생각해 보면 한번쯤 고민에 빠지게 된다. 
 
마지막으로 간단하게 모션 애니메이션을 적용해 볼 수 있는 방법은 로티파일즈를 적용하는 것이다. 
 

resource: LottieFiles

 
 
서드파트의 경우 앞서 언급했듯이 장기적인 지원유무가 중요한 점 중 하나인데 업데이트 내역을 보면 아주 만족스럽다 👍

로티 android (왼쪽), iOS (오른쪽) 2024년 9월 기준

 

3-1. iOS 적용방법

1. SPM 추가 

https://github.com/airbnb/lottie-spm.git

 
2. 리소스 추가 

 
3. 전체 코드 

import SwiftUI
import Lottie

struct ContentView: View {
    var body: some View {
      VStack {
        Spacer()
        Text("lottie-spm")
        Spacer()

        LottieView(animation: .named("LottieLogo1"))
          .playing(loopMode: .loop)
      }
    }
}

 
 
사용법

 LottieView(animation: .named("LottieLogo1"))
          .playing(loopMode: .loop)

 
 

3-2. android 적용방법

1.  gradle 추가 

implementation("com.airbnb.android:lottie-compose:6.5.2")

 
2. res > raw 폴더에 리소스 추가 

 
3. 전체 코드 

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            Loader()
        }
    }
}

@Composable
fun Loader() {
    val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.lottie_logo_1))
    val progress by animateLottieCompositionAsState(composition)
    LottieAnimation(
        composition = composition,
        progress = { progress },
    )
}

 
간단하게 각 플랫폼에서 적용할 수 있는 것을 확인하였다.
 
포스팅에서 비교를 진행한 3가지 방법을 비교하면서 마무리! 
 

 
 
 

마무리

- 모든 개발환경을 존중합니다. 어떤 방법이든 현재 본인이 선택한 것이 현재 상황에서 최선의 선택인 것을 존중합니다 👍
- 로티파일즈를 통해 간단하게 모션 애니메이션 구현 가능하다 👍
 
 
 
ref. 
 
https://github.com/PotatoArtie/Potato-iOS/tree/master/Labs/Playground/Lottifiles_android

Potato-iOS/Labs/Playground/Lottifiles_android at master · PotatoArtie/Potato-iOS

Contribute to PotatoArtie/Potato-iOS development by creating an account on GitHub.

github.com

 
 
https://developers.lottiefiles.com/

Developer Portal - LottieFiles

Lottie Developer Portal is your single source for all things Lottie tooling and documentation.

developers.lottiefiles.com

 
https://github.com/kaishin/Gifu

GitHub - kaishin/Gifu: High-performance animated GIF support for iOS in Swift

High-performance animated GIF support for iOS in Swift - kaishin/Gifu

github.com

 
https://github.com/airbnb/lottie-spm

GitHub - airbnb/lottie-spm: Swift Package Manager support for Lottie, an iOS library to natively render After Effects vector ani

Swift Package Manager support for Lottie, an iOS library to natively render After Effects vector animations - airbnb/lottie-spm

github.com

 
 
https://airbnb.io/lottie/#/android-compose

Lottie Docs

airbnb.io

 

반응형

관련글 더보기

댓글 영역