公告栏修正
This commit is contained in:
1 parent
87d6561779
commit
517e92a00b
9 files changed
+37
-11
No files matched your search
@@ -14,11 +14,13 @@ const { t, locale } = useI18n()
|
||||
const config = ref<AnnouncementConfig | null>(null)
|
||||
const visible = ref(false)
|
||||
const animationRun = ref(0)
|
||||
const centerX = ref<number | null>(null)
|
||||
const CACHE_KEY = 'SpineParticle.Announcement.v1'
|
||||
let memoryCache: AnnouncementCache | null = null
|
||||
let refreshTimer: ReturnType<typeof setInterval> | null = null
|
||||
let staticHideTimer: ReturnType<typeof setTimeout> | null = null
|
||||
let refreshing = false
|
||||
let layoutObserver: ResizeObserver | null = null
|
||||
|
||||
const text = computed(() => {
|
||||
if (!config.value?.enabled) return ''
|
||||
@@ -65,6 +67,19 @@ function showAnnouncement(next: AnnouncementConfig) {
|
||||
function hideAnnouncement() {
|
||||
visible.value = false
|
||||
}
|
||||
function syncHorizontalPosition() {
|
||||
const home = document.querySelector<HTMLElement>('.stage-home-btn')
|
||||
const panel = document.querySelector<HTMLElement>('.parameter-panel')
|
||||
if (!home) {
|
||||
centerX.value = window.innerWidth / 2
|
||||
return
|
||||
}
|
||||
const homeRect = home.getBoundingClientRect()
|
||||
const panelRect = panel?.getBoundingClientRect()
|
||||
const panelOnRight = panelRect && panelRect.width > 0 && panelRect.left > homeRect.left
|
||||
const rightEdge = panelOnRight ? panelRect.left : window.innerWidth
|
||||
centerX.value = (homeRect.right + rightEdge) / 2
|
||||
}
|
||||
async function refreshAnnouncement(initial = false) {
|
||||
if (refreshing) return
|
||||
refreshing = true
|
||||
@@ -96,10 +111,20 @@ async function refreshAnnouncement(initial = false) {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
syncHorizontalPosition()
|
||||
layoutObserver = new ResizeObserver(syncHorizontalPosition)
|
||||
const home = document.querySelector<HTMLElement>('.stage-home-btn')
|
||||
const panel = document.querySelector<HTMLElement>('.parameter-panel')
|
||||
if (home) layoutObserver.observe(home)
|
||||
if (panel) layoutObserver.observe(panel)
|
||||
window.addEventListener('resize', syncHorizontalPosition)
|
||||
void refreshAnnouncement(true)
|
||||
refreshTimer = setInterval(() => { void refreshAnnouncement() }, ANNOUNCEMENT_REFRESH_MS)
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
layoutObserver?.disconnect()
|
||||
layoutObserver = null
|
||||
window.removeEventListener('resize', syncHorizontalPosition)
|
||||
if (refreshTimer) clearInterval(refreshTimer)
|
||||
if (staticHideTimer) clearTimeout(staticHideTimer)
|
||||
})
|
||||
@@ -111,7 +136,7 @@ onBeforeUnmount(() => {
|
||||
v-if="visible && text"
|
||||
class="announcement-bar"
|
||||
:aria-label="text"
|
||||
:style="{ '--announcement-duration': `${duration}s` }"
|
||||
:style="{ '--announcement-duration': `${duration}s`, left: centerX == null ? '50%' : `${centerX}px` }"
|
||||
tabindex="0"
|
||||
role="status"
|
||||
>
|
||||
@@ -138,12 +163,13 @@ onBeforeUnmount(() => {
|
||||
|
||||
<style scoped>
|
||||
.announcement-bar {
|
||||
position: absolute; top: 10px; left: 50%; z-index: 3;
|
||||
position: fixed; top: 10px; z-index: 3;
|
||||
width: min(60vw, 1100px); height: 27.2px; box-sizing: border-box;
|
||||
transform: translateX(-50%);
|
||||
overflow: hidden; border: 1px solid rgba(255, 189, 190, .34); border-radius: 999px;
|
||||
background:
|
||||
linear-gradient(90deg, rgba(120, 48, 55, .12), rgba(145, 57, 64, .72) 10%, rgba(145, 57, 64, .72) 90%, rgba(120, 48, 55, .12));
|
||||
color: #ffe4e5; transform: translateX(-50%);
|
||||
color: #ffe4e5;
|
||||
}
|
||||
.announcement-viewport {
|
||||
position: absolute; inset: 0 26px 0 0; overflow: hidden;
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<AnnouncementBar />
|
||||
<TransferProgressOverlay />
|
||||
</template>
|
||||
|
||||
@@ -77,6 +78,7 @@ import Stage from './Stage.vue'
|
||||
import ParticlePanel from './ParticlePanel.vue'
|
||||
import Timeline from './Timeline.vue'
|
||||
import TransferProgressOverlay from './TransferProgressOverlay.vue'
|
||||
import AnnouncementBar from './AnnouncementBar.vue'
|
||||
import { transferProgress } from '../editor/transferProgress'
|
||||
import { provideParticlePanel } from './particle-panel/particlePanelContext'
|
||||
import { PARTICLE_SECTIONS } from './particle-panel/particleSections'
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div class="stage-wrap">
|
||||
<div ref="holder" class="stage-holder" :class="{ grid: store.settings.showGrid }" tabindex="0" @wheel.prevent="onWheelEvent" @pointerdown="onPanDown" @dblclick.prevent="onStageDoubleClick"></div>
|
||||
<AnnouncementBar />
|
||||
<img
|
||||
class="stage-watermark"
|
||||
:class="{ 'watermark-left-panel': !store.settings.parameterPanelOnRight }"
|
||||
@@ -64,7 +63,6 @@ import { useEditorShortcuts } from '../editor/useEditorShortcuts'
|
||||
import { PROJECT_SAVE_EVENT } from '../editor/projectLibrary'
|
||||
import { translate } from '../i18n'
|
||||
import HelpDialog from './HelpDialog.vue'
|
||||
import AnnouncementBar from './AnnouncementBar.vue'
|
||||
import StageToolbar from './StageToolbar.vue'
|
||||
import StageSettingsPanel from './StageSettingsPanel.vue'
|
||||
import { onWheel, panView, type StageContext } from './stage/viewControls'
|
||||
|
||||
Reference in new issue
Block a user