背景特效切换美化
This commit is contained in:
+76
-7
@@ -112,14 +112,83 @@ function switchView(view: 'editor' | 'manager' | 'presets') {
|
|||||||
currentView.value = view
|
currentView.value = view
|
||||||
}
|
}
|
||||||
|
|
||||||
function cycleBackground() {
|
function cycleBackground(event?: MouseEvent) {
|
||||||
const currentIndex = bgModes.indexOf(currentBgMode.value)
|
const isAppearanceTransition = 'startViewTransition' in document
|
||||||
const nextIndex = (currentIndex + 1) % bgModes.length
|
&& !window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
||||||
const nextMode = bgModes[nextIndex]
|
&& event instanceof MouseEvent
|
||||||
if (nextMode) {
|
|
||||||
currentBgMode.value = nextMode
|
const updateState = () => {
|
||||||
localStorage.setItem('bg.mode', currentBgMode.value)
|
const currentIndex = bgModes.indexOf(currentBgMode.value)
|
||||||
|
const nextIndex = (currentIndex + 1) % bgModes.length
|
||||||
|
const nextMode = bgModes[nextIndex]
|
||||||
|
if (nextMode) {
|
||||||
|
currentBgMode.value = nextMode
|
||||||
|
localStorage.setItem('bg.mode', currentBgMode.value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isAppearanceTransition) {
|
||||||
|
updateState()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const x = event.clientX
|
||||||
|
const y = event.clientY
|
||||||
|
|
||||||
|
const transition = document.startViewTransition(async () => {
|
||||||
|
updateState()
|
||||||
|
await nextTick()
|
||||||
|
})
|
||||||
|
|
||||||
|
transition.ready.then(() => {
|
||||||
|
const effects = ['circle', 'vertical', 'horizontal', 'diamond']
|
||||||
|
const effect = effects[Math.floor(Math.random() * effects.length)]
|
||||||
|
|
||||||
|
let clipPath: string[] = []
|
||||||
|
|
||||||
|
if (effect === 'circle') {
|
||||||
|
const endRadius = Math.hypot(
|
||||||
|
Math.max(x, innerWidth - x),
|
||||||
|
Math.max(y, innerHeight - y)
|
||||||
|
)
|
||||||
|
clipPath = [
|
||||||
|
`circle(0px at ${x}px ${y}px)`,
|
||||||
|
`circle(${endRadius}px at ${x}px ${y}px)`
|
||||||
|
]
|
||||||
|
} else if (effect === 'vertical') {
|
||||||
|
clipPath = [
|
||||||
|
'inset(0 0 100% 0)',
|
||||||
|
'inset(0 0 0 0)'
|
||||||
|
]
|
||||||
|
} else if (effect === 'horizontal') {
|
||||||
|
clipPath = [
|
||||||
|
'inset(0 100% 0 0)',
|
||||||
|
'inset(0 0 0 0)'
|
||||||
|
]
|
||||||
|
} else if (effect === 'diamond') {
|
||||||
|
const endRadius = Math.hypot(
|
||||||
|
Math.max(x, innerWidth - x),
|
||||||
|
Math.max(y, innerHeight - y)
|
||||||
|
) * 1.5 // Multiply to ensure coverage for diamond shape
|
||||||
|
|
||||||
|
clipPath = [
|
||||||
|
`polygon(${x}px ${y}px, ${x}px ${y}px, ${x}px ${y}px, ${x}px ${y}px)`,
|
||||||
|
`polygon(${x}px ${y - endRadius}px, ${x + endRadius}px ${y}px, ${x}px ${y + endRadius}px, ${x - endRadius}px ${y}px)`
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
document.documentElement.animate(
|
||||||
|
{
|
||||||
|
clipPath: clipPath,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
duration: 1500,
|
||||||
|
easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
|
||||||
|
pseudoElement: '::view-transition-new(root)',
|
||||||
|
fill: 'forwards',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const bgModeLabel = computed(() => {
|
const bgModeLabel = computed(() => {
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
window.addEventListener('mousemove', onMouseMove, { passive: true })
|
window.addEventListener('mousemove', onMouseMove, { passive: true })
|
||||||
document.addEventListener('visibilitychange', onVisibilityChange)
|
document.addEventListener('visibilitychange', onVisibilityChange)
|
||||||
|
draw() // Initial draw to ensure no flicker
|
||||||
raf = requestAnimationFrame(loop)
|
raf = requestAnimationFrame(loop)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -185,6 +185,7 @@ onMounted(() => {
|
|||||||
initMesh()
|
initMesh()
|
||||||
window.addEventListener('resize', onResize)
|
window.addEventListener('resize', onResize)
|
||||||
window.addEventListener('mousemove', onMouseMove)
|
window.addEventListener('mousemove', onMouseMove)
|
||||||
|
draw() // Initial draw
|
||||||
raf = requestAnimationFrame(loop)
|
raf = requestAnimationFrame(loop)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ onMounted(() => {
|
|||||||
resize()
|
resize()
|
||||||
window.addEventListener('resize', resize)
|
window.addEventListener('resize', resize)
|
||||||
window.addEventListener('mousemove', onMouseMove)
|
window.addEventListener('mousemove', onMouseMove)
|
||||||
|
draw() // Initial draw
|
||||||
raf = requestAnimationFrame(loop)
|
raf = requestAnimationFrame(loop)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user