✨ Finish to replace Anime with Motion One for page animations
Page intro animation and reveal that has now been simplified as Motion One manages an inView option (that uses IntersectionObserver)
This commit is contained in:
@@ -4,17 +4,18 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { browser } from '$app/env'
|
||||
import { page } from '$app/stores'
|
||||
import { page, navigating } from '$app/stores'
|
||||
import { goto } from '$app/navigation'
|
||||
import { onMount, tick } from 'svelte'
|
||||
import { fade, scale } from 'svelte/transition'
|
||||
import { quartOut } from 'svelte/easing'
|
||||
import dayjs from 'dayjs'
|
||||
import { stagger, timeline } from 'motion'
|
||||
import { fetchAPI, getAssetUrlKey } from '$utils/api'
|
||||
import { previousPage } from '$utils/stores'
|
||||
import { DELAY } from '$utils/contants'
|
||||
import { throttle } from '$utils/functions'
|
||||
import { swipe } from '$utils/interactions/swipe'
|
||||
import dayjs from 'dayjs'
|
||||
import anime, { type AnimeTimelineInstance } from 'animejs'
|
||||
// Components
|
||||
import Metas from '$components/Metas.svelte'
|
||||
import SplitText from '$components/SplitText.svelte'
|
||||
@@ -219,76 +220,74 @@
|
||||
/**
|
||||
* Animations
|
||||
*/
|
||||
// Setup animations
|
||||
const timeline: AnimeTimelineInstance = anime.timeline({
|
||||
duration: 1600,
|
||||
easing: 'easeOutQuart',
|
||||
autoplay: false,
|
||||
})
|
||||
const animation = timeline([
|
||||
// First photo
|
||||
['.photo-page__picture.is-1', {
|
||||
y: [24, 0],
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
duration: 0.9,
|
||||
}],
|
||||
// Other photos
|
||||
['.photo-page__picture:not(.is-1)', {
|
||||
x: ['-150%', 0],
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 0.4,
|
||||
delay: stagger(0.1),
|
||||
opacity: { duration: 0.25 },
|
||||
}],
|
||||
|
||||
anime.set('.photo-page__picture', {
|
||||
opacity: 0,
|
||||
})
|
||||
anime.set('.photo-page__picture.is-1', {
|
||||
translateY: 24,
|
||||
})
|
||||
// Prev/Next buttons
|
||||
['.photo-page__controls .prev', {
|
||||
x: [-16, 0],
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 0.45,
|
||||
}],
|
||||
['.photo-page__controls .next', {
|
||||
x: [16, 0],
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 0.45,
|
||||
}],
|
||||
|
||||
// Photos
|
||||
timeline.add({
|
||||
targets: '.photo-page__picture.is-1',
|
||||
opacity: 1,
|
||||
translateY: 0,
|
||||
duration: 900,
|
||||
}, 250)
|
||||
timeline.add({
|
||||
targets: '.photo-page__picture:not(.is-1)',
|
||||
opacity: 1,
|
||||
translateX (element: HTMLElement) {
|
||||
const x = getComputedStyle(element).getPropertyValue('--offset-x').trim()
|
||||
return [`-${x}`, 0]
|
||||
// Infos
|
||||
['.photo-page__info > *', {
|
||||
y: [24, 0],
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 0.4,
|
||||
delay: stagger(0.3)
|
||||
}],
|
||||
|
||||
// Index
|
||||
['.photo-page__index', {
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 0.6,
|
||||
delay: stagger(0.2),
|
||||
duration: 0.9,
|
||||
}],
|
||||
// Fly each number
|
||||
['.photo-page__index .char', {
|
||||
y: ['300%', 0],
|
||||
}, {
|
||||
at: 1.1,
|
||||
delay: stagger(0.2),
|
||||
duration: 1,
|
||||
}],
|
||||
], {
|
||||
delay: $navigating ? DELAY.PAGE_LOADING / 1000 : 0,
|
||||
defaultOptions: {
|
||||
duration: 1.6,
|
||||
easing: quartOut,
|
||||
},
|
||||
delay: anime.stagger(55)
|
||||
}, 350)
|
||||
|
||||
// Prev/Next buttons
|
||||
timeline.add({
|
||||
targets: '.photo-page__controls button',
|
||||
translateX (item: HTMLElement) {
|
||||
let direction = item.classList.contains('prev') ? -1 : 1
|
||||
return [16 * direction, 0]
|
||||
},
|
||||
opacity: [0, 1],
|
||||
}, 450)
|
||||
|
||||
|
||||
// Infos
|
||||
timeline.add({
|
||||
targets: '.photo-page__info > *',
|
||||
translateY: [24, 0],
|
||||
opacity: [0, 1],
|
||||
delay: anime.stagger(200)
|
||||
}, 400)
|
||||
|
||||
|
||||
anime.set('.photo-page__index', {
|
||||
opacity: 0
|
||||
})
|
||||
// Index
|
||||
timeline.add({
|
||||
targets: '.photo-page__index',
|
||||
opacity: 1,
|
||||
duration: 900,
|
||||
}, 600)
|
||||
// Fly each number
|
||||
timeline.add({
|
||||
targets: '.photo-page__index .char',
|
||||
translateY: ['100%', 0],
|
||||
delay: anime.stagger(200),
|
||||
duration: 1000,
|
||||
}, 1100)
|
||||
animation.stop()
|
||||
|
||||
// Transition in
|
||||
requestAnimationFrame(timeline.play)
|
||||
// Run animation
|
||||
requestAnimationFrame(animation.play)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -146,13 +146,12 @@
|
||||
/**
|
||||
* Animations
|
||||
*/
|
||||
const animationDelay = $navigating ? DURATION.PAGE_IN : 0
|
||||
const animation = timeline([
|
||||
// Title word
|
||||
['.location-page__intro .word', {
|
||||
y: ['110%', 0],
|
||||
}, {
|
||||
at: 0.2 + animationDelay,
|
||||
at: 0.2,
|
||||
}],
|
||||
|
||||
// Illustration
|
||||
@@ -160,7 +159,7 @@
|
||||
scale: [1.06, 1],
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 0.4 + animationDelay,
|
||||
at: 0.4,
|
||||
duration: 2.4,
|
||||
}],
|
||||
|
||||
@@ -168,7 +167,7 @@
|
||||
['.location-page__intro .of', {
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 0.95 + animationDelay,
|
||||
at: 0.95,
|
||||
duration: 1.2,
|
||||
}],
|
||||
|
||||
@@ -177,11 +176,11 @@
|
||||
y: ['10%', 0],
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 0.9 + animationDelay,
|
||||
at: 0.9,
|
||||
duration: 1.2,
|
||||
}]
|
||||
], {
|
||||
delay: DELAY.PAGE_LOADING / 1000,
|
||||
delay: $navigating ? DELAY.PAGE_LOADING / 1000 : 0,
|
||||
defaultOptions: {
|
||||
duration: 1.6,
|
||||
easing: quartOut,
|
||||
|
||||
Reference in New Issue
Block a user