From eccd6b2cd918e93a2a391044e5ccc262bfe7de27 Mon Sep 17 00:00:00 2001 From: LemonNeko Date: Thu, 27 Mar 2025 21:07:05 +0800 Subject: [PATCH] feat(stage-web): new settings animation (#100) * feat(stage-web): new settings animation * fix: optimize, issues * fix: allow disable icon animation * fix: typo * fix: disable icon animation when disable all animation --- apps/stage-web/locales/en.yml | 3 + apps/stage-web/locales/zh-CN.yml | 3 + apps/stage-web/src/App.vue | 1 + .../src/components/IconAnimation.vue | 76 +++++++++ .../src/components/Settings/CheckBar.vue | 8 +- .../src/composables/useIconAnimation.ts | 29 ++++ .../src/pages/settings/appearance/index.vue | 32 +++- apps/stage-web/src/pages/settings/index.vue | 157 ++++++++++++------ .../src/pages/settings/models/index.vue | 23 ++- .../src/pages/settings/modules/index.vue | 25 ++- .../src/pages/settings/providers/index.vue | 25 ++- packages/stage-ui/src/stores/settings.ts | 2 + .../src/components/StageTransitionGroup.vue | 16 +- 13 files changed, 341 insertions(+), 59 deletions(-) create mode 100644 apps/stage-web/src/components/IconAnimation.vue create mode 100644 apps/stage-web/src/composables/useIconAnimation.ts diff --git a/apps/stage-web/locales/en.yml b/apps/stage-web/locales/en.yml index 9a323c880..06fcf447d 100644 --- a/apps/stage-web/locales/en.yml +++ b/apps/stage-web/locales/en.yml @@ -46,6 +46,9 @@ settings: animations: stage-transitions: title: Disable Stage Transitions + use-page-specific-transitions: + title: Use Page Specific Transitions + description: Some pages will have their own transitions, this will override the stage transitions language: chinese: 简体中文 english: English diff --git a/apps/stage-web/locales/zh-CN.yml b/apps/stage-web/locales/zh-CN.yml index 49cab6647..068405eb2 100644 --- a/apps/stage-web/locales/zh-CN.yml +++ b/apps/stage-web/locales/zh-CN.yml @@ -34,6 +34,9 @@ settings: animations: stage-transitions: title: 是否开启舞台动画 + use-page-specific-transitions: + title: 是否使用页面特定过场动画 + description: 某些页面会有自己的过场动画,这将覆盖舞台过场动画 language: chinese: 简体中文 english: English diff --git a/apps/stage-web/src/App.vue b/apps/stage-web/src/App.vue index 566866cc8..2bcfc6a4d 100644 --- a/apps/stage-web/src/App.vue +++ b/apps/stage-web/src/App.vue @@ -54,6 +54,7 @@ watch(settings.themeColorsHueDynamic, () => { :colors="colors" :z-index="100" :disable-transitions="settings.disableTransitions.value" + :use-page-specific-transitions="settings.usePageSpecificTransitions.value" > diff --git a/apps/stage-web/src/components/IconAnimation.vue b/apps/stage-web/src/components/IconAnimation.vue new file mode 100644 index 000000000..aa0adc179 --- /dev/null +++ b/apps/stage-web/src/components/IconAnimation.vue @@ -0,0 +1,76 @@ + + + diff --git a/apps/stage-web/src/components/Settings/CheckBar.vue b/apps/stage-web/src/components/Settings/CheckBar.vue index f203cc4dc..d92fc96b9 100644 --- a/apps/stage-web/src/components/Settings/CheckBar.vue +++ b/apps/stage-web/src/components/Settings/CheckBar.vue @@ -3,6 +3,7 @@ defineProps<{ text: string iconOn: string iconOff: string + description?: string }>() const model = defineModel() @@ -14,7 +15,12 @@ const model = defineModel() hover="bg-neutral-200 dark:bg-neutral-700" > - {{ $t(text) }} +
+ {{ $t(text) }} +
+ {{ $t(description) }} +
+
diff --git a/apps/stage-web/src/composables/useIconAnimation.ts b/apps/stage-web/src/composables/useIconAnimation.ts new file mode 100644 index 000000000..d890ee3c5 --- /dev/null +++ b/apps/stage-web/src/composables/useIconAnimation.ts @@ -0,0 +1,29 @@ +import { useSettings } from '@proj-airi/stage-ui/stores' +import { computed, onMounted, onUnmounted, ref } from 'vue' + +export function useIconAnimation(icon: string) { + const iconAnimationStarted = ref(false) + const showAnimationComponent = ref(false) + const animationIcon = ref(icon) + + const settingsStore = useSettings() + const showIconAnimation = computed(() => showAnimationComponent.value && !settingsStore.disableTransitions && settingsStore.usePageSpecificTransitions) + + onMounted(() => { + showAnimationComponent.value = true + requestAnimationFrame(() => { + iconAnimationStarted.value = true + }) + }) + + onUnmounted(() => { + iconAnimationStarted.value = false + showAnimationComponent.value = false + }) + + return { + iconAnimationStarted, + showIconAnimation, + animationIcon, + } +} diff --git a/apps/stage-web/src/pages/settings/appearance/index.vue b/apps/stage-web/src/pages/settings/appearance/index.vue index db60dcc22..56f3d4ec3 100644 --- a/apps/stage-web/src/pages/settings/appearance/index.vue +++ b/apps/stage-web/src/pages/settings/appearance/index.vue @@ -1,16 +1,26 @@ @@ -202,4 +231,5 @@ const dark = useDark() meta: stageTransition: name: slide + pageSpecificAvailable: true diff --git a/apps/stage-web/src/pages/settings/index.vue b/apps/stage-web/src/pages/settings/index.vue index c9f8ed2f2..b606d88e6 100644 --- a/apps/stage-web/src/pages/settings/index.vue +++ b/apps/stage-web/src/pages/settings/index.vue @@ -1,8 +1,96 @@ diff --git a/apps/stage-web/src/pages/settings/models/index.vue b/apps/stage-web/src/pages/settings/models/index.vue index ab8e7eb21..f43798b71 100644 --- a/apps/stage-web/src/pages/settings/models/index.vue +++ b/apps/stage-web/src/pages/settings/models/index.vue @@ -1,6 +1,7 @@ @@ -77,4 +97,5 @@ async function extractColorsFromModel() { meta: stageTransition: name: slide + pageSpecificAvailable: true diff --git a/apps/stage-web/src/pages/settings/modules/index.vue b/apps/stage-web/src/pages/settings/modules/index.vue index 165a939d2..15cb32ca9 100644 --- a/apps/stage-web/src/pages/settings/modules/index.vue +++ b/apps/stage-web/src/pages/settings/modules/index.vue @@ -1,11 +1,16 @@ @@ -151,4 +173,5 @@ const modulesList = computed(() => [ meta: stageTransition: name: slide + pageSpecificAvailable: true diff --git a/apps/stage-web/src/pages/settings/providers/index.vue b/apps/stage-web/src/pages/settings/providers/index.vue index 7ed841d8f..ddbf0c4e2 100644 --- a/apps/stage-web/src/pages/settings/providers/index.vue +++ b/apps/stage-web/src/pages/settings/providers/index.vue @@ -1,14 +1,23 @@ @@ -59,4 +79,5 @@ const { allProvidersMetadata } = storeToRefs(providersStore) meta: stageTransition: name: slide + pageSpecificAvailable: true diff --git a/packages/stage-ui/src/stores/settings.ts b/packages/stage-ui/src/stores/settings.ts index 69e69dbb8..50db805f5 100644 --- a/packages/stage-ui/src/stores/settings.ts +++ b/packages/stage-ui/src/stores/settings.ts @@ -29,6 +29,7 @@ export const useSettings = defineStore('settings', () => { const live2dMotionMap = useLocalStorage>('settings/live2d/motion-map', {}) const disableTransitions = useLocalStorage('settings/disable-transitions', true) + const usePageSpecificTransitions = useLocalStorage('settings/use-page-specific-transitions', true) const themeColorsHue = useLocalStorage('settings/theme/colors/hue', DEFAULT_THEME_COLORS_HUE) const themeColorsHueDynamic = useLocalStorage('settings/theme/colors/hue-dynamic', false) @@ -87,6 +88,7 @@ export const useSettings = defineStore('settings', () => { live2dMotionMap, loadingLive2dModel, disableTransitions, + usePageSpecificTransitions, language, stageView, themeColorsHue, diff --git a/packages/ui-transitions/src/components/StageTransitionGroup.vue b/packages/ui-transitions/src/components/StageTransitionGroup.vue index f4abecc7c..e31792c66 100644 --- a/packages/ui-transitions/src/components/StageTransitionGroup.vue +++ b/packages/ui-transitions/src/components/StageTransitionGroup.vue @@ -17,6 +17,7 @@ const props = defineProps<{ colors?: string[] zIndex?: number disableTransitions?: boolean + usePageSpecificTransitions?: boolean }>() interface StageTransitionCommonParams { @@ -27,6 +28,7 @@ interface StageTransitionCommonParams { direction?: 'top' | 'bottom' | 'left' | 'right' colors?: string[] zIndex?: number + pageSpecificAvailable?: boolean } type TransitionComponent = @@ -247,12 +249,21 @@ function triggerTransition(params: StageTransitionCommonParams, next: Navigation } router.beforeEach((to, _from, next) => { + if (props.disableTransitions) { + next() + return + } + if (typeof to.meta.stageTransition !== 'object') { next() return } const stageTransition = to.meta.stageTransition as StageTransitionCommonParams + if (props.usePageSpecificTransitions && stageTransition.pageSpecificAvailable) { + next() + return + } if (typeof props.primaryColor !== 'undefined') { stageTransition.primaryColor = props.primaryColor } @@ -269,11 +280,6 @@ router.beforeEach((to, _from, next) => { stageTransition.zIndex = props.zIndex } - if (props.disableTransitions) { - next() - return - } - triggerTransition(stageTransition, next) })