mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-05 15:36:49 +08:00
feat: add configurable opacity and blur settings for the transparent theme background
This commit is contained in:
+30
-2
@@ -49,6 +49,26 @@ const backgroundImages = ref<string[]>([])
|
|||||||
const activeImageIndex = ref(0)
|
const activeImageIndex = ref(0)
|
||||||
const isTransparentTheme = computed(() => globalTheme.name.value === 'transparent')
|
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
|
let heartbeatInterval: number | null = null
|
||||||
|
|
||||||
@@ -266,7 +286,11 @@ onUnmounted(() => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-wrapper">
|
<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
|
<div
|
||||||
v-for="(imageUrl, index) in backgroundImages"
|
v-for="(imageUrl, index) in backgroundImages"
|
||||||
:key="`bg-${index}-${loginStateKey}`"
|
: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 {
|
.global-blur-layer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
backdrop-filter: blur(16px);
|
backdrop-filter: blur(var(--transparent-background-blur, 16px));
|
||||||
background-color: rgba(128, 128, 128, 30%);
|
background-color: rgba(128, 128, 128, 30%);
|
||||||
block-size: 100%;
|
block-size: 100%;
|
||||||
inline-size: 100%;
|
inline-size: 100%;
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ const customCSS = ref('')
|
|||||||
// 透明度相关
|
// 透明度相关
|
||||||
const transparencyOpacity = ref(parseFloat(localStorage.getItem('transparency-opacity') || '0.3'))
|
const transparencyOpacity = ref(parseFloat(localStorage.getItem('transparency-opacity') || '0.3'))
|
||||||
const transparencyBlur = ref(parseFloat(localStorage.getItem('transparency-blur') || '10'))
|
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 transparencyLevel = ref(localStorage.getItem('transparency-level') || 'medium')
|
||||||
const isTransparentTheme = computed(() => currentThemeName.value === 'transparent')
|
const isTransparentTheme = computed(() => currentThemeName.value === 'transparent')
|
||||||
const showTransparencyDialog = ref(false)
|
const showTransparencyDialog = ref(false)
|
||||||
@@ -383,6 +385,15 @@ async function saveCustomCSS() {
|
|||||||
function applyTransparencySettings() {
|
function applyTransparencySettings() {
|
||||||
const root = document.documentElement
|
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变量
|
// 设置CSS变量
|
||||||
root.style.setProperty('--transparent-opacity', transparencyOpacity.value.toString())
|
root.style.setProperty('--transparent-opacity', transparencyOpacity.value.toString())
|
||||||
root.style.setProperty('--transparent-opacity-light', (transparencyOpacity.value * 0.67).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', `${transparencyBlur.value}px`)
|
||||||
root.style.setProperty('--transparent-blur-light', `${transparencyBlur.value * 0.6}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-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-opacity', transparencyOpacity.value.toString())
|
||||||
localStorage.setItem('transparency-blur', transparencyBlur.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 = ''
|
transparencyLevel.value = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 背景海报透明度变化处理
|
||||||
|
function onBackgroundPosterOpacityChange() {
|
||||||
|
applyTransparencySettings()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 背景磨砂变化处理
|
||||||
|
function onBackgroundBlurChange() {
|
||||||
|
applyTransparencySettings()
|
||||||
|
}
|
||||||
|
|
||||||
// 重置透明度设置
|
// 重置透明度设置
|
||||||
function resetTransparencySettings() {
|
function resetTransparencySettings() {
|
||||||
transparencyOpacity.value = 0.3
|
transparencyOpacity.value = 0.3
|
||||||
transparencyBlur.value = 10
|
transparencyBlur.value = 10
|
||||||
|
backgroundPosterOpacity.value = 1
|
||||||
|
backgroundBlur.value = 16
|
||||||
transparencyLevel.value = 'medium'
|
transparencyLevel.value = 'medium'
|
||||||
applyTransparencySettings()
|
applyTransparencySettings()
|
||||||
}
|
}
|
||||||
@@ -821,6 +848,38 @@ onUnmounted(() => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</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>
|
<div>
|
||||||
<span class="text-body-2 d-block mb-2">{{ t('common.preset') }}</span>
|
<span class="text-body-2 d-block mb-2">{{ t('common.preset') }}</span>
|
||||||
|
|||||||
@@ -149,6 +149,8 @@ export default {
|
|||||||
transparencyAdjust: 'Transparency Adjustment',
|
transparencyAdjust: 'Transparency Adjustment',
|
||||||
transparencyOpacity: 'Opacity',
|
transparencyOpacity: 'Opacity',
|
||||||
transparencyBlur: 'Blur',
|
transparencyBlur: 'Blur',
|
||||||
|
backgroundPosterOpacity: 'Background Opacity',
|
||||||
|
backgroundBlur: 'Background Frosted Blur',
|
||||||
transparencyReset: 'Reset',
|
transparencyReset: 'Reset',
|
||||||
transparencyLow: 'Low Transparency',
|
transparencyLow: 'Low Transparency',
|
||||||
transparencyMedium: 'Medium Transparency',
|
transparencyMedium: 'Medium Transparency',
|
||||||
|
|||||||
@@ -149,6 +149,8 @@ export default {
|
|||||||
transparencyAdjust: '透明度调整',
|
transparencyAdjust: '透明度调整',
|
||||||
transparencyOpacity: '透明度',
|
transparencyOpacity: '透明度',
|
||||||
transparencyBlur: '模糊度',
|
transparencyBlur: '模糊度',
|
||||||
|
backgroundPosterOpacity: '背景透明度',
|
||||||
|
backgroundBlur: '背景磨砂效果',
|
||||||
transparencyReset: '重置',
|
transparencyReset: '重置',
|
||||||
transparencyLow: '低透明度',
|
transparencyLow: '低透明度',
|
||||||
transparencyMedium: '中等透明度',
|
transparencyMedium: '中等透明度',
|
||||||
|
|||||||
@@ -149,6 +149,8 @@ export default {
|
|||||||
transparencyAdjust: '透明度調整',
|
transparencyAdjust: '透明度調整',
|
||||||
transparencyOpacity: '透明度',
|
transparencyOpacity: '透明度',
|
||||||
transparencyBlur: '模糊度',
|
transparencyBlur: '模糊度',
|
||||||
|
backgroundPosterOpacity: '背景透明度',
|
||||||
|
backgroundBlur: '背景磨砂效果',
|
||||||
transparencyReset: '重置',
|
transparencyReset: '重置',
|
||||||
transparencyLow: '低透明度',
|
transparencyLow: '低透明度',
|
||||||
transparencyMedium: '中等透明度',
|
transparencyMedium: '中等透明度',
|
||||||
|
|||||||
Reference in New Issue
Block a user