Skip to content

Commit

Permalink
feat(quartz): 添加页面切换动画并优化 SPA 导航
Browse files Browse the repository at this point in the history
- 在 custom.scss 中添加了页面切换动画的基础样式和关键帧
- 在 spa.inline.ts 中实现了页面加载时的动画效果和 loading 状态
- 优化了页面导航逻辑,提高了用户体验
  • Loading branch information
hulinjiang committed Dec 4, 2024
1 parent c03e38f commit 6531bda
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 3 deletions.
35 changes: 32 additions & 3 deletions quartz/components/scripts/spa.inline.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import micromorph from "micromorph"
import { FullSlug, RelativeURL, getFullSlug, normalizeRelativeURLs } from "../../util/path"
import {FullSlug, getFullSlug, normalizeRelativeURLs, RelativeURL} from "../../util/path"

// adapted from `micromorph`
// https://github.com/natemoo-re/micromorph
Expand Down Expand Up @@ -44,6 +44,9 @@ window.addCleanup = (fn) => cleanupFns.add(fn)

let p: DOMParser
async function navigate(url: URL, isBack: boolean = false) {
// Add loading class at the start of navigation
document.body.classList.add('loading')

p = p || new DOMParser()
const contents = await fetch(`${url}`)
.then((res) => {
Expand All @@ -54,7 +57,7 @@ async function navigate(url: URL, isBack: boolean = false) {
window.location.assign(url)
}
})
.catch(() => {
.catch((error) => {
window.location.assign(url)
})

Expand Down Expand Up @@ -83,6 +86,33 @@ async function navigate(url: URL, isBack: boolean = false) {
// morph body
micromorph(document.body, html.body)

// 在 morph 完成后添加动画
const headerElements = document.querySelectorAll('.page-header, .banner-wrapper')
const articleElements = document.querySelectorAll('article')

// 先处理 header 元素
headerElements.forEach((element) => {
if (element instanceof HTMLElement) {
element.classList.remove('page-transition')
void element.offsetHeight
element.classList.add('page-transition')
}
})

// 然后处理文章内容
articleElements.forEach((element) => {
if (element instanceof HTMLElement) {
element.classList.remove('page-transition')
void element.offsetHeight
element.classList.add('page-transition')
}
})

// 移除 loading 类
setTimeout(() => {
document.body.classList.remove('loading')
}, 100)

// scroll into place and add history
if (!isBack) {
if (url.hash) {
Expand All @@ -100,7 +130,6 @@ async function navigate(url: URL, isBack: boolean = false) {
elementsToAdd.forEach((el) => document.head.appendChild(el))

// delay setting the url until now
// at this point everything is loaded so changing the url should resolve to the correct addresses
if (!isBack) {
history.pushState({}, "", url)
}
Expand Down
42 changes: 42 additions & 0 deletions quartz/styles/custom.scss
Original file line number Diff line number Diff line change
Expand Up @@ -597,4 +597,46 @@ a.internal.broken-link {
display: inline-flex;
align-items: center;
gap: 4px;
}


// 统一的页面切换动画基础样式
.page-transition {
animation-fill-mode: both;
will-change: opacity, transform;
backface-visibility: hidden; // 防止闪烁
perspective: 1000px; // 提高性能
}

// Header 区域动画(包括 banner)
.page-header.page-transition,
.banner-wrapper.page-transition {
animation: fadeInDown 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

// 内容区域动画
article.page-transition {
animation: fadeIn 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

// 从上方滑入(用于 header)
@keyframes fadeInDown {
0% {
opacity: 0;
transform: translateY(-10px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}

// 淡入(用于内容)
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}

0 comments on commit 6531bda

Please sign in to comment.