diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 54fe210..ea8c53a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -104,6 +104,8 @@ dependencies { implementation("com.google.android.filament:gltfio-android:1.57.1") implementation("com.google.android.filament:filament-utils-android:1.57.1") + implementation("com.airbnb.android:lottie-compose:6.5.0") + testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) diff --git a/app/src/main/assets/models/level_2.glb b/app/src/main/assets/models/level_2.glb index 3ac46da..92e1080 100644 Binary files a/app/src/main/assets/models/level_2.glb and b/app/src/main/assets/models/level_2.glb differ diff --git a/app/src/main/assets/models/level_3.glb b/app/src/main/assets/models/level_3.glb index 843e872..3d197bf 100644 Binary files a/app/src/main/assets/models/level_3.glb and b/app/src/main/assets/models/level_3.glb differ diff --git a/app/src/main/assets/models/level_4.glb b/app/src/main/assets/models/level_4.glb index 3eac3c8..56e6aa7 100644 Binary files a/app/src/main/assets/models/level_4.glb and b/app/src/main/assets/models/level_4.glb differ diff --git a/app/src/main/java/com/ssafy/tiggle/data/model/piggybank/response/PiggyBankEntriesResponseDto.kt b/app/src/main/java/com/ssafy/tiggle/data/model/piggybank/response/PiggyBankEntriesResponseDto.kt index bbeac1c..21112f1 100644 --- a/app/src/main/java/com/ssafy/tiggle/data/model/piggybank/response/PiggyBankEntriesResponseDto.kt +++ b/app/src/main/java/com/ssafy/tiggle/data/model/piggybank/response/PiggyBankEntriesResponseDto.kt @@ -15,7 +15,7 @@ data class PiggyBankEntryItem( val id: String, val type: String, val amount: Long, - val occurredAt: String, + val occurredDate: String, val title: String ) @@ -30,6 +30,6 @@ fun PiggyBankEntryItem.toDomain(): PiggyBankEntry = id = id, type = type, amount = amount, - occurredAt = occurredAt, + occurredAt = occurredDate, title = title ) \ No newline at end of file diff --git a/app/src/main/java/com/ssafy/tiggle/presentation/navigation/NavigationGraph.kt b/app/src/main/java/com/ssafy/tiggle/presentation/navigation/NavigationGraph.kt index 8991972..cbd6ab7 100644 --- a/app/src/main/java/com/ssafy/tiggle/presentation/navigation/NavigationGraph.kt +++ b/app/src/main/java/com/ssafy/tiggle/presentation/navigation/NavigationGraph.kt @@ -172,7 +172,8 @@ fun NavigationGraph( onBackClick = { navBackStack.removeLastOrNull() }, onFinish = { navBackStack.removeLastOrNull() - } + }, + isEdit = key.isEdit ) } @@ -199,6 +200,7 @@ fun NavigationGraph( is Screen.MainAccountDetail -> NavEntry(key) { MainAccountDetailScreen( accountNo = key.accountNo, + onBackClick = {navBackStack.removeLastOrNull()} ) } diff --git a/app/src/main/java/com/ssafy/tiggle/presentation/ui/growth/Character3D.kt b/app/src/main/java/com/ssafy/tiggle/presentation/ui/growth/Character3D.kt index a625f2d..f2eac5b 100644 --- a/app/src/main/java/com/ssafy/tiggle/presentation/ui/growth/Character3D.kt +++ b/app/src/main/java/com/ssafy/tiggle/presentation/ui/growth/Character3D.kt @@ -3,20 +3,21 @@ package com.ssafy.tiggle.presentation.ui.growth import android.annotation.SuppressLint import android.content.Context import android.view.Choreographer -import android.view.SurfaceView import android.view.MotionEvent -import androidx.compose.runtime.* +import android.view.SurfaceView +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.viewinterop.AndroidView -import com.google.android.filament.utils.ModelViewer -import com.google.android.filament.utils.Utils -import com.google.android.filament.IndirectLight -import com.google.android.filament.gltfio.ResourceLoader -import android.graphics.PixelFormat -import android.util.Log import com.google.android.filament.EntityManager import com.google.android.filament.LightManager +import com.google.android.filament.gltfio.ResourceLoader +import com.google.android.filament.utils.ModelViewer +import com.google.android.filament.utils.Utils import java.io.IOException import java.nio.ByteBuffer import java.nio.ByteOrder @@ -27,6 +28,7 @@ import kotlin.math.PI */ // 전역 변수 private var baseTransform: FloatArray? = null + // 애니메이션 자동재생용 상태 private var animIndex: Int = -1 private var animDurationSec: Float = 0f @@ -122,6 +124,7 @@ fun Character3D( } ) } + private fun setupFrontLight(modelViewer: ModelViewer) { // 배경은 투명/스카이박스 없음 (필요시 색만 바꾸세요) modelViewer.scene.skybox = null @@ -135,12 +138,13 @@ private fun setupFrontLight(modelViewer: ModelViewer) { val key = EntityManager.get().create() LightManager.Builder(LightManager.Type.DIRECTIONAL) .color(1.0f, 1.0f, 1.0f) // 순백색 라이트 - .intensity(200_000f) // 밝기 (필요하면 80k~200k 사이로 조절) + .intensity(450_000f) // 밝기 (필요하면 80k~200k 사이로 조절) .direction(0f, -0.2f, -1f) // ✅ 화면 정면(–Z)에서 약간 아래로 .castShadows(false) // 그림자 비활성화 .build(modelViewer.engine, key) modelViewer.scene.addEntity(key) } + /** * 투명 배경 설정 */ @@ -195,10 +199,10 @@ private fun loadModelForLevel(context: Context, modelViewer: ModelViewer, level: // column-major 4x4, translation은 [12],[13],[14] 슬롯 val trs = floatArrayOf( - scale, 0f, 0f, 0f, - 0f, scale,0f, 0f, - 0f, 0f, scale,0f, - 0f, translateY, 0f, 1f + scale, 0f, 0f, 0f, + 0f, scale, 0f, 0f, + 0f, 0f, scale, 0f, + 0f, translateY, 0f, 1f ) tm.setTransform(rootInst, trs) @@ -277,6 +281,7 @@ private fun enableHorizontalDragRotation(surfaceView: SurfaceView, modelViewer: MotionEvent.ACTION_DOWN -> { lastTouchX = event.x } + MotionEvent.ACTION_MOVE -> { val dx = event.x - lastTouchX lastTouchX = event.x @@ -319,9 +324,9 @@ private fun multiplyMat4(a: FloatArray, b: FloatArray): FloatArray { for (j in 0..3) { var sum = 0f for (k in 0..3) { - sum += a[i + k*4] * b[k + j*4] + sum += a[i + k * 4] * b[k + j * 4] } - out[i + j*4] = sum + out[i + j * 4] = sum } } return out diff --git a/app/src/main/java/com/ssafy/tiggle/presentation/ui/growth/GrowthScreen.kt b/app/src/main/java/com/ssafy/tiggle/presentation/ui/growth/GrowthScreen.kt index 9c7d5a0..9244311 100644 --- a/app/src/main/java/com/ssafy/tiggle/presentation/ui/growth/GrowthScreen.kt +++ b/app/src/main/java/com/ssafy/tiggle/presentation/ui/growth/GrowthScreen.kt @@ -1,17 +1,23 @@ package com.ssafy.tiggle.presentation.ui.growth +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.FastOutLinearInEasing +import androidx.compose.animation.core.LinearEasing +import androidx.compose.animation.core.tween import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable +import androidx.compose.foundation.gestures.detectDragGestures import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -21,27 +27,41 @@ import androidx.compose.material3.CardDefaults import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel +import com.airbnb.lottie.compose.LottieAnimation +import com.airbnb.lottie.compose.LottieCompositionSpec +import com.airbnb.lottie.compose.rememberLottieComposition import com.ssafy.tiggle.R import com.ssafy.tiggle.core.utils.Formatter import com.ssafy.tiggle.presentation.ui.components.TiggleScreenLayout import com.ssafy.tiggle.presentation.ui.theme.AppTypography import com.ssafy.tiggle.presentation.ui.theme.TiggleBlue -import com.ssafy.tiggle.presentation.ui.theme.TiggleGrayLight import com.ssafy.tiggle.presentation.ui.theme.TiggleGrayText import com.ssafy.tiggle.presentation.ui.theme.TiggleSkyBlue +import kotlinx.coroutines.launch +import kotlin.math.roundToInt @Composable fun GrowthScreen( @@ -55,7 +75,8 @@ fun GrowthScreen( TiggleScreenLayout( showBackButton = false, - showLogo = false + showLogo = false, + enableScroll = false ) { Column( modifier = modifier @@ -64,7 +85,6 @@ fun GrowthScreen( ) { Spacer(Modifier.height(30.dp)) - // 제목 Text( text = "나의 성장", color = Color.Black, @@ -80,13 +100,13 @@ fun GrowthScreen( ) Spacer(Modifier.height(30.dp)) - // 성장 카드 (아이콘들 포함) - GrowthCard( - uiState=uiState, - onDonationHistoryClick = onDonationHistoryClick, - onDonationStatusClick = onDonationStatusClick, - onDonationRankingClick = onDonationRankingClick - ) + GrowthCard( + uiState = uiState, + onDonationHistoryClick = onDonationHistoryClick, + onDonationStatusClick = onDonationStatusClick, + onDonationRankingClick = onDonationRankingClick, + modifier = Modifier.weight(1f) + ) } } } @@ -101,7 +121,6 @@ private fun GrowthIconRow( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Start ) { - // 기부 기록 Spacer(Modifier.width(6.dp)) GrowthIconItem( iconRes = R.drawable.donation_history_icon, @@ -109,14 +128,12 @@ private fun GrowthIconRow( onClick = onDonationHistoryClick ) Spacer(Modifier.width(6.dp)) - // 현황 GrowthIconItem( iconRes = R.drawable.donation_status_icon, label = "현황", onClick = onDonationStatusClick ) Spacer(Modifier.width(6.dp)) - // 랭킹 GrowthIconItem( iconRes = R.drawable.donation_ranking, label = "랭킹", @@ -156,54 +173,102 @@ private fun GrowthCard( onDonationHistoryClick: () -> Unit, onDonationStatusClick: () -> Unit, onDonationRankingClick: () -> Unit, + modifier: Modifier = Modifier ) { Card( - modifier = Modifier.fillMaxSize(), + modifier = modifier.fillMaxWidth(), shape = RoundedCornerShape(16.dp), colors = CardDefaults.cardColors(containerColor = TiggleSkyBlue), elevation = CardDefaults.cardElevation(0.dp) ) { Column( - modifier = Modifier - .fillMaxWidth() - .fillMaxHeight() - .padding(24.dp), + modifier = Modifier.padding(24.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - // 기부 관련 아이콘들 (기부 기록, 현황, 랭킹) GrowthIconRow( onDonationHistoryClick = onDonationHistoryClick, onDonationStatusClick = onDonationStatusClick, onDonationRankingClick = onDonationRankingClick ) - Spacer(Modifier.height(24.dp)) - - // 캐릭터 이미지 (현재는 비워둠) - Box(Modifier.fillMaxWidth().height(500.dp).background(Color.Transparent) ) { + Box( + modifier = Modifier + .weight(1f) + .fillMaxWidth() + .heightIn(min = 240.dp) + .background(Color.Transparent) + ) { + // 1) 캐릭터 Character3D(level = uiState.growth.level, modifier = Modifier.fillMaxSize()) - } - Spacer(Modifier.height(20.dp)) + // 2) 중앙 오버레이 Lottie (방법2: 진행도 직접 애니메이션) + val LOTTIE_SIZE_DP = 260.dp // ← 더 크게 + val LOTTIE_DURATION_MS = 3000 // ← 원하는 재생 시간(ms) 여기서 조절 + val SLOW_PORTION = 0.85f + val MID_PROGRESS = 0.60f + var playLottie by remember { mutableStateOf(false) } + val composition by rememberLottieComposition( + LottieCompositionSpec.RawRes(R.raw.heart2) // res/raw/heart.json + ) - // 레벨 정보 - Row( - verticalAlignment = Alignment.CenterVertically - ) { + // 진행도 0f → 1f 를 내가 정한 시간에 맞춰 애니메이션 + val lottieProgress = remember { Animatable(0f) } + + LaunchedEffect(playLottie, composition) { + if (playLottie && composition != null) { + lottieProgress.snapTo(0f) + val t1 = (LOTTIE_DURATION_MS * SLOW_PORTION).toInt() + lottieProgress.animateTo( + targetValue = MID_PROGRESS, + animationSpec = tween(durationMillis = t1, easing = LinearEasing) + ) + + // 2) 뒤 구간: 남은 시간에 MID_PROGRESS → 1.0 (막판에 몰아서 빨라짐) + val t2 = LOTTIE_DURATION_MS - t1 + lottieProgress.animateTo( + targetValue = 1f, + animationSpec = tween( + durationMillis = t2, + easing = FastOutLinearInEasing + ) + ) + playLottie = false // 1회 재생 후 종료 + } + } + + if (playLottie && composition != null) { + Box( + modifier = Modifier + .align(Alignment.Center) + .size(LOTTIE_SIZE_DP) // ← 크기 키움 + ) { + LottieAnimation( + composition = composition, + progress = { lottieProgress.value } + ) + } + } + + // 3) 드래그 하트 (중앙 드롭 성공 시 Lottie 트리거 + 하트 원위치 복귀) + DraggableHeartDropTrigger( + iconRes = R.drawable.heart, + iconSize = 50.dp, + triggerRadius = 80.dp, + startOffsetBottomPadding = 16.dp, + onDropInCenter = { playLottie = true } + ) + } + + Row(verticalAlignment = Alignment.CenterVertically) { Text( - text = "레벨 ${uiState.growth.level+1}", + text = "레벨 ${uiState.growth.level + 1}", fontSize = 14.sp, color = TiggleGrayText, modifier = Modifier - .background( - Color.White.copy(alpha = 0.7f), - RoundedCornerShape(12.dp) - ) + .background(Color.White.copy(alpha = 0.7f), RoundedCornerShape(12.dp)) .padding(horizontal = 12.dp, vertical = 4.dp) ) - Spacer(Modifier.width(12.dp)) - Text( text = "쏠", fontSize = 18.sp, @@ -214,7 +279,6 @@ private fun GrowthCard( Spacer(Modifier.height(16.dp)) - // 총 티끌 금액 Text( text = "총 티끌: ${Formatter.formatCurrency(uiState.growth.totalAmount)}", fontSize = 16.sp, @@ -224,9 +288,8 @@ private fun GrowthCard( Spacer(Modifier.height(12.dp)) - // 진행 바 LinearProgressIndicator( - progress = { 0.7f }, // TODO: 실제 진행률 계산 + progress = { 0.7f }, // TODO: 실제 진행률 modifier = Modifier .fillMaxWidth() .height(8.dp) @@ -237,7 +300,6 @@ private fun GrowthCard( Spacer(Modifier.height(8.dp)) - // 다음 레벨까지 필요한 금액 Text( text = "다음 레벨까지 ${Formatter.formatCurrency(uiState.growth.toNextLevel.toLong())}", fontSize = 12.sp, @@ -247,6 +309,89 @@ private fun GrowthCard( } } +/** + * 중앙 원(반경 triggerRadius) 안에 드롭 시 onDropInCenter 호출. + * 드롭 후 하트는 시작 위치(하단 중앙)로 부드럽게 복귀. + */ +@Composable +private fun DraggableHeartDropTrigger( + iconRes: Int, + iconSize: Dp, + triggerRadius: Dp, + startOffsetBottomPadding: Dp = 16.dp, + onDropInCenter: () -> Unit +) { + val density = LocalDensity.current + val scope = rememberCoroutineScope() + + var parentW by remember { mutableStateOf(0f) } + var parentH by remember { mutableStateOf(0f) } + val iconSizePx = with(density) { iconSize.toPx() } + val triggerRadiusPx = with(density) { triggerRadius.toPx() } + val bottomPadPx = with(density) { startOffsetBottomPadding.toPx() } + + val offsetX = remember { Animatable(0f) } + val offsetY = remember { Animatable(0f) } + var initialized by remember { mutableStateOf(false) } + + Box( + modifier = Modifier + .fillMaxSize() + .onGloballyPositioned { c -> + parentW = c.size.width.toFloat() + parentH = c.size.height.toFloat() + if (!initialized && parentW > 0f && parentH > 0f) { + val sx = parentW / 2f - iconSizePx / 2f + val sy = parentH - iconSizePx - bottomPadPx + scope.launch { + offsetX.snapTo(sx) + offsetY.snapTo(sy) + } + initialized = true + } + } + ) { + if (initialized) { + Image( + painter = painterResource(id = iconRes), + contentDescription = "드래그 하트", + modifier = Modifier + .size(iconSize) + .offset { IntOffset(offsetX.value.roundToInt(), offsetY.value.roundToInt()) } + .pointerInput(parentW, parentH, iconSizePx) { + detectDragGestures( + onDrag = { change, drag -> + // change.consume() // 버전에 따라 경고 나면 생략해도 OK + val nx = (offsetX.value + drag.x) + .coerceIn(0f, (parentW - iconSizePx).coerceAtLeast(0f)) + val ny = (offsetY.value + drag.y) + .coerceIn(0f, (parentH - iconSizePx).coerceAtLeast(0f)) + scope.launch { offsetX.snapTo(nx) } + scope.launch { offsetY.snapTo(ny) } + }, + onDragEnd = { + val centerX = parentW / 2f + val centerY = parentH / 2f + val heartCenterX = offsetX.value + iconSizePx / 2f + val heartCenterY = offsetY.value + iconSizePx / 2f + val dist = kotlin.math.hypot( + heartCenterX - centerX, heartCenterY - centerY + ) + + if (dist <= triggerRadiusPx) onDropInCenter() + + val sx = parentW / 2f - iconSizePx / 2f + val sy = parentH - iconSizePx - bottomPadPx + scope.launch { offsetX.animateTo(sx, tween(220)) } + scope.launch { offsetY.animateTo(sy, tween(220)) } + } + ) + } + ) + } + } +} + @Preview(showBackground = true) @Composable private fun GrowthScreenPreview() { diff --git a/app/src/main/java/com/ssafy/tiggle/presentation/ui/growth/LevelModels.kt b/app/src/main/java/com/ssafy/tiggle/presentation/ui/growth/LevelModels.kt index c9277cd..9ff9083 100644 --- a/app/src/main/java/com/ssafy/tiggle/presentation/ui/growth/LevelModels.kt +++ b/app/src/main/java/com/ssafy/tiggle/presentation/ui/growth/LevelModels.kt @@ -1,24 +1,21 @@ package com.ssafy.tiggle.presentation.ui.growth -import android.content.ContentValues.TAG -import android.util.Log - object LevelModels { - fun assetPathFor(level: Int): String { - val bucket = when { - level ==0 -> "level_1.glb" - level ==1 -> "level_2.glb" - level ==2 -> "level_3.glb" - else -> "level_4.glb" - } - return "models/$bucket" - } + fun assetPathFor(level: Int): String { + val bucket = when { + level == 0 -> "level_1.glb" + level == 1 -> "level_2.glb" + level == 2 -> "level_3.glb" + else -> "level_4.glb" + } + return "models/$bucket" + } - // 필요 시 스케일/초기 카메라 등도 레벨별로 다르게 - fun scaleFor(level: Int): Float = when { - level < 5 -> 1.0f - level < 10 -> 1.0f - level < 20 -> 1.1f - else -> 1.2f - } + // 필요 시 스케일/초기 카메라 등도 레벨별로 다르게 + fun scaleFor(level: Int): Float = when { + level < 5 -> 1.0f + level < 10 -> 1.0f + level < 20 -> 1.1f + else -> 1.2f + } } \ No newline at end of file diff --git a/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/MainAccountDetailScreen.kt b/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/MainAccountDetailScreen.kt index 6303e25..8db7dbf 100644 --- a/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/MainAccountDetailScreen.kt +++ b/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/MainAccountDetailScreen.kt @@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape @@ -25,6 +26,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel @@ -47,7 +49,7 @@ fun MainAccountDetailScreen( TiggleScreenLayout( showBackButton = true, - title = "오늘 모인 티끌", + title = "나의 계좌 입출금", onBackClick = onBackClick, contentPadding = PaddingValues(0.dp), enableScroll = false @@ -102,7 +104,7 @@ fun MainAccountDetailScreen( fun TransactionItem(tx: DomainTransaction) { val borderColor = Color(0xFFE0E0E0) // 캡처 느낌의 연한 회색 테두리 val timeTextColor = Color(0xFF9AA3AD) // 연한 회색 텍스트 - val amountColor = if (tx.transactionType == "출금") Color(0xFFD32F2F) else TiggleBlue + val amountColor = if (tx.transactionType == "출금(이체)") Color(0xFFD32F2F) else TiggleBlue Card( modifier = Modifier.fillMaxWidth(), @@ -111,7 +113,7 @@ fun TransactionItem(tx: DomainTransaction) { elevation = CardDefaults.cardElevation(defaultElevation = 0.dp), border = androidx.compose.foundation.BorderStroke(1.dp, borderColor) ) { - Column(modifier = Modifier.padding(vertical = 10.dp, horizontal = 15.dp)) { + Column(modifier = Modifier.padding(vertical = 20.dp, horizontal = 15.dp)) { // 상단 행: 날짜 + 이름 / 금액 Row( @@ -127,24 +129,34 @@ fun TransactionItem(tx: DomainTransaction) { color = timeTextColor ) Spacer(Modifier.height(4.dp)) - Text( - text = tx.description, - fontSize = 15.sp, - fontWeight = FontWeight.ExtraBold, - color = Color(0xFF1C1F23) - ) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = tx.description, + fontSize = 13.sp, + fontWeight = FontWeight.ExtraBold, + color = Color(0xFF1C1F23), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.width(200.dp) + ) + // 금액 (+/-) + Text( + text = buildString { + append(if (tx.transactionType == "출금(이체)") "- " else "+ ") + append("${formatAmount(tx.amount.toLong())}원") + }, + fontSize = 15.sp, + fontWeight = FontWeight.ExtraBold, + color = amountColor + ) + } } - // 금액 (+/-) - Text( - text = buildString { - append(if (tx.transactionType == "출금") "- " else "+ ") - append("${formatAmount(tx.amount.toLong())}원") - }, - fontSize = 18.sp, - fontWeight = FontWeight.ExtraBold, - color = amountColor - ) + } Spacer(Modifier.height(18.dp)) diff --git a/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/PiggyBankDetailRoute.kt b/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/PiggyBankDetailRoute.kt index 29f3c64..e08daf1 100644 --- a/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/PiggyBankDetailRoute.kt +++ b/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/PiggyBankDetailRoute.kt @@ -28,7 +28,7 @@ fun PiggyBankDetailRoute( onTabChange = { tab -> viewModel.setSelectedTab(tab) when (tab) { - PiggyTab.SpareChange -> viewModel.reloadEntriesByType("CHANGE") + PiggyTab.SpareChange -> viewModel.reloadEntriesByType("TIGGLE") PiggyTab.DutchPay -> viewModel.reloadEntriesByType("DUTCHPAY") } }, diff --git a/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/PiggyBankDetailScreen.kt b/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/PiggyBankDetailScreen.kt index 6542dcc..008e193 100644 --- a/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/PiggyBankDetailScreen.kt +++ b/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/PiggyBankDetailScreen.kt @@ -64,7 +64,7 @@ fun PiggyBankDetailsScreen( onBack: () -> Unit = {}, onMore: () -> Unit = {}, onTabChange: (PiggyTab) -> Unit = {}, - onItemClick: (PiggyBankEntry) -> Unit = {} + onItemClick: (PiggyBankEntry) -> Unit = {}, ) { TiggleScreenLayout( showBackButton = true, @@ -108,12 +108,11 @@ fun PiggyBankDetailsScreen( SectionTitle(text = "주간 자투리 적립") Spacer(Modifier.height(10.dp)) - Box(Modifier.fillMaxSize()) { + Column () { // 카드 높이만큼 하단 여백(패딩) 확보: 100~120dp 권장 LazyColumn( modifier = Modifier - .fillMaxSize() - .padding(bottom = 108.dp), + .weight(2f), verticalArrangement = Arrangement.spacedBy(10.dp), contentPadding = PaddingValues(horizontal = 20.dp, vertical = 0.dp) ) { @@ -126,8 +125,8 @@ fun PiggyBankDetailsScreen( title = "자투리 적립 방식", message = "매주 월요일에 내 계좌 잔액의 천원 미만 자투리 금액이 자동으로 저금통에 적립됩니다.", modifier = Modifier - .align(Alignment.BottomCenter) - .padding(horizontal = 20.dp, vertical = 20.dp) + .weight(1f) + .padding(horizontal = 20.dp, vertical = 30.dp) ) } } @@ -136,11 +135,10 @@ fun PiggyBankDetailsScreen( SectionTitle(text = "더치페이 잔돈 적립") Spacer(Modifier.height(10.dp)) - Box(Modifier.fillMaxSize()) { + Column () { LazyColumn( modifier = Modifier - .fillMaxSize() - .padding(bottom = 108.dp), + .weight(2f), verticalArrangement = Arrangement.spacedBy(10.dp), contentPadding = PaddingValues(horizontal = 20.dp, vertical = 0.dp) ) { @@ -153,8 +151,8 @@ fun PiggyBankDetailsScreen( title = "더치페이 적립 방식", message = "더치페이할 때 ‘내가 더 낼게요’를 선택하면 자투리 금액이 저금통에 적립됩니다.", modifier = Modifier - .align(Alignment.BottomCenter) - .padding(horizontal = 20.dp, vertical = 20.dp) + .weight(1f) + .padding(horizontal = 20.dp, vertical = 30.dp) ) } } @@ -296,7 +294,7 @@ private fun EntryItemCard(item: PiggyBankEntry, onClick: () -> Unit) { ) { // 아이콘 매핑 val icon = when (item.type.lowercase()) { - "자투리", "spare", "weekly", "change" -> R.drawable.coin_icon + "자투리", "spare", "weekly", "change", "tiggle" -> R.drawable.coin_icon "더치페이", "dutch", "dutchpay" -> R.drawable.dutchpay_icon else -> null } @@ -336,7 +334,7 @@ private fun EntryItemCard(item: PiggyBankEntry, onClick: () -> Unit) { Column(horizontalAlignment = Alignment.End) { Text( text = "+ ${formatAmount(item.amount)}", - color = MaterialTheme.colorScheme.primary, + color = TiggleBlue, fontWeight = FontWeight.Bold ) Spacer(Modifier.height(6.dp)) @@ -345,7 +343,8 @@ private fun EntryItemCard(item: PiggyBankEntry, onClick: () -> Unit) { "자투리", "spare", "weekly", - "change" + "change", + "tiggle" ) ) "주간 적립" else "더치페이", color = MaterialTheme.colorScheme.onSurfaceVariant, diff --git a/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/PiggyBankScreen.kt b/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/PiggyBankScreen.kt index 6469f79..f861e02 100644 --- a/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/PiggyBankScreen.kt +++ b/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/PiggyBankScreen.kt @@ -1,5 +1,7 @@ package com.ssafy.tiggle.presentation.ui.piggybank +import androidx.compose.animation.core.animateIntAsState +import androidx.compose.animation.core.tween import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Canvas import androidx.compose.foundation.Image @@ -28,6 +30,9 @@ import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -111,7 +116,6 @@ fun PiggyBankScreen( style = AppTypography.bodySmall ) - Spacer(Modifier.height(50.dp)) Spacer(Modifier.height(50.dp)) if (uiState.hasPiggyBank) { @@ -281,7 +285,6 @@ private fun TodaySavingBanner(uiState: PiggyBankState, onClick: () -> Unit) { Box( modifier = Modifier .fillMaxWidth() - .height(130.dp) .clip(RoundedCornerShape(radius)) .background( brush = Brush.horizontalGradient( @@ -303,12 +306,18 @@ private fun TodaySavingBanner(uiState: PiggyBankState, onClick: () -> Unit) { style = AppTypography.bodySmall ) Spacer(Modifier.height(6.dp)) - Text( - "${uiState.piggyBankAccount.currentAmount}원", - color = Color.White, - fontSize = 34.sp, - fontWeight = FontWeight.ExtraBold + val target = uiState.piggyBankAccount.currentAmount // Long + + AnimatedNumberCounter( + targetValue = target ) +// Text( +// text = "${Formatter.formatCurrency(animated.toLong())}원", +// color = Color.White, +// fontSize = 34.sp, +// fontWeight = FontWeight.ExtraBold +// ) + Spacer(Modifier.height(10.dp)) Text( "+ 지난주에 ${ @@ -343,7 +352,6 @@ private fun AccountCard( Column( modifier = Modifier .fillMaxWidth() - .height(130.dp) .clip(RoundedCornerShape(radius)) .background(Color.White) .border(1.dp, Color(0x11000000), RoundedCornerShape(radius)) @@ -429,6 +437,33 @@ private fun DutchButtonsRow(onStatus: () -> Unit, onStart: () -> Unit) { } } +@Composable +private fun AnimatedNumberCounter( + targetValue: Long, + modifier: Modifier = Modifier +) { + var isVisible by remember { mutableStateOf(false) } + + LaunchedEffect(Unit) { + isVisible = true + } + + val animatedValue by animateIntAsState( + targetValue = if (isVisible) targetValue.toInt() else 0, + animationSpec = tween( + durationMillis = 1000, + easing = androidx.compose.animation.core.EaseOutQuart + ), + label = "number_animation" + ) + + Text( + text = "${Formatter.formatCurrency(animatedValue.toLong())}", + color = Color.White, + fontSize = 34.sp, + fontWeight = FontWeight.ExtraBold + ) +} @Preview @Composable diff --git a/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/PiggyBankViewModel.kt b/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/PiggyBankViewModel.kt index ce9f6de..a83c3bb 100644 --- a/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/PiggyBankViewModel.kt +++ b/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/PiggyBankViewModel.kt @@ -1,5 +1,6 @@ package com.ssafy.tiggle.presentation.ui.piggybank +import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.ssafy.tiggle.domain.entity.piggybank.EsgCategory @@ -15,6 +16,7 @@ import retrofit2.HttpException import java.text.DecimalFormat import javax.inject.Inject +private const val TAG = "PiggyBankViewModel" @HiltViewModel class PiggyBankViewModel @Inject constructor( val useCases: PiggyBankUseCases @@ -276,40 +278,54 @@ class PiggyBankViewModel @Inject constructor( viewModelScope.launch { _uiState.update { it.copy(isLoading = true, errorMessage = null) } - // 병렬 호출 - val changeDeferred = async { - useCases.getPiggyBankEntryUseCase( - type = "CHANGE", - cursor = changeCursor, - size = size, - sortKey = sortKey - ) - } - val dutchDeferred = async { - useCases.getPiggyBankEntryUseCase( - type = "DUTCHPAY", - cursor = dutchCursor, - size = size, - sortKey = sortKey - ) - } + try { + // 병렬 호출 + val changeDeferred = async { + useCases.getPiggyBankEntryUseCase( + type = "TIGGLE", + cursor = changeCursor, + size = size, + sortKey = sortKey + ) + } + val dutchDeferred = async { + useCases.getPiggyBankEntryUseCase( + type = "DUTCHPAY", + cursor = dutchCursor, + size = size, + sortKey = sortKey + ) + } - val changeRes = changeDeferred.await() - val dutchRes = dutchDeferred.await() + val changeRes = changeDeferred.await() + val dutchRes = dutchDeferred.await() - val changeList = changeRes.getOrElse { emptyList() } - val dutchList = dutchRes.getOrElse { emptyList() } + val changeList = changeRes.getOrElse { emptyList() } + val dutchList = dutchRes.getOrElse { emptyList() } - val error = changeRes.exceptionOrNull()?.message - ?: dutchRes.exceptionOrNull()?.message + val error = changeRes.exceptionOrNull()?.message + ?: dutchRes.exceptionOrNull()?.message - _uiState.update { - it.copy( - changeList = changeList, - dutchpayList = dutchList, - isLoading = false, - errorMessage = error - ) + Log.d(TAG, "loadAllPiggyEntries: $changeList") + Log.d(TAG, "loadAllPiggyEntries: $dutchList") + _uiState.update { + it.copy( + changeList = changeList, + dutchpayList = dutchList, + isLoading = false, + errorMessage = error + ) + } + }catch (e:Exception){ + Log.e(TAG, "loadAllPiggyEntries failed", e) + _uiState.update { + it.copy( + changeList = emptyList(), + dutchpayList = emptyList(), + isLoading = false, + errorMessage = e.message + ) + } } } } @@ -321,11 +337,16 @@ class PiggyBankViewModel @Inject constructor( sortKey: String? = null ) { viewModelScope.launch { + val serverType = when (type.uppercase()) { + "CHANGE" -> "TIGGLE" + "DUTCHPAY" -> "DUTCHPAY" + else -> type.uppercase() + } val result = useCases.getPiggyBankEntryUseCase(type, cursor, size, null, null, sortKey) result.onSuccess { list -> _uiState.update { s -> when (type) { - "CHANGE" -> s.copy(changeList = list) + "CHANGE","TIGGLE" -> s.copy(changeList = list) "DUTCHPAY" -> s.copy(dutchpayList = list) else -> s } diff --git a/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/RegisterAccountScreen.kt b/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/RegisterAccountScreen.kt index d27df37..3194c8c 100644 --- a/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/RegisterAccountScreen.kt +++ b/app/src/main/java/com/ssafy/tiggle/presentation/ui/piggybank/RegisterAccountScreen.kt @@ -39,6 +39,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.media3.extractor.text.Subtitle import com.ssafy.tiggle.R import com.ssafy.tiggle.domain.entity.piggybank.AccountHolder import com.ssafy.tiggle.domain.entity.piggybank.RegisterAccount @@ -56,7 +57,7 @@ fun RegisterAccountScreen( modifier: Modifier = Modifier, viewModel: RegisterAccountViewModel = hiltViewModel(), onBackClick: () -> Unit = {}, - isEdit: Boolean = false, + isEdit: Boolean, onFinish: () -> Unit = {} ) { val uiState by viewModel.uiState.collectAsState() @@ -69,7 +70,10 @@ fun RegisterAccountScreen( viewModel.goToPreviousStep() } } - val title = if (isEdit) "계좌 수정" else "계좌 등록" + val title = if (!isEdit) "계좌 등록" else "계좌 수정" + val sub_title=if (!isEdit) "계좌 등록" else "계좌 수정" + val desc=if (!isEdit) "잔돈 적립과 기부를 위해\n" + + " 내 계좌를 등록해주세요." else "새로운 계좌를 등록해주세요." when (uiState.registerAccountStep) { RegisterAccountStep.ACCOUNT -> { @@ -79,7 +83,9 @@ fun RegisterAccountScreen( onAccountChange = viewModel::updateAccountNum, onConfirmClick = { viewModel.fetchAccountHolder() }, onDismissError = viewModel::clearError, - title = title + title = title, + subTitle=sub_title, + desc=desc ) } @@ -131,7 +137,9 @@ fun AccountInputScreen( onAccountChange: (String) -> Unit, onConfirmClick: () -> Unit, onDismissError: () -> Unit, - title: String + title: String, + subTitle: String, + desc:String ) { TiggleScreenLayout( showBackButton = true, @@ -175,14 +183,14 @@ fun AccountInputScreen( modifier = Modifier.align(Alignment.CenterHorizontally) ) { Text( - text = "계좌 등록", + text = subTitle, color = Color.Black, fontSize = 22.sp, style = AppTypography.headlineLarge, ) Spacer(Modifier.height(6.dp)) Text( - text = "잔돈 적립과 기부를 위해\n 내 계좌를 등록해주세요.", + text = desc, color = TiggleGrayText, fontSize = 13.sp, style = AppTypography.bodySmall, @@ -777,7 +785,9 @@ fun AccountInputPreview() { onAccountChange = {}, onConfirmClick = {}, onDismissError = {}, - title = "" + title = "", + subTitle = "", + desc = "" ) } diff --git a/app/src/main/res/drawable/coin_icon.png b/app/src/main/res/drawable/coin_icon.png deleted file mode 100644 index 7440acc..0000000 Binary files a/app/src/main/res/drawable/coin_icon.png and /dev/null differ diff --git a/app/src/main/res/drawable/coin_icon.webp b/app/src/main/res/drawable/coin_icon.webp new file mode 100644 index 0000000..0433add Binary files /dev/null and b/app/src/main/res/drawable/coin_icon.webp differ diff --git a/app/src/main/res/drawable/dutchpay_icon.png b/app/src/main/res/drawable/dutchpay_icon.png deleted file mode 100644 index fc188c2..0000000 Binary files a/app/src/main/res/drawable/dutchpay_icon.png and /dev/null differ diff --git a/app/src/main/res/drawable/dutchpay_icon.webp b/app/src/main/res/drawable/dutchpay_icon.webp new file mode 100644 index 0000000..2b77ea8 Binary files /dev/null and b/app/src/main/res/drawable/dutchpay_icon.webp differ diff --git a/app/src/main/res/drawable/heart.webp b/app/src/main/res/drawable/heart.webp new file mode 100644 index 0000000..c27ed40 Binary files /dev/null and b/app/src/main/res/drawable/heart.webp differ diff --git a/app/src/main/res/drawable/icon_people.png b/app/src/main/res/drawable/icon_people.png deleted file mode 100644 index 742fc3c..0000000 Binary files a/app/src/main/res/drawable/icon_people.png and /dev/null differ diff --git a/app/src/main/res/drawable/icon_people.webp b/app/src/main/res/drawable/icon_people.webp new file mode 100644 index 0000000..08541d7 Binary files /dev/null and b/app/src/main/res/drawable/icon_people.webp differ diff --git a/app/src/main/res/drawable/icon_planet.png b/app/src/main/res/drawable/icon_planet.png deleted file mode 100644 index 9196bd2..0000000 Binary files a/app/src/main/res/drawable/icon_planet.png and /dev/null differ diff --git a/app/src/main/res/drawable/icon_planet.webp b/app/src/main/res/drawable/icon_planet.webp new file mode 100644 index 0000000..848db34 Binary files /dev/null and b/app/src/main/res/drawable/icon_planet.webp differ diff --git a/app/src/main/res/drawable/icon_prosperity.png b/app/src/main/res/drawable/icon_prosperity.png deleted file mode 100644 index 6709325..0000000 Binary files a/app/src/main/res/drawable/icon_prosperity.png and /dev/null differ diff --git a/app/src/main/res/drawable/icon_prosperity.webp b/app/src/main/res/drawable/icon_prosperity.webp new file mode 100644 index 0000000..4677953 Binary files /dev/null and b/app/src/main/res/drawable/icon_prosperity.webp differ diff --git a/app/src/main/res/drawable/linked_card_option.png b/app/src/main/res/drawable/linked_card_option.png deleted file mode 100644 index fd535cd..0000000 Binary files a/app/src/main/res/drawable/linked_card_option.png and /dev/null differ diff --git a/app/src/main/res/drawable/linked_card_option.webp b/app/src/main/res/drawable/linked_card_option.webp new file mode 100644 index 0000000..ba5c63c Binary files /dev/null and b/app/src/main/res/drawable/linked_card_option.webp differ diff --git a/app/src/main/res/raw/heart.json b/app/src/main/res/raw/heart.json new file mode 100644 index 0000000..e4552df --- /dev/null +++ b/app/src/main/res/raw/heart.json @@ -0,0 +1 @@ +{"v":"5.5.8","fr":29.9700012207031,"ip":0,"op":362.000014744562,"w":1000,"h":1000,"nm":"HEART FRAME","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":0,"nm":"HEART 4","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[196.126,788.709,0],"ix":2},"a":{"a":0,"k":[100,367.5,0],"ix":1},"s":{"a":0,"k":[40,40,100],"ix":6}},"ao":0,"w":200,"h":735,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"HEART 4","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[728,850,0],"ix":2},"a":{"a":0,"k":[100,367.5,0],"ix":1},"s":{"a":0,"k":[40,40,100],"ix":6}},"ao":0,"w":200,"h":735,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":0,"nm":"HEART 4","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[738,498,0],"ix":2},"a":{"a":0,"k":[100,367.5,0],"ix":1},"s":{"a":0,"k":[40,40,100],"ix":6}},"ao":0,"w":200,"h":735,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":0,"nm":"HEART 4","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[318,632,0],"ix":2},"a":{"a":0,"k":[100,367.5,0],"ix":1},"s":{"a":0,"k":[40,40,100],"ix":6}},"ao":0,"w":200,"h":735,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":0,"nm":"HEART 4","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[446,228,0],"ix":2},"a":{"a":0,"k":[100,367.5,0],"ix":1},"s":{"a":0,"k":[40,40,100],"ix":6}},"ao":0,"w":200,"h":735,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":0,"nm":"HEART 4","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[158,252,0],"ix":2},"a":{"a":0,"k":[100,367.5,0],"ix":1},"s":{"a":0,"k":[40,40,100],"ix":6}},"ao":0,"w":200,"h":735,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":0,"nm":"HEART 4","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-31,"ix":10},"p":{"a":0,"k":[340,802,0],"ix":2},"a":{"a":0,"k":[100,367.5,0],"ix":1},"s":{"a":0,"k":[40,40,100],"ix":6}},"ao":0,"w":200,"h":735,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":0,"nm":"HEART 4","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-31,"ix":10},"p":{"a":0,"k":[816,736,0],"ix":2},"a":{"a":0,"k":[100,367.5,0],"ix":1},"s":{"a":0,"k":[40,40,100],"ix":6}},"ao":0,"w":200,"h":735,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":0,"nm":"HEART 4","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-31,"ix":10},"p":{"a":0,"k":[826,384,0],"ix":2},"a":{"a":0,"k":[100,367.5,0],"ix":1},"s":{"a":0,"k":[40,40,100],"ix":6}},"ao":0,"w":200,"h":735,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":0,"nm":"HEART 4","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-31,"ix":10},"p":{"a":0,"k":[406,518,0],"ix":2},"a":{"a":0,"k":[100,367.5,0],"ix":1},"s":{"a":0,"k":[40,40,100],"ix":6}},"ao":0,"w":200,"h":735,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":0,"nm":"HEART 4","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-31,"ix":10},"p":{"a":0,"k":[534,114,0],"ix":2},"a":{"a":0,"k":[100,367.5,0],"ix":1},"s":{"a":0,"k":[40,40,100],"ix":6}},"ao":0,"w":200,"h":735,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":0,"nm":"HEART 4","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-31,"ix":10},"p":{"a":0,"k":[246,138,0],"ix":2},"a":{"a":0,"k":[100,367.5,0],"ix":1},"s":{"a":0,"k":[40,40,100],"ix":6}},"ao":0,"w":200,"h":735,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":14,"ix":10},"p":{"a":0,"k":[181.055,641.26,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[46.951,46.951,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":14,"ix":10},"p":{"a":0,"k":[746,712,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[46.951,46.951,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":15,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":14,"ix":10},"p":{"a":0,"k":[746.551,371.024,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[46.951,46.951,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":14,"ix":10},"p":{"a":0,"k":[336,494,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[46.951,46.951,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":17,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":14,"ix":10},"p":{"a":0,"k":[464,90,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[46.951,46.951,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":18,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":14,"ix":10},"p":{"a":0,"k":[176,114,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[46.951,46.951,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":19,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":14,"ix":10},"p":{"a":0,"k":[586.063,778.504,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[78,78,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":20,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":14,"ix":10},"p":{"a":0,"k":[906,780,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[78,78,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":21,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":14,"ix":10},"p":{"a":0,"k":[916,428,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[78,78,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":22,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":14,"ix":10},"p":{"a":0,"k":[543.449,397.559,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[78,78,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":23,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":14,"ix":10},"p":{"a":0,"k":[816,158,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[78,78,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":24,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":14,"ix":10},"p":{"a":0,"k":[660,102,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[78,78,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":25,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-8,"ix":10},"p":{"a":0,"k":[54.961,804.598,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[78,78,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":26,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-8,"ix":10},"p":{"a":0,"k":[538.961,914.441,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[78,78,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":27,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-8,"ix":10},"p":{"a":0,"k":[554.126,575.717,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[78,78,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":28,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-8,"ix":10},"p":{"a":0,"k":[231.953,452.614,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[78,78,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":29,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-8,"ix":10},"p":{"a":0,"k":[890,278,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[78,78,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":30,"ty":0,"nm":"HEART 5","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-8,"ix":10},"p":{"a":0,"k":[94,186,0],"ix":2},"a":{"a":0,"k":[100,320,0],"ix":1},"s":{"a":0,"k":[78,78,100],"ix":6}},"ao":0,"w":200,"h":640,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":31,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-11,"ix":10},"p":{"a":0,"k":[194,936,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":32,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-11,"ix":10},"p":{"a":0,"k":[706.976,946.898,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":33,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-11,"ix":10},"p":{"a":0,"k":[806.74,618.52,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":34,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-11,"ix":10},"p":{"a":0,"k":[402.488,765.118,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":35,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-11,"ix":10},"p":{"a":0,"k":[868,66,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":36,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-11,"ix":10},"p":{"a":0,"k":[377.071,358.173,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":37,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-11,"ix":10},"p":{"a":0,"k":[70.803,592.409,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[86,86,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":38,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-11,"ix":10},"p":{"a":0,"k":[620,660,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[86,86,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":39,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-11,"ix":10},"p":{"a":0,"k":[686,216,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[86,86,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":40,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-11,"ix":10},"p":{"a":0,"k":[76.142,442,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[86,86,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":41,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-11,"ix":10},"p":{"a":0,"k":[338,38,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[86,86,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":42,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-11,"ix":10},"p":{"a":0,"k":[50,62,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[86,86,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":43,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":17,"ix":10},"p":{"a":0,"k":[344,882,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[52,52,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":44,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":17,"ix":10},"p":{"a":0,"k":[868,874,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[52,52,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":45,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":17,"ix":10},"p":{"a":0,"k":[878,522,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[52,52,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":46,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":17,"ix":10},"p":{"a":0,"k":[458,656,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[52,52,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":47,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":17,"ix":10},"p":{"a":0,"k":[618,294,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[52,52,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0},{"ddd":0,"ind":48,"ty":0,"nm":"HEART 6","refId":"comp_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":17,"ix":10},"p":{"a":0,"k":[298,276,0],"ix":2},"a":{"a":0,"k":[100,363,0],"ix":1},"s":{"a":0,"k":[52,52,100],"ix":6}},"ao":0,"w":200,"h":726,"ip":0,"op":362.000014744562,"st":0,"bm":0}]},{"id":"comp_1","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Element01","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":2,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":15,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":30,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":42,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":54,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":67,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":82,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":94,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":103,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":116,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":131,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":143,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":155,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":168,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":183,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":195,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":203,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":216,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":231,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":243,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":255,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":268,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":283,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":295,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":303,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":316,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":331,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":343,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":355,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":368,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":383,"s":[100]},{"t":394.99976608867,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":1,"s":[101.5,370.047,0],"to":[0,-51,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":45,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":53,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":97,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":102,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":146,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":154,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":198,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":202,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":246,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":254,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":298,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":302,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":346,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":354,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,51,0]},{"t":397.999766210862,"s":[101.5,64.047,0]}],"ix":2},"a":{"a":0,"k":[-704.087,0,0],"ix":1},"s":{"a":0,"k":[6.768,5.654,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[374,300],[165.994,-333.229],[120.29,-99.411],[-457.169,-331]],"o":[[-126,-98],[-182.006,-333.229],[-359.958,297.479],[470.831,-333]],"v":[[72.696,-558.406],[-703.994,-420.771],[-1181.287,-520.507],[-713.605,785.226]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":-181,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":-5.00000020365417,"op":595.404024251302,"st":3.99600016276042,"bm":0}]},{"id":"comp_2","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Element01","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":14,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":29,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":41,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":53,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":66,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":81,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":93,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":102,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":115,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":130,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":142,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":167,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":182,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":194,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":202,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":215,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":230,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":242,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":254,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":267,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":282,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":294,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":302,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":315,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":330,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":342,"s":[0]},{"t":353.999764418705,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[101.5,370.047,0],"to":[0,-51,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":44,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":52,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":96,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":101,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":145,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":153,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":197,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":201,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":245,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":253,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":297,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":301,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":345,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,-51,0]},{"t":352.999764377975,"s":[101.5,370.047,0]}],"ix":2},"a":{"a":0,"k":[-704.087,0,0],"ix":1},"s":{"a":0,"k":[3,3.43,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[374,300],[165.994,-333.229],[120.29,-99.411],[-457.169,-331]],"o":[[-126,-98],[-182.006,-333.229],[-359.958,297.479],[470.831,-333]],"v":[[-118,-594],[-703.994,-420.771],[-1510.527,-490.039],[-706.218,555.302]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.426989626417,0.29411761714,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":-181,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":77,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":-15.0000006109625,"op":595.404024251302,"st":3.99600016276042,"bm":0}]},{"id":"comp_3","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Element01","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":14,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":29,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":41,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":53,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":66,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":81,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":93,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":102,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":115,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":130,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":142,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":154,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":167,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":182,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":194,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":202,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":215,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":230,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":242,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":254,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":267,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":282,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":294,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":302,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":315,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":330,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":342,"s":[0]},{"t":353.999764418705,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[101.5,370.047,0],"to":[0,-51,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":44,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":52,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":96,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":101,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":145,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":153,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":197,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":201,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":245,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":253,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":297,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":301,"s":[101.5,370.047,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":345,"s":[101.5,64.047,0],"to":[0,0,0],"ti":[0,-51,0]},{"t":352.999764377975,"s":[101.5,370.047,0]}],"ix":2},"a":{"a":0,"k":[-704.087,0,0],"ix":1},"s":{"a":0,"k":[3.983,4.163,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[374,300],[165.993,-333.229],[120.29,-99.411],[-457.169,-331]],"o":[[-126,-98],[-182.007,-333.229],[-359.958,297.479],[470.831,-333]],"v":[[202.096,-587.995],[-703.994,-420.771],[-1298.29,-590.589],[-706.218,555.302]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":-181,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":70,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":-29.0000011811942,"op":595.404024251302,"st":3.99600016276042,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"1","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":27.0000010997325,"op":389.000015844295,"st":27.0000010997325,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"1","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[500,500,0],"ix":2},"a":{"a":0,"k":[500,500,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"w":1000,"h":1000,"ip":0,"op":362.000014744562,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/app/src/main/res/raw/heart2.json b/app/src/main/res/raw/heart2.json new file mode 100644 index 0000000..134786b --- /dev/null +++ b/app/src/main/res/raw/heart2.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":240,"w":1920,"h":1080,"nm":"Final anim heart","ddd":0,"assets":[{"id":"comp_0","nm":"Full","fr":30,"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Full hearts 2","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[946,560,0],"ix":2,"l":2},"a":{"a":0,"k":[960,540,0],"ix":1,"l":2},"s":{"a":0,"k":[-100,100,100],"ix":6,"l":2}},"ao":0,"w":1920,"h":1080,"ip":0,"op":213,"st":-80,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"Full hearts 3","refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1004,696,0],"ix":2,"l":2},"a":{"a":0,"k":[960,540,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":1920,"h":1080,"ip":0,"op":213,"st":-89,"bm":0}]},{"id":"comp_1","nm":"Full hearts","fr":60,"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Hearts","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":7,"ix":10},"p":{"a":0,"k":[1338,412,0],"ix":2,"l":2},"a":{"a":0,"k":[960,540,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"w":1920,"h":1080,"ip":3,"op":903,"st":3,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"Hearts","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-11,"ix":10},"p":{"a":0,"k":[912,580,0],"ix":2,"l":2},"a":{"a":0,"k":[960,540,0],"ix":1,"l":2},"s":{"a":0,"k":[80,80,100],"ix":6,"l":2}},"ao":0,"w":1920,"h":1080,"ip":2,"op":902,"st":2,"bm":0},{"ddd":0,"ind":3,"ty":0,"nm":"Hearts","refId":"comp_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1032,346,0],"ix":2,"l":2},"a":{"a":0,"k":[960,540,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":1920,"h":1080,"ip":0,"op":900,"st":0,"bm":0}]},{"id":"comp_2","nm":"Hearts","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"heart Outlines 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":201,"s":[-5.7]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":219,"s":[16.3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":236.42,"s":[-10.7]},{"t":254.033203125,"s":[-5.7]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.574,"y":1},"o":{"x":0.459,"y":0},"t":201,"s":[1123.715,403.85,0],"to":[1.892,-6.658,0],"ti":[-1.865,6.563,0]},{"t":258.06640625,"s":[1127.89,280.155,0]}],"ix":2,"l":2},"a":{"a":0,"k":[300,300,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.59,0.59,0.59],"y":[0.521,0.521,1]},"o":{"x":[0.164,0.164,0.164],"y":[0,0,0]},"t":201,"s":[0,0,100]},{"i":{"x":[0.59,0.59,0.59],"y":[1,1,1]},"o":{"x":[0.422,0.422,0.422],"y":[-4.61,-4.61,0]},"t":221,"s":[11,11,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.422,0.422,0.422],"y":[0,0,0]},"t":238,"s":[10,10,100]},{"t":258.06640625,"s":[0,0,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-45.423,-78.607],[-105.068,-26.379],[62.964,26.168],[-218.06,45.708]],"o":[[0,0],[262.55,65.917],[-184.447,-69.076],[55.312,-8.968]],"v":[[-2.21,-117.568],[144.791,-246.794],[22.233,247.006],[-153.193,-223.077]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.9372549019607843,0.34901960784313724,0.34901960784313724,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[300,300.856],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-7,"op":900,"st":-7,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"heart Outlines 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":199,"s":[-12.7]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":212.775,"s":[-47]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":236.389,"s":[-14]},{"t":256.06640625,"s":[-12.7]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.368,"y":1},"o":{"x":0.424,"y":0},"t":199,"s":[1086.14,430.57,0],"to":[0.868,-3.053,0],"ti":[-2.89,10.168,0]},{"t":256.06640625,"s":[1048.565,356.255,0]}],"ix":2,"l":2},"a":{"a":0,"k":[300,300,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.015,0.015,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":199,"s":[0,0,100]},{"i":{"x":[0.015,0.015,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":219,"s":[6,6,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":238,"s":[6,6,100]},{"t":258.033203125,"s":[0,0,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-45.423,-78.607],[-105.068,-26.379],[62.964,26.168],[-218.06,45.708]],"o":[[0,0],[262.55,65.917],[-184.447,-69.076],[55.312,-8.968]],"v":[[-2.21,-117.568],[144.791,-246.794],[22.233,247.006],[-153.193,-223.077]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.9372549019607843,0.34901960784313724,0.34901960784313724,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[300,300.856],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-7,"op":900,"st":-7,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"heart Outlines 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":197,"s":[31.3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":210.775,"s":[48.3]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":228.486,"s":[31.3]},{"t":250.12890625,"s":[48.3]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.324,"y":1},"o":{"x":0.345,"y":0},"t":197,"s":[1150.435,421.385,0],"to":[7.793,-10.438,0],"ti":[-10.02,10.716,0]},{"t":258,"s":[1210.555,357.09,0]}],"ix":2,"l":2},"a":{"a":0,"k":[300,300,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.015,0.015,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":197,"s":[0,0,100]},{"i":{"x":[0.015,0.015,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":217,"s":[6,6,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":236,"s":[6,6,100]},{"t":262,"s":[0,0,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-45.423,-78.607],[-105.068,-26.379],[62.964,26.168],[-218.06,45.708]],"o":[[0,0],[262.55,65.917],[-184.447,-69.076],[55.312,-8.968]],"v":[[-2.21,-117.568],[144.791,-246.794],[22.233,247.006],[-153.193,-223.077]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.9372549019607843,0.34901960784313724,0.34901960784313724,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[300,300.856],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-7,"op":900,"st":-7,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"heart Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":103,"s":[-31]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":124,"s":[-7.2]},{"i":{"x":[0.572],"y":[0.677]},"o":{"x":[0.19],"y":[0]},"t":147,"s":[10]},{"i":{"x":[0.704],"y":[1]},"o":{"x":[0.334],"y":[-0.937]},"t":175,"s":[-3]},{"t":199,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.628,"y":0.583},"o":{"x":0.283,"y":0},"t":103,"s":[1617.42,1023.45,0],"to":[-224.353,-89.193,0],"ti":[118.706,171.802,0]},{"i":{"x":0.66,"y":1},"o":{"x":0.322,"y":0.589},"t":163,"s":[1207.02,700.132,0],"to":[-104.912,-151.838,0],"ti":[-4.762,49.834,0]},{"t":221,"s":[1127,403.43,0]}],"ix":2,"l":2},"a":{"a":0,"k":[300,300,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":93,"s":[0,0,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":103,"s":[28.056,28.056,100]},{"i":{"x":[0.691,0.691,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":118,"s":[28.056,28.056,100]},{"i":{"x":[0.199,0.199,0.833],"y":[1,1,1]},"o":{"x":[0.22,0.22,0.333],"y":[0,0,0]},"t":199,"s":[28.056,28.056,100]},{"t":209,"s":[0,0,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-45.423,-78.607],[-105.068,-26.379],[62.964,26.168],[-218.06,45.708]],"o":[[0,0],[262.55,65.917],[-184.447,-69.076],[55.312,-8.968]],"v":[[-2.21,-117.568],[144.791,-246.794],[22.233,247.006],[-153.193,-223.077]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.9372549019607843,0.34901960784313724,0.34901960784313724,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[300,300.856],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":907,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Full","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[960,540,0],"ix":2,"l":2},"a":{"a":0,"k":[960,540,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":1920,"h":1080,"ip":0,"op":213,"st":0,"bm":0}],"markers":[{"tm":212,"cm":"","dr":0}]} \ No newline at end of file