diff --git a/src/views/Editor/Toolbar/ElementAnimationPanel.vue b/src/views/Editor/Toolbar/ElementAnimationPanel.vue index 7efb3691..1564183d 100644 --- a/src/views/Editor/Toolbar/ElementAnimationPanel.vue +++ b/src/views/Editor/Toolbar/ElementAnimationPanel.vue @@ -30,12 +30,24 @@ + +
+
持续时间(毫秒):
+ +
选中画布中的元素添加动画
@@ -57,7 +69,7 @@
【{{element.elType}}】{{element.animationType}}
- + @@ -79,6 +91,8 @@ import useHistorySnapshot from '@/hooks/useHistorySnapshot' import Draggable from 'vuedraggable' +const defaultDuration = 1000 + const animationTypes: { [key: string]: string } = {} for (const type of ANIMATIONS) { for (const animation of type.children) { @@ -128,8 +142,13 @@ export default defineComponent({ if (!handleElement.value) return null const animations = currentSlideAnimations.value || [] const animation = animations.find(item => item.elId === handleElement.value.id) - if (!animation) return null - return animationTypes[animation.type] + return animation || null + }) + + // 当前选中元素的入场动画名称 + const handleElementAnimationName = computed(() => { + if (!handleElementAnimation.value) return null + return animationTypes[handleElementAnimation.value.type] }) // 删除元素入场动画 @@ -154,14 +173,16 @@ export default defineComponent({ } // 执行入场动画预览 - const runAnimation = (elId: string, animationType: string) => { + const runAnimation = (elId: string, animationType: string, duration: number) => { const prefix = 'animate__' const elRef = document.querySelector(`#editable-element-${elId} [class^=editable-element-]`) if (elRef) { const animationName = `${prefix}${animationType}` + document.documentElement.style.setProperty('--animate-duration', `${duration}ms`) elRef.classList.add(`${prefix}animated`, animationName) const handleAnimationEnd = () => { + document.documentElement.style.removeProperty('--animate-duration') elRef.classList.remove(`${prefix}animated`, animationName) } elRef.addEventListener('animationend', handleAnimationEnd, { once: true }) @@ -170,7 +191,9 @@ export default defineComponent({ // 修改元素入场动画,并执行一次预览 const updateElementAnimation = (type: string) => { - const animations = (currentSlideAnimations.value as PPTAnimation[]).map(item => { + if (!currentSlideAnimations.value) return + + const animations = currentSlideAnimations.value.map(item => { if (item.elId === handleElement.value.id) return { ...item, type } return item }) @@ -178,12 +201,28 @@ export default defineComponent({ animationPoolVisible.value = false addHistorySnapshot() - runAnimation(handleElement.value.id, type) + const animationItem = currentSlideAnimations.value.find(item => item.elId === handleElement.value.id) + const duration = animationItem?.duration || defaultDuration + + runAnimation(handleElement.value.id, type, duration) + } + + // 修改元素入场动画持续时间 + const updateElementAnimationDuration = (duration: number) => { + if (!currentSlideAnimations.value) return + if (duration < 100 || duration > 5000) return + + const animations = currentSlideAnimations.value.map(item => { + if (item.elId === handleElement.value.id) return { ...item, duration } + return item + }) + store.commit(MutationTypes.UPDATE_SLIDE, { animations }) + addHistorySnapshot() } // 添加元素入场动画,并执行一次预览 const addAnimation = (type: string) => { - if (handleElementAnimation.value) { + if (handleElementAnimationName.value) { updateElementAnimation(type) return } @@ -191,13 +230,13 @@ export default defineComponent({ animations.push({ elId: handleElement.value.id, type, - duration: 1000, + duration: defaultDuration, }) store.commit(MutationTypes.UPDATE_SLIDE, { animations }) animationPoolVisible.value = false addHistorySnapshot() - runAnimation(handleElement.value.id, type) + runAnimation(handleElement.value.id, type, defaultDuration) } return { @@ -207,10 +246,12 @@ export default defineComponent({ animationSequence, hoverPreviewAnimation, handleElementAnimation, + handleElementAnimationName, addAnimation, deleteAnimation, handleDragEnd, runAnimation, + updateElementAnimationDuration, } }, }) @@ -220,6 +261,12 @@ export default defineComponent({ .element-animation-btn { width: 100%; } +.duration { + width: 100%; + display: flex; + align-items: center; + margin: 10px 0; +} .tip { text-align: center; font-style: italic; diff --git a/src/views/Screen/index.vue b/src/views/Screen/index.vue index b36de7cc..6e608ce3 100644 --- a/src/views/Screen/index.vue +++ b/src/views/Screen/index.vue @@ -148,9 +148,11 @@ export default defineComponent({ const elRef = document.querySelector(`#screen-element-${animation.elId} [class^=base-element-]`) if (elRef) { const animationName = `${prefix}${animation.type}` + document.documentElement.style.setProperty('--animate-duration', `${animation.duration}ms`) elRef.classList.add(`${prefix}animated`, animationName) const handleAnimationEnd = () => { + document.documentElement.style.removeProperty('--animate-duration') elRef.classList.remove(`${prefix}animated`, animationName) } elRef.addEventListener('animationend', handleAnimationEnd, { once: true })