Add transitions to missing pages and attempt to animate it better?

This commit is contained in:
2021-12-06 15:10:39 +01:00
parent 8728d0f834
commit 0b772f26cb
9 changed files with 366 additions and 164 deletions

View File

@@ -12,6 +12,7 @@
import dayjs from 'dayjs'
import advancedFormat from 'dayjs/plugin/advancedFormat.js'
import anime from 'animejs'
import type { AnimeTimelineInstance } from 'animejs'
// Components
import Metas from '$components/Metas.svelte'
import SplitText from '$components/SplitText.svelte'
@@ -213,69 +214,88 @@
}
/**
* Transition: Anime timeline
*/
let timeline: AnimeTimelineInstance
if (browser) {
requestAnimationFrame(() => {
// Setup animations
timeline = anime.timeline({
duration: 1600,
easing: 'easeOutQuart',
})
anime.set('.viewer-photo__picture', {
opacity: 0,
})
anime.set('.viewer-photo__picture.is-1', {
translateY: 24,
})
// Photos
timeline.add({
targets: '.viewer-photo__picture.is-1',
opacity: 1,
translateY: 0,
duration: 900,
}, 250)
timeline.add({
targets: '.viewer-photo__picture:not(.is-0):not(.is-1)',
opacity: 1,
translateX (element: HTMLElement, index: number) {
const x = getComputedStyle(element).getPropertyValue('--offset-x').trim()
return [`-${x}`, 0]
},
delay: anime.stagger(55)
}, 500)
// Prev/Next buttons
timeline.add({
targets: '.viewer-photo__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: '.viewer-photo__info > *',
translateY: [24, 0],
opacity: [0, 1],
delay: anime.stagger(200)
}, 400)
anime.set('.viewer-photo__index', {
opacity: 0
})
// Index
timeline.add({
targets: '.viewer-photo__index',
opacity: 1,
duration: 900,
}, 600)
// Fly each number
timeline.add({
targets: '.viewer-photo__index .char',
translateY: ['100%', 0],
delay: anime.stagger(200),
duration: 1000,
}, 700)
})
}
onMount(() => {
// Setup animations
const timeline = anime.timeline({
duration: 1600,
easing: 'easeOutQuart',
// Transition in
requestAnimationFrame(() => {
timeline.play()
})
anime.set('.viewer-photo__picture', {
opacity: 0,
})
// Photos
timeline.add({
targets: '.viewer-photo__picture.is-1',
opacity: 1,
duration: 900,
}, 200)
timeline.add({
targets: '.viewer-photo__picture:not(.is-0):not(.is-1)',
opacity: 1,
translateX (element: HTMLElement, index: number) {
const x = getComputedStyle(element).getPropertyValue('--offset-x').trim()
return [`-${x}`, 0]
},
delay: anime.stagger(55)
}, 400)
// Prev button
timeline.add({
targets: '.viewer-photo__controls button:first-child',
translateX: [-16, 0],
opacity: [0, 1],
}, 600)
// Next button
timeline.add({
targets: '.viewer-photo__controls button:last-child',
translateX: [16, 0],
opacity: [0, 1],
}, 600)
// Infos
timeline.add({
targets: '.viewer-photo__info > *',
translateY: [24, 0],
opacity: [0, 1],
delay: anime.stagger(200)
}, 400)
anime.set('.viewer-photo__index', { opacity: 0 })
// Index
timeline.add({
targets: '.viewer-photo__index',
opacity: 1,
duration: 900,
}, 600)
timeline.add({
targets: '.viewer-photo__index .char',
translateY: ['100%', 0],
delay: anime.stagger(200),
duration: 1000,
}, 1100)
})
</script>
@@ -328,10 +348,10 @@
{/each}
<div class="viewer-photo__controls">
<ButtonCircle class="shadow-box-dark" disabled={!canGoNext} clone={true} on:click={goToPrevious}>
<ButtonCircle class="prev shadow-box-dark" disabled={!canGoNext} clone={true} on:click={goToPrevious}>
<IconArrow color="pink" flip={true} />
</ButtonCircle>
<ButtonCircle class="shadow-box-dark" disabled={!canGoPrev} clone={true} on:click={goToNext}>
<ButtonCircle class="next shadow-box-dark" disabled={!canGoPrev} clone={true} on:click={goToNext}>
<IconArrow color="pink" />
</ButtonCircle>
</div>

View File

@@ -1,7 +1,9 @@
<script lang="ts">
import { browser } from '$app/env'
import { navigating, page } from '$app/stores'
import { onMount } from 'svelte'
import anime from 'animejs'
import type { AnimeTimelineInstance } from 'animejs'
import dayjs from 'dayjs'
import advancedFormat from 'dayjs/plugin/advancedFormat.js'
import relativeTime from 'dayjs/plugin/relativeTime.js'
@@ -106,42 +108,53 @@
}
onMount(() => {
const timeline = anime.timeline({
duration: 1600,
easing: 'easeOutQuart'
/**
* Transition: Anime timeline
*/
let timeline: AnimeTimelineInstance
if (browser) {
requestAnimationFrame(() => {
timeline = anime.timeline({
duration: 1600,
easing: 'easeOutQuart',
autoplay: false,
})
// Title word
timeline.add({
targets: '.location-page__intro .word',
translateY: ['110%', 0],
delay: anime.stagger(200)
}, 200 + ($navigating ? DURATION.PAGE_IN : 0))
// Illustration
timeline.add({
targets: '.location-page__illustration',
scale: [1.06, 1],
opacity: [0, 1],
duration: 2400,
}, 400 + ($navigating ? DURATION.PAGE_IN : 0))
// Title of
timeline.add({
targets: '.location-page__intro .of',
opacity: [0, 1],
duration: 1200,
}, 1050 + ($navigating ? DURATION.PAGE_IN : 0))
// Description
timeline.add({
targets: '.location-page__description',
translateY: ['10%', 0],
opacity: [0, 1],
}, 900 + ($navigating ? DURATION.PAGE_IN : 0))
})
// Title word
timeline.add({
targets: '.location-page__intro .word',
translateY: ['110%', 0],
delay: anime.stagger(200)
}, 200 + ($navigating ? DURATION.PAGE_IN : 0))
// Illustration
timeline.add({
targets: '.location-page__illustration',
scale: [1.06, 1],
opacity: [0, 1],
duration: 2400,
}, 400 + ($navigating ? DURATION.PAGE_IN : 0))
// Title of
timeline.add({
targets: '.location-page__intro .of',
opacity: [0, 1],
duration: 1200,
}, 1050 + ($navigating ? DURATION.PAGE_IN : 0))
// Description
timeline.add({
targets: '.location-page__description',
translateY: ['10%', 0],
opacity: [0, 1],
}, 900 + ($navigating ? DURATION.PAGE_IN : 0))
}
onMount(() => {
// Photos IntersectionObserver
observerPhotos = new IntersectionObserver(entries => {
entries.forEach(({ isIntersecting, target }: IntersectionObserverEntry) => {
@@ -173,6 +186,11 @@
const existingPhotos = photosListEl.querySelectorAll('.house')
existingPhotos.forEach(el => observerPhotos.observe(el))
// Transition in
requestAnimationFrame(() => {
timeline.play()
})
// Destroy
return () => {