feat: glass effect toggle, media refresh timing fix, page transition perf
This commit is contained in:
@@ -42,9 +42,10 @@ body {
|
||||
.rail {
|
||||
width: 80px;
|
||||
background: var(--glass-bg);
|
||||
backdrop-filter: blur(20px) saturate(1.2) brightness(1.05) contrast(1.1);
|
||||
-webkit-backdrop-filter: blur(20px) saturate(1.2) brightness(1.05) contrast(1.1);
|
||||
backdrop-filter: var(--blur-filter);
|
||||
-webkit-backdrop-filter: var(--blur-filter);
|
||||
border-right: 1px solid var(--glass-border);
|
||||
box-shadow: var(--glass-shadow);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
@@ -70,6 +71,8 @@ body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
gap: 3px;
|
||||
background: none;
|
||||
border: none;
|
||||
@@ -87,7 +90,7 @@ body {
|
||||
justify-content: center;
|
||||
}
|
||||
.rail-item .ico svg { width: 100%; height: 100%; display: block; }
|
||||
.rail-item .lbl { font-size: 11px; }
|
||||
.rail-item .lbl { font-size: 11px; text-align: center; width: 100%; }
|
||||
|
||||
.rail-item.active { background: var(--accent); color: #fff; }
|
||||
|
||||
@@ -140,9 +143,10 @@ body {
|
||||
/* Card: soft-glass morphism (reuse Task 4 tokens, not a solid color) */
|
||||
.card {
|
||||
background: var(--glass-bg);
|
||||
backdrop-filter: blur(20px) saturate(1.2) brightness(1.05) contrast(1.1);
|
||||
-webkit-backdrop-filter: blur(20px) saturate(1.2) brightness(1.05) contrast(1.1);
|
||||
backdrop-filter: var(--blur-filter);
|
||||
-webkit-backdrop-filter: var(--blur-filter);
|
||||
border: 1px solid var(--glass-border);
|
||||
box-shadow: var(--glass-shadow);
|
||||
border-radius: 14px;
|
||||
padding: 20px;
|
||||
color: var(--text);
|
||||
@@ -298,8 +302,8 @@ body {
|
||||
padding: 6px 10px;
|
||||
border-radius: 999px;
|
||||
background: var(--glass-bg);
|
||||
backdrop-filter: blur(20px) saturate(1.2);
|
||||
-webkit-backdrop-filter: blur(20px) saturate(1.2);
|
||||
backdrop-filter: var(--blur-filter);
|
||||
-webkit-backdrop-filter: var(--blur-filter);
|
||||
border: 1px solid var(--glass-border);
|
||||
z-index: 100;
|
||||
}
|
||||
@@ -343,8 +347,8 @@ body {
|
||||
padding: 8px;
|
||||
border-radius: 16px;
|
||||
background: var(--glass-bg);
|
||||
backdrop-filter: blur(20px) saturate(1.2);
|
||||
-webkit-backdrop-filter: blur(20px) saturate(1.2);
|
||||
backdrop-filter: var(--blur-filter);
|
||||
-webkit-backdrop-filter: var(--blur-filter);
|
||||
border: 1px solid var(--glass-border);
|
||||
z-index: 100;
|
||||
}
|
||||
@@ -408,9 +412,10 @@ body {
|
||||
margin-bottom: 8px;
|
||||
border-radius: 14px;
|
||||
background: var(--glass-bg);
|
||||
backdrop-filter: blur(20px) saturate(1.2) brightness(1.05) contrast(1.1);
|
||||
-webkit-backdrop-filter: blur(20px) saturate(1.2) brightness(1.05) contrast(1.1);
|
||||
backdrop-filter: var(--blur-filter);
|
||||
-webkit-backdrop-filter: var(--blur-filter);
|
||||
border: 1px solid var(--glass-border);
|
||||
box-shadow: var(--glass-shadow);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,18 @@
|
||||
--text: #1a1a1a;
|
||||
--text-dim: #8a8a90;
|
||||
--accent: #ff6900;
|
||||
/* 玻璃效果默认关闭:无模糊、无高光(普通半透明) */
|
||||
/* Glass effect off by default: no blur, no highlight (plain translucent) */
|
||||
--blur-filter: none;
|
||||
--glass-shadow: none;
|
||||
}
|
||||
|
||||
/* 玻璃效果开启:磨砂模糊 + 边缘反射高光(液态玻璃,参考 Apple WWDC25) */
|
||||
/* Glass effect on: frosted blur + edge-reflection highlight (liquid glass) */
|
||||
:root[data-glass="on"] {
|
||||
--blur-filter: blur(20px) saturate(1.2) brightness(1.05) contrast(1.1);
|
||||
--glass-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18),
|
||||
inset 0 -1px 0 rgba(255, 255, 255, 0.04);
|
||||
}
|
||||
|
||||
/* 系统深色:仅在未强制浅色时生效(跟随系统) */
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<link rel="stylesheet" href="css/tokens.css">
|
||||
<link rel="stylesheet" href="css/app.css">
|
||||
<script src="js/theme.js"></script>
|
||||
<script src="js/glass.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wallpaper-dim"></div>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// 玻璃效果开关:普通半透明(默认)/ 液态玻璃(backdrop-filter 磨砂 + 边缘高光)
|
||||
// Glass effect toggle: plain translucent (default) / liquid glass (backdrop-filter
|
||||
// frost + edge highlight), persisted in localStorage
|
||||
(function () {
|
||||
const KEY = 'hearth-glass';
|
||||
|
||||
window.glass = {
|
||||
enabled() {
|
||||
return localStorage.getItem(KEY) === '1';
|
||||
},
|
||||
setEnabled(on) {
|
||||
localStorage.setItem(KEY, on ? '1' : '0');
|
||||
this.apply();
|
||||
},
|
||||
// 应用开关:写 data-glass 属性,CSS 据此切换 --blur-filter 等变量
|
||||
// Apply: set the data-glass attribute; CSS switches --blur-filter etc. from it
|
||||
apply() {
|
||||
document.documentElement.setAttribute('data-glass', this.enabled() ? 'on' : 'off');
|
||||
},
|
||||
};
|
||||
|
||||
// 启动即应用(默认关闭 = 普通半透明)
|
||||
window.glass.apply();
|
||||
})();
|
||||
@@ -10,6 +10,10 @@ window.loadSettings = function () {
|
||||
<span class="lbl">主题</span>
|
||||
<span class="arrow" id="theme-state">跟随系统</span>
|
||||
</div>
|
||||
<div class="st-item" id="glass-item">
|
||||
<span class="lbl">玻璃效果</span>
|
||||
<span class="sw" id="glass-sw"><i></i></span>
|
||||
</div>
|
||||
<div class="st-item" id="brightness-item">
|
||||
<span class="lbl">屏幕亮度</span>
|
||||
<span class="arrow" id="brightness-state">›</span>
|
||||
@@ -41,6 +45,7 @@ window.loadSettings = function () {
|
||||
<div class="st-item"><span class="lbl">版本 0.1.0</span><span class="arrow">›</span></div>
|
||||
</div>`;
|
||||
setupTheme(page);
|
||||
setupGlass(page);
|
||||
setupMask(page);
|
||||
setupNotificationAccess(page);
|
||||
setupBrightness(page);
|
||||
@@ -71,6 +76,18 @@ function setupTheme(page) {
|
||||
};
|
||||
}
|
||||
|
||||
// 玻璃效果开关:普通半透明 ↔ 液态玻璃(backdrop-filter 磨砂 + 边缘高光)
|
||||
// Glass effect toggle: plain translucent vs liquid glass
|
||||
function setupGlass(page) {
|
||||
const sw = page.querySelector('#glass-sw');
|
||||
const refresh = () => sw.classList.toggle('on', glass.enabled());
|
||||
refresh();
|
||||
page.querySelector('#glass-item').onclick = () => {
|
||||
glass.setEnabled(!glass.enabled());
|
||||
refresh();
|
||||
};
|
||||
}
|
||||
|
||||
// 背景遮罩:开关 + 明暗度(仅夜间主题显示)
|
||||
// Wallpaper dim: toggle + opacity (shown only under dark theme)
|
||||
function setupMask(page) {
|
||||
|
||||
@@ -29,9 +29,16 @@ const router = {
|
||||
// always occupies space; only toggle visibility to avoid shifting icons)
|
||||
const clock = document.getElementById('rail-clock');
|
||||
if (clock) clock.style.visibility = (id === 'home') ? 'hidden' : 'visible';
|
||||
if (id === 'home') window.updateHomeCards && window.updateHomeCards();
|
||||
if (id === 'applist') window.loadAppList && window.loadAppList();
|
||||
if (id === 'webapplist') window.loadWebAppList && window.loadWebAppList();
|
||||
if (id === 'settings') window.loadSettings && window.loadSettings();
|
||||
// 延迟内容加载到下一帧:让切换动画先流畅播放,避免加载重活(查应用/拉清单)
|
||||
// 在动画帧内阻塞导致卡顿
|
||||
// Defer content loading to the next frame: let the switch animation play
|
||||
// smoothly first, avoiding jank from heavy loads (app query / manifest fetch)
|
||||
// blocking within the animation frame
|
||||
requestAnimationFrame(() => {
|
||||
if (id === 'home') window.updateHomeCards && window.updateHomeCards();
|
||||
if (id === 'applist') window.loadAppList && window.loadAppList();
|
||||
if (id === 'webapplist') window.loadWebAppList && window.loadWebAppList();
|
||||
if (id === 'settings') window.loadSettings && window.loadSettings();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user