增加 配色切换动画
All checks were successful
Build / build (push) Successful in 1m24s

This commit is contained in:
Twilight 2024-10-06 00:50:17 +08:00
parent e84a897619
commit a90997d12d
7 changed files with 209 additions and 24 deletions

View File

@ -43,6 +43,7 @@
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.4.0",
"eslint-plugin-vue": "^9.27.0",
"less": "^4.2.0",
"naive-ui": "^2.39.0",
"postcss": "^8.4.45",
"prettier": "^3.3.3",

View File

@ -49,9 +49,9 @@
</template>
<script setup>
import { computed } from 'vue'
import hljs from 'highlight.js/lib/core'
import ini from 'highlight.js/lib/languages/ini'
import { computed } from "vue";
import hljs from "highlight.js/lib/core";
import ini from "highlight.js/lib/languages/ini";
import {
darkTheme,
@ -63,14 +63,78 @@ import {
NMessageProvider,
NNotificationProvider,
useOsTheme,
zhCN
} from 'naive-ui'
zhCN,
} from "naive-ui";
// import Lottie from "./components/Lottie.vue";
import DefaultLayout from './layouts/DefaultLayout.vue'
import { useUserStore } from './stores/user'
import DefaultLayout from "./layouts/DefaultLayout.vue";
import { useUserStore } from "./stores/user";
import { useAppStore } from "./stores/app";
const osThemeRef = useOsTheme()
const theme = computed(() => (osThemeRef.value === 'dark' ? darkTheme : null))
const appStore = useAppStore();
const osThemeRef = useOsTheme();
let switched = false;
const theme = computed(() => {
if (switched && document.startViewTransition) {
switch_appearance_with_transitions(osThemeRef.value);
}
switched = true;
if (osThemeRef.value === "dark") {
document.documentElement.setAttribute("theme", "dark");
return darkTheme;
} else {
document.documentElement.setAttribute("theme", "light");
return null;
}
});
// event
const switch_appearance_with_transitions = (toColor) => {
const transition = document.startViewTransition(() => {});
//
let x = appStore.headerCenterLogoPosition.x;
let y = appStore.headerCenterLogoPosition.y;
if (toColor === "dark") {
//
const innerWidth = window.innerWidth;
const innerHeight = window.innerHeight;
x = innerWidth / 2;
y = innerHeight - 1;
}
console.log(x, y);
const endRadius = Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y)
);
//
transition.ready.then(() => {
// 0endRadius
document.documentElement.animate(
{
clipPath: [
`circle(0 at ${x}px ${y}px)`,
`circle(${endRadius}px at ${x}px ${y}px)`,
],
},
{
duration: 500,
easing: "ease-in",
//
pseudoElement: "::view-transition-new(root)",
}
);
});
};
// watch theme change
// const load_step = ref(1)
//
@ -87,7 +151,7 @@ const theme = computed(() => (osThemeRef.value === 'dark' ? darkTheme : null))
// load_step.value = 2
// }
hljs.registerLanguage('ini', ini)
hljs.registerLanguage("ini", ini);
//
/**
@ -109,13 +173,10 @@ const themeOverrides = {
common: {
fontFamily: "Noto Sans SC, sans-serif",
fontFamilyMono: "JetBrains Mono, monospace",
}
}
},
};
// UserStore
const userStore = useUserStore();
userStore.setupTimer();
</script>

View File

@ -37,6 +37,7 @@
<div
@click="showDrawer = true"
class="cursor-pointer ml-3 flex justify-center items-center"
ref="leftMenu"
>
<n-icon size="24">
<menu-outline />
@ -61,6 +62,7 @@
<img
:src="leaflowpng"
class="w-8 cursor-pointer block select-none"
ref="centerLogo"
@click="toggleHomeChat"
/>
</div>
@ -76,18 +78,14 @@
</div>
</n-grid-item>
<n-grid-item class="flex items-center justify-end mr-1.5">
<n-grid-item class="flex items-center justify-end mr-1.5">
<!-- 右侧 -->
<div v-if="userStore.logined"
class="flex items-center">
<div v-if="userStore.logined" class="flex items-center">
<!-- 新对话 -->
<n-tooltip trigger="hover">
<template #trigger>
<n-icon
class="text-2xl mr-4 cursor-pointer"
@click="newChat"
>
<n-icon class="text-2xl mr-4 cursor-pointer" @click="newChat">
<AddOutline />
</n-icon>
</template>
@ -216,8 +214,10 @@ import leaflowpng from "@/assets/images/leaflow.png";
import { useChatStore } from "@/stores/chat";
import groupPng from "@/assets/images/group.png";
import config from "@/config/config";
import { useAppStore } from "@/stores/app";
const userStore = useUserStore();
const appStore = useAppStore();
const chatStore = useChatStore();
const isMobile = useIsMobile();
const showDrawer = ref(false);
@ -253,4 +253,40 @@ const newChat = () => {
const gotoLogin = () => {
router.push("/auth/login");
};
const leftMenu = ref();
const centerLogo = ref();
const setCirclePosition = () => {
if (isMobile.value) {
// leftMenu
const leftMenuRect = leftMenu.value.getBoundingClientRect();
//
const centerX = leftMenuRect.x + leftMenuRect.width / 2;
const centerY = leftMenuRect.y + leftMenuRect.height / 2;
appStore.headerCenterLogoPosition.x = centerX;
appStore.headerCenterLogoPosition.y = centerY;
} else {
// centerLogo
const centerLogoRect = centerLogo.value.getBoundingClientRect();
//
const centerX = centerLogoRect.x + centerLogoRect.width / 2;
const centerY = centerLogoRect.y + centerLogoRect.height / 2;
appStore.headerCenterLogoPosition.x = centerX;
appStore.headerCenterLogoPosition.y = centerY;
}
};
onMounted(() => {
setCirclePosition();
});
window.addEventListener("resize", setCirclePosition);
onUnmounted(() => {
window.removeEventListener("resize", setCirclePosition);
});
</script>

View File

@ -2,7 +2,8 @@ const meta = document.createElement("meta");
meta.name = "naive-ui-style";
document.head.appendChild(meta);
import "./style.css";
import "./styles/style.css";
import "./styles/color.less";
import "animate.css";
import { registerPlugins } from "./plugins";
import router from "./router";

View File

@ -9,5 +9,9 @@ export const useAppStore = defineStore("app", {
contentScrollPosition: 0,
contentScrollOnBottom: false,
contentScrollable: false,
headerCenterLogoPosition: {
x: 0,
y: 0,
}
}),
});

82
src/styles/color.less Normal file
View File

@ -0,0 +1,82 @@
// // light-dark-8deg-animation
// @keyframes light-to-dark {
// from {
// clip-path: polygon(
// 0 0,
// 0 0,
// calc(tan(8deg) * -100vh) 100%,
// calc(tan(8deg) * -100vh) 100%
// );
// }
// to {
// clip-path: polygon(
// 0 0,
// calc((tan(8deg) * 100vh) + 100%) 0,
// 100% 100%,
// calc(tan(8deg) * -100vh) 100%
// );
// }
// }
// @keyframes dark-to-light {
// from {
// clip-path: polygon(
// calc((tan(8deg) * 100vh) + 100%) 0,
// calc((tan(8deg) * 100vh) + 100%) 0,
// 100% 100%,
// 100% 100%
// );
// }
// to {
// clip-path: polygon(
// 0 0,
// calc((tan(8deg) * 100vh) + 100%) 0,
// 100% 100%,
// calc(tan(8deg) * -100vh) 100%
// );
// }
// }
// :root::view-transition-group(root) {
// animation-duration: 1s;
// }
// :root::view-transition-new(root),
// :root::view-transition-old(root) {
// mix-blend-mode: normal;
// }
// :root::view-transition-old(root),
// :root[theme="dark"]::view-transition-old(root) {
// animation: none;
// }
// :root::view-transition-new(root) {
// animation-name: dark-to-light;
// }
// :root[theme="dark"]::view-transition-new(root) {
// animation-name: light-to-dark;
// }
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
:root[theme="dark"]::view-transition-old(root) {
z-index: 1;
}
:root[theme="light"]::view-transition-new(root) {
z-index: 999;
}
::view-transition-old(root) {
z-index: 999;
}
::view-transition-new(root) {
z-index: 1;
}

View File

@ -1,5 +1,5 @@
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@100..900&display=swap");
@import "styles/github-markdown.css";
@import "github-markdown.css";
@tailwind base;
@tailwind components;
@tailwind utilities;