From 29fdabbb0ef5c1b8ebafd7a47364a67c86b63fe2 Mon Sep 17 00:00:00 2001 From: AdingApkgg Date: Fri, 26 Dec 2025 23:01:22 +0800 Subject: [PATCH] Refactor ImageViewer component to remove custom animation functions and simplify transition handling - Eliminated the `useAnime` composable and its associated animation functions from ImageViewer.vue, opting for a more straightforward approach to transitions. - Updated the onEnter function to focus solely on sound effects during transitions, enhancing clarity and maintainability of the code. --- src/components/ImageViewer.vue | 22 +---- src/composables/useAnime.ts | 145 --------------------------------- 2 files changed, 2 insertions(+), 165 deletions(-) delete mode 100644 src/composables/useAnime.ts diff --git a/src/components/ImageViewer.vue b/src/components/ImageViewer.vue index fdf66e1..1c645e0 100644 --- a/src/components/ImageViewer.vue +++ b/src/components/ImageViewer.vue @@ -5,7 +5,6 @@ */ import { ref, computed, watch, onMounted, onUnmounted } from 'vue' -import { animate } from '@/composables/useAnime' import { X, ChevronLeft, @@ -68,26 +67,9 @@ const imageStyle = computed(() => { } }) -// 动画函数 -function onEnter(el: Element, done: () => void) { +// 进入动画时播放音效 +function onEnter() { playTransitionUp() - animate(el as HTMLElement, { - opacity: [0, 1], - scale: [0.95, 1], - duration: 250, - ease: 'outCubic', - complete: done, - }) -} - -function onLeave(el: Element, done: () => void) { - animate(el as HTMLElement, { - opacity: [1, 0], - scale: [1, 0.95], - duration: 200, - ease: 'inCubic', - complete: done, - }) } // 监听图片切换 diff --git a/src/composables/useAnime.ts b/src/composables/useAnime.ts deleted file mode 100644 index 95a3acf..0000000 --- a/src/composables/useAnime.ts +++ /dev/null @@ -1,145 +0,0 @@ -/** - * 动画系统 - 使用原生 Web Animations API - * 轻量级替代 anime.js - */ - -// 缓动函数映射 -const easingMap: Record = { - 'outQuad': 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', - 'inQuad': 'cubic-bezier(0.55, 0.085, 0.68, 0.53)', - 'outCubic': 'cubic-bezier(0.33, 1, 0.68, 1)', - 'inCubic': 'cubic-bezier(0.32, 0, 0.67, 0)', - 'outQuart': 'cubic-bezier(0.25, 1, 0.5, 1)', - 'inQuart': 'cubic-bezier(0.5, 0, 0.75, 0)', - 'outBack': 'cubic-bezier(0.34, 1.56, 0.64, 1)', - 'inBack': 'cubic-bezier(0.36, 0, 0.66, -0.56)', - 'inOutQuad': 'cubic-bezier(0.45, 0, 0.55, 1)', - 'linear': 'linear', - 'ease': 'ease', - 'easeIn': 'ease-in', - 'easeOut': 'ease-out', - 'easeInOut': 'ease-in-out', -} - -interface AnimationParams { - opacity?: number[] - scale?: number[] | number - translateX?: number[] | number - translateY?: number[] | number - rotate?: number[] - duration?: number - ease?: string - delay?: number - complete?: () => void -} - -/** - * 将动画参数转换为 Web Animations API 格式 - */ -function paramsToKeyframes(params: AnimationParams): Keyframe[] { - const fromFrame: Keyframe = {} - const toFrame: Keyframe = {} - - // 构建 transform 字符串 - let fromTransform = '' - let toTransform = '' - - if (params.opacity) { - fromFrame.opacity = params.opacity[0] - toFrame.opacity = params.opacity[1] - } - - if (params.scale) { - if (Array.isArray(params.scale)) { - fromTransform += `scale(${params.scale[0]}) ` - toTransform += `scale(${params.scale[1]}) ` - } - } - - if (params.translateX) { - if (Array.isArray(params.translateX)) { - fromTransform += `translateX(${params.translateX[0]}px) ` - toTransform += `translateX(${params.translateX[1]}px) ` - } - } - - if (params.translateY) { - if (Array.isArray(params.translateY)) { - fromTransform += `translateY(${params.translateY[0]}px) ` - toTransform += `translateY(${params.translateY[1]}px) ` - } - } - - if (params.rotate) { - if (Array.isArray(params.rotate) && params.rotate.length >= 2) { - fromTransform += `rotate(${params.rotate[0]}deg) ` - toTransform += `rotate(${params.rotate[params.rotate.length - 1]}deg) ` - } - } - - if (fromTransform) { - fromFrame.transform = fromTransform.trim() - toFrame.transform = toTransform.trim() - } - - return [fromFrame, toFrame] -} - -/** - * 执行动画 - 使用 Web Animations API - */ -export function animate( - target: HTMLElement | string | NodeList | HTMLElement[], - animation: AnimationParams, - options?: Partial, -): Promise { - const params = { ...animation, ...options } - - // 获取目标元素 - let elements: HTMLElement[] = [] - if (typeof target === 'string') { - elements = Array.from(document.querySelectorAll(target)) as HTMLElement[] - } else if (target instanceof NodeList) { - elements = Array.from(target) as HTMLElement[] - } else if (Array.isArray(target)) { - elements = target - } else if (target instanceof HTMLElement) { - elements = [target] - } - - if (elements.length === 0) { - return Promise.resolve() - } - - const keyframes = paramsToKeyframes(params) - const duration = params.duration || 300 - const easing = easingMap[params.ease || 'outQuad'] || params.ease || 'ease-out' - const delay = params.delay || 0 - - const animations = elements.map(el => { - const anim = el.animate(keyframes, { - duration, - easing, - delay, - fill: 'forwards', - }) - return anim.finished - }) - - return Promise.all(animations).then(() => { - // 将最终状态应用到元素 - elements.forEach(el => { - const lastFrame = keyframes[keyframes.length - 1] - if (lastFrame.opacity !== undefined) { - el.style.opacity = String(lastFrame.opacity) - } - if (lastFrame.transform) { - el.style.transform = lastFrame.transform - } - }) - - if (params.complete) { - params.complete() - } - }) -}