페이지 이동 전환 베일 추가
This commit is contained in:
@@ -3,14 +3,21 @@
|
||||
*
|
||||
* Vue Router 기본 scrollBehavior는 전환 중 이전 화면을 먼저 움직일 수 있어
|
||||
* `app/router.options.js`에서 끄고, 여기서는 Nuxt 페이지 렌더링이 끝난 뒤
|
||||
* 새 화면에서만 최상단 또는 해시 위치로 이동한다.
|
||||
* 새 화면에서만 최상단 또는 해시 위치로 이동한다. 전환 중에는 짧은 베일을
|
||||
* 씌워 이전 화면이 상단으로 튀는 순간이 사용자에게 보이지 않게 한다.
|
||||
*/
|
||||
const ROUTE_VEIL_CLASS = 'site-route-veil'
|
||||
const ROUTE_VEIL_TIMEOUT_MS = 8000
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
const router = nuxtApp.$router
|
||||
const root = document.documentElement
|
||||
|
||||
/** @type {{ id: number, to: import('vue-router').RouteLocationNormalizedLoaded, from: import('vue-router').RouteLocationNormalizedLoaded } | null} */
|
||||
let pendingRouteScroll = null
|
||||
let routeScrollId = 0
|
||||
/** @type {ReturnType<typeof setTimeout> | null} */
|
||||
let veilTimer = null
|
||||
|
||||
/**
|
||||
* 브라우저 렌더 프레임을 기다린다.
|
||||
@@ -22,6 +29,28 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* 페이지 전환 베일을 표시한다.
|
||||
* @returns {void}
|
||||
*/
|
||||
const showRouteVeil = () => {
|
||||
root.classList.add(ROUTE_VEIL_CLASS)
|
||||
clearTimeout(veilTimer)
|
||||
veilTimer = setTimeout(() => {
|
||||
root.classList.remove(ROUTE_VEIL_CLASS)
|
||||
}, ROUTE_VEIL_TIMEOUT_MS)
|
||||
}
|
||||
|
||||
/**
|
||||
* 페이지 전환 베일을 숨긴다.
|
||||
* @returns {void}
|
||||
*/
|
||||
const hideRouteVeil = () => {
|
||||
clearTimeout(veilTimer)
|
||||
veilTimer = null
|
||||
root.classList.remove(ROUTE_VEIL_CLASS)
|
||||
}
|
||||
|
||||
/**
|
||||
* 이동 완료 후 적용할 스크롤 정보를 저장한다.
|
||||
* @param {import('vue-router').RouteLocationNormalizedLoaded} to - 이동 대상 라우트
|
||||
@@ -49,6 +78,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
const routeScroll = pendingRouteScroll
|
||||
|
||||
if (!routeScroll) {
|
||||
hideRouteVeil()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -68,6 +98,8 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
|
||||
if (target) {
|
||||
target.scrollIntoView({ block: 'start' })
|
||||
await waitForFrame()
|
||||
hideRouteVeil()
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -77,11 +109,16 @@ export default defineNuxtPlugin((nuxtApp) => {
|
||||
left: 0,
|
||||
behavior: 'auto'
|
||||
})
|
||||
|
||||
await waitForFrame()
|
||||
hideRouteVeil()
|
||||
}
|
||||
|
||||
router.afterEach((to, from) => {
|
||||
queueRouteScroll(to, from)
|
||||
})
|
||||
|
||||
nuxtApp.hook('page:loading:start', showRouteVeil)
|
||||
nuxtApp.hook('page:finish', applyPendingRouteScroll)
|
||||
nuxtApp.hook('app:error', hideRouteVeil)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user