mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-02-22 22:21:09 +08:00
Merge pull request #600 from nagisa77/codex/add-switch-for-frosted-glass-effect
Add frosted glass effect toggle
This commit is contained in:
@@ -131,7 +131,7 @@ const goToNewPost = () => {
|
||||
cursor: pointer;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
backdrop-filter: blur(5px);
|
||||
backdrop-filter: var(--blur-5);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
--header-background-color: white;
|
||||
--header-border-color: lightgray;
|
||||
--header-text-color: black;
|
||||
--blur-1: blur(1px);
|
||||
--blur-2: blur(2px);
|
||||
--blur-4: blur(4px);
|
||||
--blur-5: blur(5px);
|
||||
--blur-10: blur(10px);
|
||||
/* 加一个app前缀防止与firefox的userChrome.css中的--menu-background-color冲突 */
|
||||
--app-menu-background-color: white;
|
||||
--background-color: white;
|
||||
@@ -59,6 +64,14 @@
|
||||
--activity-card-background-color: #585858;
|
||||
}
|
||||
|
||||
:root[data-frosted='off'] {
|
||||
--blur-1: none;
|
||||
--blur-2: none;
|
||||
--blur-4: none;
|
||||
--blur-5: none;
|
||||
--blur-10: none;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
@@ -41,8 +41,8 @@ export default {
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
backdrop-filter: blur(2px);
|
||||
-webkit-backdrop-filter: blur(2px);
|
||||
backdrop-filter: var(--blur-2);
|
||||
-webkit-backdrop-filter: var(--blur-2);
|
||||
}
|
||||
.popup-content {
|
||||
position: relative;
|
||||
|
||||
@@ -188,7 +188,7 @@ onMounted(async () => {
|
||||
justify-content: center;
|
||||
height: var(--header-height);
|
||||
background-color: var(--background-color-blur);
|
||||
backdrop-filter: blur(10px);
|
||||
backdrop-filter: var(--blur-10);
|
||||
color: var(--header-text-color);
|
||||
border-bottom: 1px solid var(--header-border-color);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ const goLogin = () => {
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
backdrop-filter: blur(4px);
|
||||
backdrop-filter: var(--blur-4);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,13 @@
|
||||
<BaseInput v-model="introduction" textarea rows="3" placeholder="说些什么..." />
|
||||
<div class="setting-description">自我介绍会出现在你的个人主页,可以简要介绍自己</div>
|
||||
</div>
|
||||
<div class="form-row switch-row">
|
||||
<div class="setting-title">毛玻璃效果</div>
|
||||
<label class="switch">
|
||||
<input type="checkbox" v-model="frosted" />
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="role === 'ADMIN'" class="admin-section">
|
||||
<h3>管理员设置</h3>
|
||||
@@ -65,12 +72,13 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
import AvatarCropper from '~/components/AvatarCropper.vue'
|
||||
import BaseInput from '~/components/BaseInput.vue'
|
||||
import Dropdown from '~/components/Dropdown.vue'
|
||||
import { toast } from '~/main'
|
||||
import { fetchCurrentUser, getToken, setToken } from '~/utils/auth'
|
||||
import { frostedState, setFrosted } from '~/utils/frosted'
|
||||
const config = useRuntimeConfig()
|
||||
const API_BASE_URL = config.public.apiBaseUrl
|
||||
const username = ref('')
|
||||
@@ -87,6 +95,7 @@ const aiFormatLimit = ref(3)
|
||||
const registerMode = ref('DIRECT')
|
||||
const isLoadingPage = ref(false)
|
||||
const isSaving = ref(false)
|
||||
const frosted = ref(true)
|
||||
|
||||
onMounted(async () => {
|
||||
isLoadingPage.value = true
|
||||
@@ -105,6 +114,7 @@ onMounted(async () => {
|
||||
navigateTo('/login', { replace: true })
|
||||
}
|
||||
isLoadingPage.value = false
|
||||
frosted.value = frostedState.enabled
|
||||
})
|
||||
|
||||
const onAvatarChange = (e) => {
|
||||
@@ -118,6 +128,7 @@ const onAvatarChange = (e) => {
|
||||
reader.readAsDataURL(file)
|
||||
}
|
||||
}
|
||||
watch(frosted, (val) => setFrosted(val))
|
||||
const onCropped = ({ file, url }) => {
|
||||
avatarFile.value = file
|
||||
avatar.value = url
|
||||
@@ -300,6 +311,58 @@ const save = async () => {
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.switch-row {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.switch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.switch input {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
transition: 0.2s;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
left: 2px;
|
||||
bottom: 2px;
|
||||
background-color: white;
|
||||
transition: 0.2s;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
input:checked + .slider {
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
|
||||
input:checked + .slider:before {
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
||||
.profile-section {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
6
frontend_nuxt/plugins/frosted.client.ts
Normal file
6
frontend_nuxt/plugins/frosted.client.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { defineNuxtPlugin } from 'nuxt/app'
|
||||
import { initFrosted } from '~/utils/frosted'
|
||||
|
||||
export default defineNuxtPlugin(() => {
|
||||
initFrosted()
|
||||
})
|
||||
26
frontend_nuxt/utils/frosted.js
Normal file
26
frontend_nuxt/utils/frosted.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import { reactive } from 'vue'
|
||||
|
||||
const FROSTED_KEY = 'frosted-glass'
|
||||
|
||||
export const frostedState = reactive({
|
||||
enabled: true,
|
||||
})
|
||||
|
||||
function apply() {
|
||||
if (!import.meta.client) return
|
||||
document.documentElement.dataset.frosted = frostedState.enabled ? 'on' : 'off'
|
||||
}
|
||||
|
||||
export function initFrosted() {
|
||||
if (!import.meta.client) return
|
||||
const saved = localStorage.getItem(FROSTED_KEY)
|
||||
frostedState.enabled = saved !== 'false'
|
||||
apply()
|
||||
}
|
||||
|
||||
export function setFrosted(enabled) {
|
||||
if (!import.meta.client) return
|
||||
frostedState.enabled = enabled
|
||||
localStorage.setItem(FROSTED_KEY, enabled ? 'true' : 'false')
|
||||
apply()
|
||||
}
|
||||
@@ -143,7 +143,7 @@ function fallbackThemeTransition(applyFn) {
|
||||
background-color: ${currentBg};
|
||||
z-index: 9999;
|
||||
pointer-events: none;
|
||||
backdrop-filter: blur(1px);
|
||||
backdrop-filter: var(--blur-1);
|
||||
`
|
||||
document.body.appendChild(transitionElement)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user