Skip to content

Commit

Permalink
feat: ✨ dark mode transition
Browse files Browse the repository at this point in the history
  • Loading branch information
CodeGetters committed Aug 29, 2023
1 parent 1bf032b commit dfe6a5d
Show file tree
Hide file tree
Showing 11 changed files with 496 additions and 389 deletions.
9 changes: 7 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link rel="stylesheet" href="loading.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue + TS</title>
</head>
<body>
<div id="loading"></div>
<body class="page-loading">
<div id="app"></div>

<div id="loading-screen" class="loading-screen">
<span>Loading ...</span>
</div>

<script type="module" src="/src/main.ts"></script>
</body>
</html>
28 changes: 14 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@
}
},
"dependencies": {
"@vueuse/core": "^10.3.0",
"axios": "^1.4.0",
"@vueuse/core": "^10.4.1",
"axios": "^1.5.0",
"normalize.css": "^8.0.1",
"nprogress": "^0.2.0",
"pinia": "^2.1.6",
Expand All @@ -58,35 +58,35 @@
"devDependencies": {
"@commitlint/cli": "^17.7.1",
"@commitlint/config-conventional": "^17.7.0",
"@types/node": "^20.5.1",
"@types/node": "^20.5.7",
"@types/nprogress": "^0.2.0",
"@typescript-eslint/eslint-plugin": "^6.4.1",
"@typescript-eslint/parser": "^6.4.1",
"@unocss/preset-attributify": "^0.55.2",
"@unocss/preset-icons": "^0.55.2",
"@unocss/preset-typography": "^0.55.2",
"@typescript-eslint/eslint-plugin": "^6.5.0",
"@typescript-eslint/parser": "^6.5.0",
"@unocss/preset-attributify": "^0.55.3",
"@unocss/preset-icons": "^0.55.3",
"@unocss/preset-typography": "^0.55.3",
"@vitejs/plugin-vue": "^4.3.3",
"@vitest/coverage-istanbul": "^0.34.2",
"@vitest/coverage-istanbul": "^0.34.3",
"@vue/test-utils": "^2.4.1",
"@vue/tsconfig": "^0.4.0",
"cz-git": "^1.7.1",
"eslint": "^8.47.0",
"eslint": "^8.48.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"eslint-plugin-vue": "^9.17.0",
"happy-dom": "^10.11.0",
"happy-dom": "^10.11.1",
"husky": "^8.0.3",
"lint-staged": "^14.0.1",
"prettier": "^3.0.2",
"sass": "^1.66.1",
"typescript": "^5.1.6",
"unocss": "^0.55.2",
"typescript": "^5.2.2",
"unocss": "^0.55.3",
"unplugin-auto-import": "^0.16.6",
"vite": "^4.4.9",
"vite-plugin-checker": "^0.6.2",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-vue-devtools": "^1.0.0-rc.2",
"vitest": "^0.34.2",
"vitest": "^0.34.3",
"vue-tsc": "^1.8.8"
}
}
49 changes: 49 additions & 0 deletions public/loading.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
body.page-loading {
margin: 0;
height: 100%;
overflow: hidden;
}

.loading-screen {
display: none;
}

.page-loading .loading-screen {
position: absolute;
z-index: 1000;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: #f9f9f9;
color: #5e6278;
line-height: 1;
font-size: 16px;
}

.page-loading .loading-screen span {
color: #5e6278;
transition: none !important;
-webkit-font-smoothing: antialiased;
}

.page-loading .loading-screen img {
margin-left: calc(100vw - 100%);
margin-bottom: 30px;
height: 40px !important;
}

html[class="dark"] .page-loading .loading-screen {
background-color: #151521;
color: #ffffff;
}

.loading-screen .dark-logo {
display: none;
}

.loading-screen .light-logo {
display: block;
}
24 changes: 5 additions & 19 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,29 +1,15 @@
<script setup lang="ts">
import { onMounted, onBeforeMount } from "vue";
const loading = document.querySelector("#loading");
onBeforeMount(() => {
if (loading) {
loading.classList.add("loading");
}
});
import { onMounted, nextTick } from "vue";
onMounted(() => {
setTimeout(() => {
if (loading) {
loading.classList.remove("loading");
}
}, 3000);
nextTick(() => {
document.body.classList.remove("page-loading");
});
});
</script>

<template>
<router-view v-slot="{ Component }">
<transition name="fade">
<component :is="Component" />
</transition>
</router-view>
<router-view />
</template>

<style lang="scss">
Expand Down
47 changes: 0 additions & 47 deletions src/assets/styles/normal.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,3 @@
font-family: "CascadiaCode";
src: url("../fonts/CascadiaCode.ttf");
}
body::-webkit-scrollbar {
display: none;
}

/* loading */
.loading {
display: block;
position: relative;
width: 6px;
height: 20px;
margin: 50vh auto;
animation: rectangle infinite 1s ease-in-out -0.2s;
background-color: #000;
}

.loading:before,
.loading:after {
position: absolute;
width: 6px;
height: 10px;
content: "";
background-color: #000;
}

.loading:before {
left: -14px;
animation: rectangle infinite 1s ease-in-out -0.4s;
}

.loading:after {
right: -14px;
animation: rectangle infinite 1s ease-in-out;
}

@keyframes rectangle {
0%,
80%,
100% {
height: 20px;
box-shadow: 0 0 #000;
}

40% {
height: 30px;
box-shadow: 0 -20px #000;
}
}
30 changes: 29 additions & 1 deletion src/assets/styles/scss/init.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,32 @@
body {
font-family: "CascadiaCode";
background-color: skyblue;
}

/* toggle theme */
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
::view-transition-old(root) {
z-index: 1;
}
::view-transition-new(root) {
z-index: 9999;
}
.dark::view-transition-old(root) {
z-index: 9999;
}
.dark::view-transition-new(root) {
z-index: 1;
}

.v-enter-active,
.v-leave-active {
transition: opacity 0.5s ease;
}

.v-enter-from,
.v-leave-to {
opacity: 0;
}
1 change: 1 addition & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { i18n } from "@/i18n/index";
import "virtual:uno.css";

const app = createApp(App);

app.use(i18n);
app.use(router);

Expand Down
26 changes: 16 additions & 10 deletions src/pages/HomePage.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<script setup lang="ts">
import { useI18n } from "vue-i18n";
import { toggleDark } from "@/utils/toggleDark";
const { locale, t } = useI18n();
import { useDark, useToggle } from "@vueuse/core";
/**
* @description 语言切换
Expand All @@ -10,17 +11,22 @@ const changeLang = () => {
locale.value === "zh" ? (locale.value = "en") : (locale.value = "zh");
};
const isDark = useDark();
const toggleDark = useToggle(isDark);
console.log(locale.value);
</script>

<template>
<div class="home .dark:bg-black .dark:text-#fff">
<span class="text-red">home</span>
<span class="bg-red" @click="changeLang()">{{ t("hello") }}</span>
<router-link to="/404">notFound</router-link>
<span @click="toggleDark()">主题切换</span>
<span text-red>预设</span>
<span bg="blue-400 hover:blue-500">预设</span>
<div
class="home .dark:bg-black .dark:text-#fff text-18px h100vh flex flex-col justify-center items-center"
>
<div class="text-red">{{ t("hello") }}</div>
<div class="container flex flex-row items-center justify-center">
<button @click="toggleDark">
<div i-carbon-sun dark:i-carbon-moon cursor-pointer />
</button>
<button @click="changeLang()" cursor-pointer>切换语言</button>
<router-link to="/404">
<button cursor-pointer>404</button>
</router-link>
</div>
</div>
</template>
2 changes: 1 addition & 1 deletion src/pages/NotFound.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts"></script>

<template>
<div class="notFound">
<div class="notFound flex items-center justify-center h100vh">
<span>404</span>
<router-link to="/">home</router-link>
</div>
Expand Down
57 changes: 57 additions & 0 deletions src/utils/toggleDark.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { nextTick } from "vue";
import { useDark } from "@vueuse/core";

export const isDark = useDark();

/**
* @param event
*/
export function toggleDark(event: MouseEvent): void {
const isAppearanceTransition =
// @ts-expect-error experimental API
document.startViewTransition &&
!window.matchMedia("(prefers-reduced-motion: reduce)").matches;

if (!isAppearanceTransition) {
isDark.value = !isDark.value;
return;
}

// Get the click position, or fallback to the middle of the screen
const x: number = event.clientX;
const y: number = event.clientY;
// Get the distance to the furthest corner
const endRadius: number = Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y),
);

// @ts-expect-error experimental API
const transition = document.startViewTransition(async () => {
isDark.value = !isDark.value;
await nextTick();
});

// Wait for the pseudo-elements to be created:
transition.ready.then(() => {
// Animate the root’s new view
const clipPath: string[] = [
`circle(0px at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`,
];

document.documentElement.animate(
{
clipPath: isDark.value ? [...clipPath].reverse() : clipPath,
},
{
duration: 400,
easing: "ease-out",
// Specify which pseudo-element to animate
pseudoElement: isDark.value
? "::view-transition-old(root)"
: "::view-transition-new(root)",
},
);
});
}
Loading

0 comments on commit dfe6a5d

Please sign in to comment.