feat: add glass materials and quality profiles (#577)

This commit is contained in:
InfinityPacer
2026-07-23 06:08:39 +08:00
committed by GitHub
parent 80519e6839
commit 1ed69ccc64
19 changed files with 2587 additions and 238 deletions
@@ -0,0 +1,32 @@
<script setup lang="ts">
import type { ThemeCustomizerGlassAppearance, ThemeCustomizerGlassQuality } from '@/composables/useThemeCustomizer'
import { useGlassOpticalRenderer } from '@/composables/useGlassOpticalRenderer'
const props = defineProps<{
/** 当前玻璃材质,用于选择透明、色调或磨砂的光学参数。 */
appearance: ThemeCustomizerGlassAppearance
/** 当前光学质量;标准档不会挂载该组件。 */
quality: Exclude<ThemeCustomizerGlassQuality, 'css'>
/** 路由变化标识,用于在页面内容稳定后重新发现高价值表面。 */
routeKey: string
/** 当前主题主色,用于同步色调材质的光学高光。 */
tintColor: string
/** 与 CSS 背景保持一致的活动壁纸。 */
wallpaperUrl: string
}>()
const canvas = ref<HTMLCanvasElement | null>(null)
const { state } = useGlassOpticalRenderer({
active: true,
appearance: () => props.appearance,
canvas,
quality: () => props.quality,
routeKey: () => props.routeKey,
tintColor: () => props.tintColor,
wallpaperUrl: () => props.wallpaperUrl,
})
</script>
<template>
<canvas ref="canvas" class="glass-optical-layer" aria-hidden="true" :data-state="state" />
</template>
+12 -14
View File
@@ -22,6 +22,8 @@ const customColorInput = ref<HTMLInputElement | null>(null)
const {
isCustomized,
resetSettings,
setGlassAppearance,
setGlassQuality,
setLayout,
setPrimaryColor,
setRadius,
@@ -137,6 +139,8 @@ const showShadowSection = computed(() => globalTheme.name.value !== 'glass')
const hasAppModeCustomization = computed(() => {
return (
settings.value.primaryColor !== defaultPrimaryColor ||
settings.value.glassAppearance !== 'clear' ||
settings.value.glassQuality !== 'css' ||
settings.value.radius !== 'default' ||
settings.value.shadow !== '0' ||
settings.value.skin !== 'default' ||
@@ -197,6 +201,8 @@ async function handleResetSettings() {
// App 模式共享定制器,但保留桌面导航相关偏好,只重置 App 侧可调整的外观设置。
await setPrimaryColor(defaultPrimaryColor)
await setGlassAppearance('clear')
await setGlassQuality('css')
await setRadius('default')
await setShadow('0')
await setSkin('default')
@@ -205,11 +211,7 @@ async function handleResetSettings() {
</script>
<template>
<aside
class="theme-customizer-panel-host"
role="dialog"
:aria-label="t('theme.customizer.title')"
>
<aside class="theme-customizer-panel-host" role="dialog" :aria-label="t('theme.customizer.title')">
<div class="theme-customizer-panel" :class="{ 'theme-customizer-panel--dialog': appMode, 'app-surface': appMode }">
<div class="theme-customizer-header py-5 px-4">
<div>
@@ -320,10 +322,7 @@ async function handleResetSettings() {
:class="{ 'is-active': settings.radius === radius.value }"
@click="setRadius(radius.value)"
>
<span
class="theme-customizer-radius-scene"
:class="`theme-customizer-radius-scene--${radius.value}`"
>
<span class="theme-customizer-radius-scene" :class="`theme-customizer-radius-scene--${radius.value}`">
<span class="theme-customizer-radius-scene__card">
<span class="theme-customizer-radius-scene__badge" />
<span class="theme-customizer-radius-scene__line" />
@@ -350,7 +349,9 @@ async function handleResetSettings() {
>
<span class="theme-customizer-shadow-slider__sample-accent" />
<span class="theme-customizer-shadow-slider__sample-line" />
<span class="theme-customizer-shadow-slider__sample-line theme-customizer-shadow-slider__sample-line--short" />
<span
class="theme-customizer-shadow-slider__sample-line theme-customizer-shadow-slider__sample-line--short"
/>
</span>
<VSlider
:model-value="shadowSliderValue"
@@ -367,10 +368,7 @@ async function handleResetSettings() {
@update:model-value="handleShadowSliderChange"
/>
</div>
<div
class="theme-customizer-shadow-slider__scale"
aria-hidden="true"
>
<div class="theme-customizer-shadow-slider__scale" aria-hidden="true">
<span>0</span>
<span>24</span>
</div>