feat: add configurable opacity and blur settings for the transparent theme background

This commit is contained in:
jxxghp
2026-05-13 22:34:12 +08:00
parent e62a0b5a8d
commit 9965428bae
5 changed files with 95 additions and 2 deletions

View File

@@ -49,6 +49,26 @@ const backgroundImages = ref<string[]>([])
const activeImageIndex = ref(0)
const isTransparentTheme = computed(() => globalTheme.name.value === 'transparent')
function getStoredNumber(key: string, fallback: number, min: number, max: number) {
const parsed = Number.parseFloat(localStorage.getItem(key) || '')
if (!Number.isFinite(parsed)) return fallback
return Math.min(max, Math.max(min, parsed))
}
function applyTransparentBackgroundSettings() {
document.documentElement.style.setProperty(
'--transparent-background-poster-opacity',
getStoredNumber('transparency-background-poster-opacity', 1, 0, 1).toString(),
)
document.documentElement.style.setProperty(
'--transparent-background-blur',
`${getStoredNumber('transparency-background-blur', 16, 0, 30)}px`,
)
}
applyTransparentBackgroundSettings()
// 心跳检测
let heartbeatInterval: number | null = null
@@ -266,7 +286,11 @@ onUnmounted(() => {
<template>
<div class="app-wrapper">
<!-- 透明主题背景 -->
<div v-if="backgroundImages.length > 0 && (isTransparentTheme || !isLogin)" class="background-container">
<div
v-if="backgroundImages.length > 0 && (isTransparentTheme || !isLogin)"
class="background-container"
:class="{ 'is-transparent-theme': isTransparentTheme && isLogin }"
>
<div
v-for="(imageUrl, index) in backgroundImages"
:key="`bg-${index}-${loginStateKey}`"
@@ -331,11 +355,15 @@ onUnmounted(() => {
}
}
.background-container.is-transparent-theme .background-image.active {
opacity: var(--transparent-background-poster-opacity, 1);
}
/* 全局磨砂层 */
.global-blur-layer {
position: absolute;
z-index: 1;
backdrop-filter: blur(16px);
backdrop-filter: blur(var(--transparent-background-blur, 16px));
background-color: rgba(128, 128, 128, 30%);
block-size: 100%;
inline-size: 100%;

View File

@@ -58,6 +58,8 @@ const customCSS = ref('')
// 透明度相关
const transparencyOpacity = ref(parseFloat(localStorage.getItem('transparency-opacity') || '0.3'))
const transparencyBlur = ref(parseFloat(localStorage.getItem('transparency-blur') || '10'))
const backgroundPosterOpacity = ref(parseFloat(localStorage.getItem('transparency-background-poster-opacity') || '1'))
const backgroundBlur = ref(parseFloat(localStorage.getItem('transparency-background-blur') || '16'))
const transparencyLevel = ref(localStorage.getItem('transparency-level') || 'medium')
const isTransparentTheme = computed(() => currentThemeName.value === 'transparent')
const showTransparencyDialog = ref(false)
@@ -383,6 +385,15 @@ async function saveCustomCSS() {
function applyTransparencySettings() {
const root = document.documentElement
if (!Number.isFinite(backgroundPosterOpacity.value)) {
backgroundPosterOpacity.value = 1
}
backgroundPosterOpacity.value = Math.min(1, Math.max(0, backgroundPosterOpacity.value))
if (!Number.isFinite(backgroundBlur.value)) {
backgroundBlur.value = 16
}
backgroundBlur.value = Math.min(30, Math.max(0, backgroundBlur.value))
// 设置CSS变量
root.style.setProperty('--transparent-opacity', transparencyOpacity.value.toString())
root.style.setProperty('--transparent-opacity-light', (transparencyOpacity.value * 0.67).toString())
@@ -390,10 +401,14 @@ function applyTransparencySettings() {
root.style.setProperty('--transparent-blur', `${transparencyBlur.value}px`)
root.style.setProperty('--transparent-blur-light', `${transparencyBlur.value * 0.6}px`)
root.style.setProperty('--transparent-blur-heavy', `${transparencyBlur.value * 1.6}px`)
root.style.setProperty('--transparent-background-poster-opacity', backgroundPosterOpacity.value.toString())
root.style.setProperty('--transparent-background-blur', `${backgroundBlur.value}px`)
// 保存到本地存储
localStorage.setItem('transparency-opacity', transparencyOpacity.value.toString())
localStorage.setItem('transparency-blur', transparencyBlur.value.toString())
localStorage.setItem('transparency-background-poster-opacity', backgroundPosterOpacity.value.toString())
localStorage.setItem('transparency-background-blur', backgroundBlur.value.toString())
}
// 调整透明度预设
@@ -434,10 +449,22 @@ function onBlurChange() {
transparencyLevel.value = ''
}
// 背景海报透明度变化处理
function onBackgroundPosterOpacityChange() {
applyTransparencySettings()
}
// 背景磨砂变化处理
function onBackgroundBlurChange() {
applyTransparencySettings()
}
// 重置透明度设置
function resetTransparencySettings() {
transparencyOpacity.value = 0.3
transparencyBlur.value = 10
backgroundPosterOpacity.value = 1
backgroundBlur.value = 16
transparencyLevel.value = 'medium'
applyTransparencySettings()
}
@@ -821,6 +848,38 @@ onUnmounted(() => {
/>
</div>
<!-- 背景海报透明度滑动条 -->
<div>
<div class="d-flex align-center justify-space-between mb-2">
<span class="text-body-2">{{ t('theme.backgroundPosterOpacity') }}</span>
<span class="text-caption">{{ Math.round(backgroundPosterOpacity * 100) }}%</span>
</div>
<VSlider
v-model="backgroundPosterOpacity"
:min="0"
:max="1"
:step="0.01"
color="primary"
@update:model-value="onBackgroundPosterOpacityChange"
/>
</div>
<!-- 背景磨砂滑动条 -->
<div>
<div class="d-flex align-center justify-space-between mb-2">
<span class="text-body-2">{{ t('theme.backgroundBlur') }}</span>
<span class="text-caption">{{ backgroundBlur }}px</span>
</div>
<VSlider
v-model="backgroundBlur"
:min="0"
:max="30"
:step="1"
color="primary"
@update:model-value="onBackgroundBlurChange"
/>
</div>
<!-- 预设按钮 -->
<div>
<span class="text-body-2 d-block mb-2">{{ t('common.preset') }}</span>

View File

@@ -149,6 +149,8 @@ export default {
transparencyAdjust: 'Transparency Adjustment',
transparencyOpacity: 'Opacity',
transparencyBlur: 'Blur',
backgroundPosterOpacity: 'Background Opacity',
backgroundBlur: 'Background Frosted Blur',
transparencyReset: 'Reset',
transparencyLow: 'Low Transparency',
transparencyMedium: 'Medium Transparency',

View File

@@ -149,6 +149,8 @@ export default {
transparencyAdjust: '透明度调整',
transparencyOpacity: '透明度',
transparencyBlur: '模糊度',
backgroundPosterOpacity: '背景透明度',
backgroundBlur: '背景磨砂效果',
transparencyReset: '重置',
transparencyLow: '低透明度',
transparencyMedium: '中等透明度',

View File

@@ -149,6 +149,8 @@ export default {
transparencyAdjust: '透明度調整',
transparencyOpacity: '透明度',
transparencyBlur: '模糊度',
backgroundPosterOpacity: '背景透明度',
backgroundBlur: '背景磨砂效果',
transparencyReset: '重置',
transparencyLow: '低透明度',
transparencyMedium: '中等透明度',