Compare commits
	
		
			3 commits
		
	
	
		
			develop
			...
			nav-animat
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | a0e1ae80b4 | ||
|  | 06d33ec520 | ||
|  | 91643db0a4 | 
					 4 changed files with 63 additions and 7 deletions
				
			
		|  | @ -9,7 +9,7 @@ import { defineComponent } from 'vue'; | |||
| import { faExpandAlt, faColumns, faExternalLinkAlt, faLink, faWindowMaximize } from '@fortawesome/free-solid-svg-icons'; | ||||
| import * as os from '@client/os'; | ||||
| import copyToClipboard from '@client/scripts/copy-to-clipboard'; | ||||
| import { router } from '@client/router'; | ||||
| import { router, setNavigationInfo } from '@client/router'; | ||||
| import { url } from '@client/config'; | ||||
| import { popout } from '@client/scripts/popout'; | ||||
| import { ColdDeviceStorage } from '@client/store'; | ||||
|  | @ -130,6 +130,10 @@ export default defineComponent({ | |||
| 				if (this.$router.currentRoute.value.path === this.to) { | ||||
| 					window.scroll({ top: 0, behavior: 'smooth' }); | ||||
| 				} else { | ||||
| 					setNavigationInfo({ | ||||
| 						from: this.$router.currentRoute.value.path, | ||||
| 						to: this.to | ||||
| 					}); | ||||
| 					this.$router.push(this.to); | ||||
| 				} | ||||
| 			} | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| import { defineAsyncComponent, markRaw } from 'vue'; | ||||
| import { defineAsyncComponent, markRaw, ref } from 'vue'; | ||||
| import { createRouter, createWebHistory } from 'vue-router'; | ||||
| import MkLoading from '@client/pages/_loading_.vue'; | ||||
| import MkError from '@client/pages/_error_.vue'; | ||||
|  | @ -13,6 +13,16 @@ const page = (path: string) => defineAsyncComponent({ | |||
| 
 | ||||
| let indexScrollPos = 0; | ||||
| 
 | ||||
| export const navigationInfo = ref(null); | ||||
| export function setNavigationInfo(info) { | ||||
| 	navigationInfo.value = info; | ||||
| } | ||||
| 
 | ||||
| window.addEventListener('popstate', (event) => { | ||||
| 	console.log('popstate'); | ||||
| 	navigationInfo.value = null; | ||||
| }); | ||||
| 
 | ||||
| export const router = createRouter({ | ||||
| 	history: createWebHistory(), | ||||
| 	routes: [ | ||||
|  | @ -91,7 +101,7 @@ export const router = createRouter({ | |||
| 	// 通常の使い方をすると scroll メソッドの behavior を設定できないため、自前で window.scroll するようにする
 | ||||
| 	scrollBehavior(to) { | ||||
| 		window._scroll = () => { // さらにHacky
 | ||||
| 			if (to.name === 'index') { | ||||
| 			if (location.pathname === '/') { | ||||
| 				window.scroll({ top: indexScrollPos, behavior: 'instant' }); | ||||
| 				const i = setInterval(() => { | ||||
| 					window.scroll({ top: indexScrollPos, behavior: 'instant' }); | ||||
|  | @ -106,11 +116,11 @@ export const router = createRouter({ | |||
| 	} | ||||
| }); | ||||
| 
 | ||||
| router.afterEach((to, from) => { | ||||
| 	if (from.name === 'index') { | ||||
| export function saveScrollPosition() { | ||||
| 	if (navigationInfo.value?.from === '/') { | ||||
| 		indexScrollPos = window.scrollY; | ||||
| 	} | ||||
| }); | ||||
| } | ||||
| 
 | ||||
| export function resolve(path: string) { | ||||
| 	const resolved = router.resolve(path); | ||||
|  |  | |||
|  | @ -322,6 +322,8 @@ hr { | |||
| 	box-sizing: border-box; | ||||
| 	margin: var(--root-margin, 32px) auto; | ||||
| 	max-width: min(var(--baseContentWidth), calc(100% - (var(--root-margin, 32px) * 2))); | ||||
| 	background: var(--bg); | ||||
| 	min-height: 100%; | ||||
| 
 | ||||
| 	@media (max-width: 500px) { | ||||
| 		--root-margin: 10px; | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ | |||
| 			</header> | ||||
| 			<div class="content" :class="{ _flat_: !fullView }"> | ||||
| 				<router-view v-slot="{ Component }"> | ||||
| 					<transition :name="$store.state.animation ? 'page' : ''" mode="out-in" @enter="onTransition"> | ||||
| 					<transition :name="$store.state.animation && navigationInfo ? 'page' : ''" @before-enter="saveScrollPosition" @enter="onTransition"> | ||||
| 						<keep-alive :include="['timeline']"> | ||||
| 							<component :is="Component" :ref="changePage"/> | ||||
| 						</keep-alive> | ||||
|  | @ -64,6 +64,7 @@ import XHeader from './_common_/header.vue'; | |||
| import * as os from '@client/os'; | ||||
| import { sidebarDef } from '@client/sidebar'; | ||||
| import * as symbols from '@client/symbols'; | ||||
| import { saveScrollPosition, navigationInfo } from '@client/router'; | ||||
| 
 | ||||
| const DESKTOP_THRESHOLD = 1100; | ||||
| const MOBILE_THRESHOLD = 600; | ||||
|  | @ -85,6 +86,7 @@ export default defineComponent({ | |||
| 			isDesktop: window.innerWidth >= DESKTOP_THRESHOLD, | ||||
| 			widgetsShowing: false, | ||||
| 			fullView: false, | ||||
| 			navigationInfo, | ||||
| 			wallpaper: localStorage.getItem('wallpaper') != null, | ||||
| 			faLayerGroup, faBars, faBell, faHome, faCircle, faPencilAlt, | ||||
| 		}; | ||||
|  | @ -152,6 +154,10 @@ export default defineComponent({ | |||
| 			this.$refs.drawerNav.show(); | ||||
| 		}, | ||||
| 
 | ||||
| 		saveScrollPosition() { | ||||
| 			saveScrollPosition(); | ||||
| 		}, | ||||
| 
 | ||||
| 		onTransition() { | ||||
| 			if (window._scroll) window._scroll(); | ||||
| 		}, | ||||
|  | @ -215,6 +221,39 @@ export default defineComponent({ | |||
| 	opacity: 0; | ||||
| } | ||||
| 
 | ||||
| .page-enter-active { | ||||
| 	position: absolute; | ||||
| 	top: 0; | ||||
| 	z-index: 1; | ||||
| 	width: 100%; | ||||
| 	opacity: 1; | ||||
| 	transform: translateX(0); | ||||
| 	transition: transform 500ms cubic-bezier(0.23, 1, 0.32, 1), opacity 500ms cubic-bezier(0.23, 1, 0.32, 1); | ||||
| } | ||||
| .page-leave-active { | ||||
| 	opacity: 1; | ||||
| 	transform: translateX(0); | ||||
| 	transition: transform 500ms cubic-bezier(0.23, 1, 0.32, 1), opacity 500ms cubic-bezier(0.23, 1, 0.32, 1); | ||||
| } | ||||
| .page-enter-from { | ||||
| 	//opacity: 0; | ||||
| 	transform: translateX(128px); | ||||
| 
 | ||||
| 	/* iOSはoverflow: clipをサポートしていない */  | ||||
| 	@supports (-webkit-touch-callout: none) { | ||||
| 		transform: translateX(0); | ||||
| 	} | ||||
| } | ||||
| .page-leave-active { | ||||
| 	opacity: 0; | ||||
| 	transform: translateX(-64px); | ||||
| 
 | ||||
| 	/* iOSはoverflow: clipをサポートしていない */  | ||||
| 	@supports (-webkit-touch-callout: none) { | ||||
| 		transform: translateX(0); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| .mk-app { | ||||
| 	$header-height: 50px; | ||||
| 	$ui-font-size: 1em; | ||||
|  | @ -294,6 +333,7 @@ export default defineComponent({ | |||
| 			} | ||||
| 
 | ||||
| 			> .content { | ||||
| 				position: relative; | ||||
| 				background: var(--bg); | ||||
| 				--stickyTop: #{$header-height}; | ||||
| 			} | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue