[wip] Switch from Anime to Motion One for page animations
This commit is contained in:
@@ -3,14 +3,15 @@
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import { navigating, page } from '$app/stores'
|
||||
import { page, navigating } from '$app/stores'
|
||||
import { onMount } from 'svelte'
|
||||
import anime, { type AnimeTimelineInstance } from 'animejs'
|
||||
import { timeline } from 'motion'
|
||||
import dayjs from 'dayjs'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime.js'
|
||||
import { getAssetUrlKey } from '$utils/helpers'
|
||||
import { quartOut } from '$animations/easings'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
import { DURATION } from '$utils/contants'
|
||||
import { DELAY, DURATION } from '$utils/contants'
|
||||
import { photoFields } from '.'
|
||||
// Components
|
||||
import Metas from '$components/Metas.svelte'
|
||||
@@ -146,43 +147,51 @@
|
||||
/**
|
||||
* Animations
|
||||
*/
|
||||
// Transition in
|
||||
const timeline: AnimeTimelineInstance = anime.timeline({
|
||||
duration: 1600,
|
||||
easing: 'easeOutQuart',
|
||||
autoplay: false,
|
||||
const animationDelay = $navigating ? DURATION.PAGE_IN : 0
|
||||
const animation = timeline([
|
||||
// Title word
|
||||
['.location-page__intro .word', {
|
||||
y: ['110%', 0],
|
||||
}, {
|
||||
at: 0.2 + animationDelay,
|
||||
}],
|
||||
|
||||
// Illustration
|
||||
['.location-page__illustration', {
|
||||
scale: [1.06, 1],
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 0.4 + animationDelay,
|
||||
duration: 2.4,
|
||||
}],
|
||||
|
||||
// Title of
|
||||
['.location-page__intro .of', {
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 0.95 + animationDelay,
|
||||
duration: 1.2,
|
||||
}],
|
||||
|
||||
// Description
|
||||
['.location-page__description', {
|
||||
y: ['10%', 0],
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 0.9 + animationDelay,
|
||||
duration: 1.2,
|
||||
}]
|
||||
], {
|
||||
delay: DELAY.PAGE_LOADING / 1000,
|
||||
defaultOptions: {
|
||||
duration: 1.6,
|
||||
easing: quartOut,
|
||||
},
|
||||
})
|
||||
animation.stop()
|
||||
|
||||
// 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,
|
||||
}, 950 + ($navigating ? DURATION.PAGE_IN : 0))
|
||||
|
||||
// Description
|
||||
timeline.add({
|
||||
targets: '.location-page__description',
|
||||
translateY: ['10%', 0],
|
||||
opacity: [0, 1],
|
||||
}, 900 + ($navigating ? DURATION.PAGE_IN : 0))
|
||||
|
||||
requestAnimationFrame(timeline.play)
|
||||
// Run animation
|
||||
requestAnimationFrame(animation.play)
|
||||
|
||||
|
||||
// Destroy
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte'
|
||||
import anime, { type AnimeTimelineInstance } from 'animejs'
|
||||
import { stagger, timeline } from 'motion'
|
||||
import { DELAY } from '$utils/contants'
|
||||
import { quartOut } from 'svelte/easing'
|
||||
// Components
|
||||
import Metas from '$components/Metas.svelte'
|
||||
import PageTransition from '$components/PageTransition.svelte'
|
||||
@@ -19,39 +21,40 @@
|
||||
/**
|
||||
* Animations
|
||||
*/
|
||||
// Setup animations
|
||||
const timeline: AnimeTimelineInstance = anime.timeline({
|
||||
duration: 1600,
|
||||
easing: 'easeOutQuart',
|
||||
autoplay: false,
|
||||
const animation = timeline([
|
||||
// Heading
|
||||
['.heading .text', {
|
||||
y: [24, 0],
|
||||
opacity: [0, 1],
|
||||
}],
|
||||
|
||||
// Categories
|
||||
['.credits__category', {
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 0,
|
||||
delay: stagger(0.35, { start: 0.5 }),
|
||||
}],
|
||||
|
||||
// Names
|
||||
['.credits__category > ul > li', {
|
||||
y: [24, 0],
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 1.1,
|
||||
delay: stagger(0.35),
|
||||
}],
|
||||
], {
|
||||
delay: DELAY.PAGE_LOADING / 1000,
|
||||
defaultOptions: {
|
||||
duration: 1.6,
|
||||
easing: quartOut,
|
||||
},
|
||||
})
|
||||
animation.stop()
|
||||
|
||||
anime.set('.heading .text, .credits__category > ul > li', {
|
||||
opacity: 0,
|
||||
translateY: 24,
|
||||
})
|
||||
anime.set('.credits__category', {
|
||||
opacity: 0,
|
||||
})
|
||||
|
||||
// Elements
|
||||
timeline.add({
|
||||
targets: '.heading .text, .credits__category',
|
||||
opacity: 1,
|
||||
translateY: 0,
|
||||
delay: anime.stagger(350),
|
||||
}, 500)
|
||||
|
||||
// Names
|
||||
timeline.add({
|
||||
targets: '.credits__category > ul > li',
|
||||
opacity: 1,
|
||||
translateY: 0,
|
||||
delay: anime.stagger(350),
|
||||
}, 1100)
|
||||
|
||||
// Transition in
|
||||
requestAnimationFrame(timeline.play)
|
||||
// Run animation
|
||||
requestAnimationFrame(animation.play)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores'
|
||||
import { getContext, onMount } from 'svelte'
|
||||
import anime, { type AnimeTimelineInstance } from 'animejs'
|
||||
import { timeline, stagger } from 'motion'
|
||||
import { DELAY } from '$utils/contants'
|
||||
import { sleep, smoothScroll } from '$utils/functions'
|
||||
import { smoothScroll } from '$utils/functions'
|
||||
import { reveal, fade as animeFade } from '$animations/index'
|
||||
import { quartOut } from '$animations/easings'
|
||||
// Components
|
||||
import Metas from '$components/Metas.svelte'
|
||||
import PageTransition from '$components/PageTransition.svelte'
|
||||
@@ -30,36 +31,42 @@
|
||||
const { settings, locations }: any = getContext('global')
|
||||
|
||||
let scrollY: number, innerHeight: number
|
||||
let timeline: AnimeTimelineInstance
|
||||
|
||||
|
||||
onMount(() => {
|
||||
timeline = anime.timeline({
|
||||
duration: 1600,
|
||||
easing: 'easeOutQuart',
|
||||
autoplay: false,
|
||||
})
|
||||
/**
|
||||
* Animations
|
||||
*/
|
||||
const animation = timeline([
|
||||
// Reveal text
|
||||
['.homepage__headline', {
|
||||
y: [16, 0],
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 0.75,
|
||||
}],
|
||||
|
||||
// Reveal text
|
||||
timeline.add({
|
||||
targets: '.homepage__headline',
|
||||
translateY: [16, 0],
|
||||
opacity: [0, 1],
|
||||
}, 750)
|
||||
|
||||
// Animate collage photos
|
||||
timeline.add({
|
||||
targets: '.collage .photo-card',
|
||||
translateY: ['33.33%', 0],
|
||||
rotate (item: HTMLElement) {
|
||||
return [-4, getComputedStyle(item).getPropertyValue('--rotation')]
|
||||
// Animate collage photos
|
||||
['.collage .photo-card', {
|
||||
y: ['33.33%', 0],
|
||||
rotate: [-4, 0],
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 0,
|
||||
duration: 1.2,
|
||||
delay: stagger(0.075),
|
||||
}]
|
||||
], {
|
||||
delay: DELAY.PAGE_LOADING / 1000,
|
||||
defaultOptions: {
|
||||
duration: 1.6,
|
||||
easing: quartOut,
|
||||
},
|
||||
opacity: [0, 1],
|
||||
duration: 1200,
|
||||
delay: anime.stagger(75),
|
||||
}, 0)
|
||||
})
|
||||
animation.stop()
|
||||
|
||||
sleep(DELAY.PAGE_LOADING).then(timeline.play)
|
||||
// Run animation
|
||||
requestAnimationFrame(animation.play)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
import { goto } from '$app/navigation'
|
||||
import { getContext, onMount } from 'svelte'
|
||||
import { fly } from 'svelte/transition'
|
||||
import { quartOut } from 'svelte/easing'
|
||||
import dayjs from 'dayjs'
|
||||
import { quartOut as quartOutSvelte } from 'svelte/easing'
|
||||
import relativeTime from 'dayjs/plugin/relativeTime.js'
|
||||
import anime, { type AnimeTimelineInstance } from 'animejs'
|
||||
import { stagger, timeline } from 'motion'
|
||||
import { DELAY } from '$utils/contants'
|
||||
import { fetchAPI } from '$utils/api'
|
||||
import { quartOut } from '$animations/easings'
|
||||
import { map, lerp, throttle } from '$utils/functions'
|
||||
// Components
|
||||
import Metas from '$components/Metas.svelte'
|
||||
@@ -282,37 +284,30 @@
|
||||
const existingPhotos = photosGridEl.querySelectorAll('.photo')
|
||||
existingPhotos.forEach(el => observerPhotos.observe(el))
|
||||
|
||||
|
||||
/**
|
||||
* Animations
|
||||
*/
|
||||
// Transition in
|
||||
const timeline: AnimeTimelineInstance = anime.timeline({
|
||||
duration: 1600,
|
||||
easing: 'easeOutQuart',
|
||||
autoplay: false,
|
||||
const animation = timeline([
|
||||
// Reveal text
|
||||
['.photos-page__intro .discover, .photos-page__intro .filters__bar', {
|
||||
y: [16, 0],
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 0.4,
|
||||
delay: stagger(0.25),
|
||||
}]
|
||||
], {
|
||||
delay: DELAY.PAGE_LOADING / 1000,
|
||||
defaultOptions: {
|
||||
duration: 1.6,
|
||||
easing: quartOut,
|
||||
},
|
||||
})
|
||||
animation.stop()
|
||||
|
||||
// Reveal text
|
||||
timeline.add({
|
||||
targets: '.photos-page__intro .discover',
|
||||
translateY: [16, 0],
|
||||
opacity: [0, 1],
|
||||
}, 900)
|
||||
|
||||
// Filters
|
||||
timeline.add({
|
||||
targets: '.photos-page__intro .filters',
|
||||
translateY: [16, 0],
|
||||
opacity: [0, 1],
|
||||
complete ({ animatables }) {
|
||||
const element = animatables[0].target
|
||||
// Remove style to not interfere with CSS when scrolling back up over photos
|
||||
element.removeAttribute('style')
|
||||
}
|
||||
}, 1300)
|
||||
|
||||
// Play animation
|
||||
requestAnimationFrame(timeline.play)
|
||||
// Run animation
|
||||
requestAnimationFrame(animation.play)
|
||||
|
||||
|
||||
// Destroy
|
||||
@@ -351,9 +346,8 @@
|
||||
class:is-transitioning={filtersTransitioning}
|
||||
class:is-visible={filtersVisible}
|
||||
>
|
||||
<span class="text-label filters__label">Filter photos</span>
|
||||
|
||||
<div class="filters__bar">
|
||||
<span class="text-label filters__label">Filter photos</span>
|
||||
<ul>
|
||||
<li>
|
||||
<Select
|
||||
@@ -418,7 +412,7 @@
|
||||
{#if filtered}
|
||||
<button class="reset button-link"
|
||||
on:click={resetFiltered}
|
||||
transition:fly={{ y: 4, duration: 600, easing: quartOut }}
|
||||
transition:fly={{ y: 4, duration: 600, easing: quartOutSvelte }}
|
||||
>
|
||||
Reset
|
||||
</button>
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte'
|
||||
import { stagger, timeline } from 'motion'
|
||||
import dayjs from 'dayjs'
|
||||
import anime, { type AnimeTimelineInstance } from 'animejs'
|
||||
import { DELAY } from '$utils/contants'
|
||||
import { quartOut } from '$animations/easings'
|
||||
// Components
|
||||
import Metas from '$components/Metas.svelte'
|
||||
import PageTransition from '$components/PageTransition.svelte'
|
||||
@@ -22,37 +24,36 @@
|
||||
/**
|
||||
* Animations
|
||||
*/
|
||||
// Setup animations
|
||||
const timeline: AnimeTimelineInstance = anime.timeline({
|
||||
duration: 1600,
|
||||
easing: 'easeOutQuart',
|
||||
autoplay: false,
|
||||
const animation = timeline([
|
||||
// Elements
|
||||
['.heading .text, .subscribe__top .newsletter-form, .subscribe__issues', {
|
||||
y: [24, 0],
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
at: 0.5,
|
||||
delay: stagger(0.35),
|
||||
}],
|
||||
|
||||
// Reveal each issue
|
||||
['.subscribe__issues > ul > li', {
|
||||
y: [16, 0],
|
||||
opacity: [0, 1],
|
||||
}, {
|
||||
duration: 1,
|
||||
at: 1.5,
|
||||
delay: stagger(0.15),
|
||||
}],
|
||||
], {
|
||||
delay: DELAY.PAGE_LOADING / 1000,
|
||||
defaultOptions: {
|
||||
duration: 1.6,
|
||||
easing: quartOut,
|
||||
},
|
||||
})
|
||||
animation.stop()
|
||||
|
||||
anime.set('.heading .text, .subscribe__top .newsletter-form, .subscribe__issues', {
|
||||
opacity: 0,
|
||||
translateY: 24,
|
||||
})
|
||||
|
||||
// Elements
|
||||
timeline.add({
|
||||
targets: '.heading .text, .subscribe__top .newsletter-form, .subscribe__issues',
|
||||
opacity: 1,
|
||||
translateY: 0,
|
||||
delay: anime.stagger(200),
|
||||
}, 500)
|
||||
|
||||
// Reveal each issue
|
||||
timeline.add({
|
||||
targets: '.subscribe__issues .issue',
|
||||
opacity: [0, 1],
|
||||
translateY: [16, 0],
|
||||
delay: anime.stagger(150),
|
||||
duration: 1000,
|
||||
}, 1000)
|
||||
|
||||
// Transition in
|
||||
requestAnimationFrame(timeline.play)
|
||||
// Run animation
|
||||
requestAnimationFrame(animation.play)
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -75,22 +76,24 @@
|
||||
<h2 class="title-small">Past Issues</h2>
|
||||
<ul>
|
||||
{#each issues as { issue, title, date_sent, link, thumbnail: { id } }}
|
||||
<li class="issue">
|
||||
<a href={link} target="_blank" rel="external noreferrer noopener" tabindex="0">
|
||||
<Image
|
||||
id={id}
|
||||
sizeKey="issue-thumbnail-small"
|
||||
width={160} height={112}
|
||||
alt="Issue {issue} thumbnail"
|
||||
/>
|
||||
<dl>
|
||||
<dt>Issue #{issue}</dt>
|
||||
<dd>
|
||||
<p>{title}</p>
|
||||
<time>{dayjs(date_sent).format('DD/MM/YYYY')}</time>
|
||||
</dd>
|
||||
</dl>
|
||||
</a>
|
||||
<li>
|
||||
<div class="issue">
|
||||
<a href={link} target="_blank" rel="external noreferrer noopener" tabindex="0">
|
||||
<Image
|
||||
id={id}
|
||||
sizeKey="issue-thumbnail-small"
|
||||
width={160} height={112}
|
||||
alt="Issue {issue} thumbnail"
|
||||
/>
|
||||
<dl>
|
||||
<dt>Issue #{issue}</dt>
|
||||
<dd>
|
||||
<p>{title}</p>
|
||||
<time>{dayjs(date_sent).format('DD/MM/YYYY')}</time>
|
||||
</dd>
|
||||
</dl>
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user