mirror of
https://github.com/yangzongzhuan/RuoYi-Vue3.git
synced 2026-01-13 12:34:59 +00:00
暗黑模式切换效果优化
This commit is contained in:
@@ -1 +1 @@
|
|||||||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 54.857h54.796v18.286H36.531V128H18.265V73.143H0V54.857zm127.857-36.571H91.935V128H72.456V18.286H36.534V0h91.326l-.003 18.286z"/></svg>
|
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path fill="#5a5e66" d="M0 54.857h54.796v18.286H36.531V128H18.265V73.143H0V54.857zm127.857-36.571H91.935V128H72.456V18.286H36.534V0h91.326l-.003 18.286z"/></svg>
|
||||||
|
Before Width: | Height: | Size: 211 B After Width: | Height: | Size: 226 B |
@@ -47,3 +47,34 @@
|
|||||||
.breadcrumb-leave-active {
|
.breadcrumb-leave-active {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 黑暗模式下过渡效果 */
|
||||||
|
::view-transition-new(root), ::view-transition-old(root) {
|
||||||
|
animation: none !important;
|
||||||
|
backface-visibility: hidden;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark::view-transition-old(root) {
|
||||||
|
z-index: 2147483646;
|
||||||
|
background: var(--bg-color-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark::view-transition-new(root) {
|
||||||
|
z-index: 1;
|
||||||
|
background: var(--bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
::view-transition-old(root) {
|
||||||
|
z-index: 1;
|
||||||
|
background: var(--bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
::view-transition-new(root) {
|
||||||
|
z-index: 2147483646;
|
||||||
|
background: var(--bg-color-dark);
|
||||||
|
}
|
||||||
|
|||||||
@@ -90,6 +90,9 @@ html.dark {
|
|||||||
--el-border-color: #434343;
|
--el-border-color: #434343;
|
||||||
--el-border-color-light: #434343;
|
--el-border-color-light: #434343;
|
||||||
|
|
||||||
|
/* primary */
|
||||||
|
--primary-bg: #18212b;
|
||||||
|
|
||||||
/* 侧边栏 */
|
/* 侧边栏 */
|
||||||
--sidebar-bg: #141414;
|
--sidebar-bg: #141414;
|
||||||
--sidebar-text: #ffffff;
|
--sidebar-text: #ffffff;
|
||||||
@@ -173,6 +176,33 @@ html.dark {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 按钮样式覆盖 */
|
||||||
|
.el-button--primary.is-plain {
|
||||||
|
background-color: var(--primary-bg);
|
||||||
|
border: 1px solid var(--el-color-primary-light-2);
|
||||||
|
color: var(--el-color-primary-light-2);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--el-button-hover-bg-color);
|
||||||
|
border-color: var(--el-button-hover-border-color);
|
||||||
|
color: var(--el-button-hover-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-disabled {
|
||||||
|
background-color: var(--link-active-bg-color);
|
||||||
|
border-color: var(--el-color-primary-light-3);
|
||||||
|
color: var(--el-color-primary-light-3);
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* primary tag 样式覆盖 */
|
||||||
|
.el-tag--primary {
|
||||||
|
background-color: var(--primary-bg);
|
||||||
|
border: 1px solid var(--el-border-color-light);
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
/* 表格样式覆盖 */
|
/* 表格样式覆盖 */
|
||||||
.el-table {
|
.el-table {
|
||||||
--el-table-header-bg-color: var(--el-bg-color-overlay) !important;
|
--el-table-header-bg-color: var(--el-bg-color-overlay) !important;
|
||||||
|
|||||||
@@ -111,8 +111,44 @@ function setLayout() {
|
|||||||
emits('setLayout')
|
emits('setLayout')
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleTheme() {
|
async function toggleTheme(event) {
|
||||||
settingsStore.toggleTheme()
|
const x = event?.clientX || window.innerWidth / 2
|
||||||
|
const y = event?.clientY || window.innerHeight / 2
|
||||||
|
const wasDark = settingsStore.isDark
|
||||||
|
|
||||||
|
const isReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
||||||
|
const isSupported = document.startViewTransition && !isReducedMotion
|
||||||
|
|
||||||
|
if (!isSupported) {
|
||||||
|
settingsStore.toggleTheme()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const transition = document.startViewTransition(async () => {
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 10))
|
||||||
|
settingsStore.toggleTheme()
|
||||||
|
await nextTick()
|
||||||
|
})
|
||||||
|
await transition.ready
|
||||||
|
|
||||||
|
const endRadius = Math.hypot(Math.max(x, window.innerWidth - x), Math.max(y, window.innerHeight - y))
|
||||||
|
const clipPath = [`circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`]
|
||||||
|
document.documentElement.animate(
|
||||||
|
{
|
||||||
|
clipPath: !wasDark ? [...clipPath].reverse() : clipPath
|
||||||
|
}, {
|
||||||
|
duration: 650,
|
||||||
|
easing: "cubic-bezier(0.4, 0, 0.2, 1)",
|
||||||
|
fill: "forwards",
|
||||||
|
pseudoElement: !wasDark ? "::view-transition-old(root)" : "::view-transition-new(root)"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
await transition.finished
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("View transition failed, falling back to immediate toggle:", error)
|
||||||
|
settingsStore.toggleTheme()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user