mirror of
https://github.com/reonokiy/blog.nokiy.net.git
synced 2025-06-15 19:22:52 +02:00
✨ feat: add fade up animation to post page, optimize global animation curves and durations, refine animation-related naming conventions
This commit is contained in:
parent
d4ea4c470b
commit
a35999629a
14 changed files with 122 additions and 52 deletions
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
|
@ -32,6 +32,9 @@ importers:
|
|||
feed:
|
||||
specifier: ^5.0.1
|
||||
version: 5.0.1
|
||||
gsap:
|
||||
specifier: ^3.13.0
|
||||
version: 3.13.0
|
||||
markdown-it:
|
||||
specifier: ^14.1.0
|
||||
version: 14.1.0
|
||||
|
@ -2191,6 +2194,9 @@ packages:
|
|||
graphemer@1.4.0:
|
||||
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
|
||||
|
||||
gsap@3.13.0:
|
||||
resolution: {integrity: sha512-QL7MJ2WMjm1PHWsoFrAQH/J8wUeqZvMtHO58qdekHpCfhvhSL4gSiz6vJf5EeMP0LOn3ZCprL2ki/gjED8ghVw==}
|
||||
|
||||
gzip-size@6.0.0:
|
||||
resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==}
|
||||
engines: {node: '>=10'}
|
||||
|
@ -6284,6 +6290,8 @@ snapshots:
|
|||
|
||||
graphemer@1.4.0: {}
|
||||
|
||||
gsap@3.13.0: {}
|
||||
|
||||
gzip-size@6.0.0:
|
||||
dependencies:
|
||||
duplexer: 0.1.2
|
||||
|
|
|
@ -93,15 +93,15 @@ function setupThemeToggle() {
|
|||
}
|
||||
|
||||
// Temporarily add markers during animation to implement view transition and disable CSS transitions
|
||||
document.documentElement.style.setProperty('view-transition-name', 'theme-transition')
|
||||
document.documentElement.setAttribute('data-theme-transition', '')
|
||||
document.documentElement.style.setProperty('view-transition-name', 'animation-theme-toggle')
|
||||
document.documentElement.setAttribute('data-theme-changing', '')
|
||||
|
||||
// If browser supports View Transitions API, use it to update theme
|
||||
const themeTransition = document.startViewTransition(updateTheme)
|
||||
// Remove markers after animation
|
||||
themeTransition.finished.then(() => {
|
||||
document.documentElement.style.removeProperty('view-transition-name')
|
||||
document.documentElement.removeAttribute('data-theme-transition')
|
||||
document.documentElement.removeAttribute('data-theme-changing')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -32,7 +32,7 @@ const SubtitleTag = isPost ? 'div' : 'h2'
|
|||
<div
|
||||
class="box-content inline-block pr-1"
|
||||
transition:name={`site-title-${currentLang}`}
|
||||
data-disable-transition-on-theme
|
||||
data-disable-theme-transition
|
||||
>
|
||||
<a
|
||||
id="site-title-link"
|
||||
|
|
|
@ -43,7 +43,7 @@ function getPostPath(post: Post) {
|
|||
lg={isHome ? 'font-medium text-4.5' : ''}
|
||||
href={getPostPath(post)}
|
||||
transition:name={`post-${post.data.abbrlink || post.id}-${lang}`}
|
||||
data-disable-transition-on-theme
|
||||
data-disable-theme-transition
|
||||
>
|
||||
{post.data.title}
|
||||
</a>
|
||||
|
@ -62,7 +62,7 @@ function getPostPath(post: Post) {
|
|||
<div
|
||||
class="py-0.8 text-3.5 font-time lg:hidden"
|
||||
transition:name={`time-${post.data.abbrlink || post.id}-${lang}`}
|
||||
data-disable-transition-on-theme
|
||||
data-disable-theme-transition
|
||||
>
|
||||
<PostDate
|
||||
date={post.data.published}
|
||||
|
|
18
src/components/Widgets/FadeUpAnimation.astro
Normal file
18
src/components/Widgets/FadeUpAnimation.astro
Normal file
|
@ -0,0 +1,18 @@
|
|||
<script>
|
||||
function resetFadeUpAnimation() {
|
||||
document.querySelectorAll('.animation-fade-up').forEach((container) => {
|
||||
const childElements = Array.from(container.children).slice(0, 20)
|
||||
childElements.forEach(element =>
|
||||
(element as HTMLElement).style.animationName = 'none',
|
||||
)
|
||||
requestAnimationFrame(() => {
|
||||
childElements.forEach(element =>
|
||||
(element as HTMLElement).style.animationName = '',
|
||||
)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
resetFadeUpAnimation()
|
||||
document.addEventListener('astro:page-load', resetFadeUpAnimation)
|
||||
</script>
|
|
@ -5,7 +5,7 @@ import GoBackIcon from '@/assets/icons/go-back.svg';
|
|||
<button
|
||||
id="back-button"
|
||||
class="hidden"
|
||||
lg="block absolute c-secondary/40 left--10 top-1/2 aspect-square w-4.5 translate-y--1/2 transition-colors c-secondary active:scale-90 hover:c-primary/80"
|
||||
lg="block absolute c-secondary/40 left--10 top-1/2 aspect-square w-4.5 translate-y--1/2 transition-colors duration-300 ease-out c-secondary active:scale-90 hover:c-primary/80"
|
||||
aria-label="Go back"
|
||||
>
|
||||
<GoBackIcon
|
||||
|
|
|
@ -29,7 +29,7 @@ const filteredHeadings = headings.filter(heading =>
|
|||
<div class="relative h-12 w-full">
|
||||
<label
|
||||
for="toc-toggle"
|
||||
class="absolute inset-0 flex cursor-pointer items-center 2xl:(static flex c-secondary/40 transition-colors hover:c-secondary/80)"
|
||||
class="absolute inset-0 flex cursor-pointer items-center 2xl:(static flex c-secondary/40 transition-colors duration-300 ease-out hover:c-secondary/80)"
|
||||
>
|
||||
<span class="toc-title">
|
||||
{currentUI.toc}
|
||||
|
|
|
@ -3,11 +3,13 @@ import Button from '@/components/Button.astro'
|
|||
import Footer from '@/components/Footer.astro'
|
||||
import Header from '@/components/Header.astro'
|
||||
import Navbar from '@/components/Navbar.astro'
|
||||
import FadeUpAnimation from '@/components/Widgets/FadeUpAnimation.astro'
|
||||
import GithubCard from '@/components/Widgets/GithubCard.astro'
|
||||
// import PhotoSwipe from '@/components/Widgets/PhotoSwipe.astro'
|
||||
import PhotoSwipe from '@/components/Widgets/PhotoSwipe.astro'
|
||||
import themeConfig from '@/config'
|
||||
import Head from '@/layouts/Head.astro'
|
||||
import { getPageInfo } from '@/utils/page'
|
||||
import '@/styles/animation.css'
|
||||
import '@/styles/global.css'
|
||||
import '@/styles/font.css'
|
||||
import '@/styles/heti.css'
|
||||
|
@ -46,8 +48,9 @@ const MarginBottom = isPost && themeConfig.comment?.enabled
|
|||
</main>
|
||||
<Footer />
|
||||
</div>
|
||||
<FadeUpAnimation />
|
||||
<Button supportedLangs={supportedLangs} />
|
||||
<GithubCard />
|
||||
<!-- <PhotoSwipe /> -->
|
||||
<PhotoSwipe />
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -114,7 +114,7 @@ const { Content, headings, remarkPluginFrontmatter } = await render(post)
|
|||
<h1 class="post-title">
|
||||
<span
|
||||
transition:name={`post-${post.data.abbrlink || post.id}-${lang}`}
|
||||
data-disable-transition-on-theme
|
||||
data-disable-theme-transition
|
||||
>
|
||||
{post.data.title}
|
||||
</span>
|
||||
|
@ -125,7 +125,7 @@ const { Content, headings, remarkPluginFrontmatter } = await render(post)
|
|||
<div
|
||||
class="mb-16.3 block c-primary font-time"
|
||||
transition:name={`time-${post.data.abbrlink || post.id}-${lang}`}
|
||||
data-disable-transition-on-theme
|
||||
data-disable-theme-transition
|
||||
>
|
||||
<PostDate
|
||||
date={post.data.published}
|
||||
|
@ -136,7 +136,9 @@ const { Content, headings, remarkPluginFrontmatter } = await render(post)
|
|||
<!-- TOC -->
|
||||
{post.data.toc && <TOC headings={headings} />}
|
||||
<!-- Content -->
|
||||
<Content />
|
||||
<div class="animation-fade-up">
|
||||
<Content />
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Tags -->
|
||||
|
|
74
src/styles/animation.css
Normal file
74
src/styles/animation.css
Normal file
|
@ -0,0 +1,74 @@
|
|||
/* View Transition */
|
||||
::view-transition-new(animation-theme-toggle) {
|
||||
animation: reveal 1s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
clip-path: inset(0 0 0 0);
|
||||
z-index: 99;
|
||||
}
|
||||
::view-transition-old(animation-theme-toggle) {
|
||||
animation: none;
|
||||
z-index: -1;
|
||||
}
|
||||
@keyframes reveal {
|
||||
from {
|
||||
clip-path: inset(var(--from));
|
||||
}
|
||||
}
|
||||
|
||||
html.dark {
|
||||
--from: 0 0 100% 0;
|
||||
}
|
||||
html:not(.dark) {
|
||||
--from: 100% 0 0 0;
|
||||
}
|
||||
|
||||
/* Disable animations for special elements during theme switching */
|
||||
html[data-theme-changing] [data-disable-theme-transition] {
|
||||
view-transition-name: none !important;
|
||||
}
|
||||
|
||||
/* Fallback animation when view-transition-name is not supported */
|
||||
@supports not (view-transition-name: none) {
|
||||
html {
|
||||
--at-apply: 'transition-colors duration-300 ease-out';
|
||||
}
|
||||
}
|
||||
|
||||
/* Fade Up Animation >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
|
||||
@keyframes fadeUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(3rem);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.animation-fade-up > * {
|
||||
opacity: 0;
|
||||
}
|
||||
.animation-fade-up > *:nth-child(-n+20) {
|
||||
animation: fadeUp 1.5s cubic-bezier(0.22, 1, 0.36, 1) forwards;
|
||||
animation-delay: calc((var(--animation-order, 0) - 1) * 0.08s);
|
||||
}
|
||||
.animation-fade-up > *:nth-child(1) { --animation-order: 1; }
|
||||
.animation-fade-up > *:nth-child(2) { --animation-order: 2; }
|
||||
.animation-fade-up > *:nth-child(3) { --animation-order: 3; }
|
||||
.animation-fade-up > *:nth-child(4) { --animation-order: 4; }
|
||||
.animation-fade-up > *:nth-child(5) { --animation-order: 5; }
|
||||
.animation-fade-up > *:nth-child(6) { --animation-order: 6; }
|
||||
.animation-fade-up > *:nth-child(7) { --animation-order: 7; }
|
||||
.animation-fade-up > *:nth-child(8) { --animation-order: 8; }
|
||||
.animation-fade-up > *:nth-child(9) { --animation-order: 9; }
|
||||
.animation-fade-up > *:nth-child(10) { --animation-order: 10; }
|
||||
.animation-fade-up > *:nth-child(11) { --animation-order: 11; }
|
||||
.animation-fade-up > *:nth-child(12) { --animation-order: 12; }
|
||||
.animation-fade-up > *:nth-child(13) { --animation-order: 13; }
|
||||
.animation-fade-up > *:nth-child(14) { --animation-order: 14; }
|
||||
.animation-fade-up > *:nth-child(15) { --animation-order: 15; }
|
||||
.animation-fade-up > *:nth-child(16) { --animation-order: 16; }
|
||||
.animation-fade-up > *:nth-child(17) { --animation-order: 17; }
|
||||
.animation-fade-up > *:nth-child(18) { --animation-order: 18; }
|
||||
.animation-fade-up > *:nth-child(19) { --animation-order: 19; }
|
||||
.animation-fade-up > *:nth-child(20) { --animation-order: 20; }
|
|
@ -1,7 +1,7 @@
|
|||
/* GitHub Card */
|
||||
.gc-container {
|
||||
--at-apply: 'block mb-4 px-5 py-4 overflow-x-auto uno-round-border bg-secondary/5';
|
||||
--at-apply: 'transition-colors lg:(px-6 py-5) hover:(bg-secondary/10 c-primary)';
|
||||
--at-apply: 'transition-colors duration-300 ease-out lg:(px-6 py-5) hover:(bg-secondary/10 c-primary)';
|
||||
scrollbar-color: oklch(var(--un-preset-theme-colors-secondary) / 0.15) transparent;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ h4:hover .heading-anchor-link svg {
|
|||
--at-apply: 'op-80';
|
||||
}
|
||||
.heading-anchor-link svg {
|
||||
--at-apply: 'ml-0.4em aspect-square w-0.9em op-0 transition-opacity active:scale-90';
|
||||
--at-apply: 'ml-0.4em aspect-square w-0.9em op-0 transition-opacity duration-300 ease-out active:scale-90';
|
||||
}
|
||||
h1:hover .heading-anchor-link svg:hover,
|
||||
h2:hover .heading-anchor-link svg:hover,
|
||||
|
@ -65,41 +65,6 @@ h4:hover .heading-anchor-link svg:hover {
|
|||
}
|
||||
}
|
||||
|
||||
/* View Transition with Theme Toggle >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
|
||||
::view-transition-new(theme-transition) {
|
||||
animation: reveal 1s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
clip-path: inset(0 0 0 0);
|
||||
z-index: 99;
|
||||
}
|
||||
::view-transition-old(theme-transition) {
|
||||
animation: none;
|
||||
z-index: -1;
|
||||
}
|
||||
@keyframes reveal {
|
||||
from {
|
||||
clip-path: inset(var(--from));
|
||||
}
|
||||
}
|
||||
|
||||
html.dark {
|
||||
--from: 0 0 100% 0;
|
||||
}
|
||||
html:not(.dark) {
|
||||
--from: 100% 0 0 0;
|
||||
}
|
||||
|
||||
/* Disable animations for other elements during theme switching */
|
||||
html[data-theme-transition] [data-disable-transition-on-theme] {
|
||||
view-transition-name: none !important;
|
||||
}
|
||||
|
||||
/* Fallback animation when view-transition-name is not supported */
|
||||
@supports not (view-transition-name: none) {
|
||||
html:not([data-restore-theme]) {
|
||||
--at-apply: 'transition-colors duration-300 ease-out';
|
||||
}
|
||||
}
|
||||
|
||||
/* Snell Roundhand Static Font >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> */
|
||||
@font-face {
|
||||
font-family: "Snell-Bold";
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
/* Links */
|
||||
.heti :where(a:not(.gc-container)) {
|
||||
--at-apply: 'break-all font-semibold tracking-0 underline underline-0.075em decoration-secondary/80 underline-offset-0.1em';
|
||||
--at-apply: 'transition-colors hover:(c-primary decoration-primary/80) lg:underline-0.1em';
|
||||
--at-apply: 'transition-colors duration-300 ease-out hover:(c-primary decoration-primary/80) lg:underline-0.1em';
|
||||
}
|
||||
|
||||
/* Images */
|
||||
|
|
|
@ -56,7 +56,7 @@ export default defineConfig({
|
|||
],
|
||||
shortcuts: {
|
||||
'uno-desktop-column': 'fixed right-[max(5rem,calc(50vw-35rem))] w-14rem',
|
||||
'uno-tags-style': 'inline-block whitespace-nowrap border border-secondary/25 rounded-full px-3.2 py-0.7 c-secondary transition-colors hover:(border-secondary/80 text-primary)',
|
||||
'uno-tags-style': 'inline-block whitespace-nowrap border border-secondary/25 rounded-full px-3.2 py-0.7 c-secondary transition-colors duration-300 ease-out hover:(border-secondary/80 text-primary)',
|
||||
'uno-decorative-line': 'mb-4.5 h-0.25 w-10 bg-secondary/25 lg:(mb-6 w-11)',
|
||||
'uno-tags-wrapper': 'flex flex-wrap gap-x-3 gap-y-3.2',
|
||||
'uno-round-border': 'border border-secondary/5 rounded border-solid',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue