From a67370c48d1361f81a304411a365ad44b10c7d27 Mon Sep 17 00:00:00 2001 From: pipipi-pikachu Date: Fri, 13 May 2022 15:12:51 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E5=85=83?= =?UTF-8?q?=E7=B4=A0=E5=8A=A8=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/configs/animation.ts | 40 +- src/main.ts | 3 - src/store/slides.ts | 47 +- src/types/slides.ts | 13 +- src/utils/emitter.ts | 4 - src/views/Editor/Canvas/Operate/index.vue | 41 +- .../Editor/Toolbar/ElementAnimationPanel.vue | 443 ++++++++---------- src/views/Screen/ScreenElement.vue | 55 +-- src/views/Screen/ScreenSlide.vue | 2 +- src/views/Screen/ScreenSlideList.vue | 4 +- src/views/Screen/hooks/useExecPlay.ts | 151 +++--- .../element/LineElement/BaseLineElement.vue | 6 +- 12 files changed, 374 insertions(+), 435 deletions(-) diff --git a/src/configs/animation.ts b/src/configs/animation.ts index 478b6f86..8e2144d5 100644 --- a/src/configs/animation.ts +++ b/src/configs/animation.ts @@ -1,4 +1,8 @@ -export const ANIMATIONS = [ +export const ANIMATION_DEFAULT_DURATION = 1000 +export const ANIMATION_DEFAULT_TRIGGER = 'click' +export const ANIMATION_CLASS_PREFIX = 'animate__' + +export const ENTER_ANIMATIONS = [ { type: 'bounce', name: '弹跳', @@ -9,7 +13,6 @@ export const ANIMATIONS = [ { name: '向上弹入', value: 'bounceInUp' }, { name: '向下弹入', value: 'bounceInDown' }, ], - hiddenElement: [] }, { type: 'fade', @@ -29,19 +32,17 @@ export const ANIMATIONS = [ { name: '从左下浮入', value: 'fadeInBottomLeft' }, { name: '从右下浮入', value: 'fadeInBottomRight' }, ], - hiddenElement: [] }, { type: 'rotate', name: '旋转', children: [ { name: '旋转进入', value: 'rotateIn' }, - { name: '绕左下旋转进入', value: 'rotateInDownLeft' }, - { name: '绕右下旋转进入', value: 'rotateInDownRight' }, - { name: '绕左上旋转进入', value: 'rotateInUpLeft' }, - { name: '绕右上旋转进入', value: 'rotateInUpRight' }, + { name: '绕左下进入', value: 'rotateInDownLeft' }, + { name: '绕右下进入', value: 'rotateInDownRight' }, + { name: '绕左上进入', value: 'rotateInUpLeft' }, + { name: '绕右上进入', value: 'rotateInUpRight' }, ], - hiddenElement: [] }, { type: 'zoom', @@ -53,7 +54,6 @@ export const ANIMATIONS = [ { name: '从右放大进入', value: 'zoomInRight' }, { name: '向上放大进入', value: 'zoomInUp' }, ], - hiddenElement: [] }, { type: 'slide', @@ -64,7 +64,6 @@ export const ANIMATIONS = [ { name: '从左滑入', value: 'slideInRight' }, { name: '向上滑入', value: 'slideInUp' }, ], - hiddenElement: [] }, { type: 'flip', @@ -73,7 +72,6 @@ export const ANIMATIONS = [ { name: 'X轴翻转进入', value: 'flipInX' }, { name: 'Y轴翻转进入', value: 'flipInY' }, ], - hiddenElement: [] }, { type: 'back', @@ -84,7 +82,6 @@ export const ANIMATIONS = [ { name: '从右放大滑入', value: 'backInRight' }, { name: '向上放大滑入', value: 'backInUp' }, ], - hiddenElement: [] }, { type: 'lightSpeed', @@ -93,11 +90,10 @@ export const ANIMATIONS = [ { name: '从右飞入', value: 'lightSpeedInRight' }, { name: '从左飞入', value: 'lightSpeedInLeft' }, ], - hiddenElement: [] }, ] -export const ANIMATIONS_EXITS = [ +export const EXIT_ANIMATIONS = [ { type: 'bounce', name: '弹跳', @@ -108,7 +104,6 @@ export const ANIMATIONS_EXITS = [ { name: '向上弹出', value: 'bounceOutUp' }, { name: '向下弹出', value: 'bounceOutDown' }, ], - hiddenElement: [] }, { type: 'fade', @@ -128,19 +123,17 @@ export const ANIMATIONS_EXITS = [ { name: '从左下浮出', value: 'fadeOutBottomLeft' }, { name: '从右下浮出', value: 'fadeOutBottomRight' }, ], - hiddenElement: [] }, { type: 'rotate', name: '旋转', children: [ { name: '旋转退出', value: 'rotateOut' }, - { name: '绕左下旋转退出', value: 'rotateOutDownLeft' }, - { name: '绕右下旋转退出', value: 'rotateOutDownRight' }, - { name: '绕左上旋转退出', value: 'rotateOutUpLeft' }, - { name: '绕右上旋转退出', value: 'rotateOutUpRight' }, + { name: '绕左下退出', value: 'rotateOutDownLeft' }, + { name: '绕右下退出', value: 'rotateOutDownRight' }, + { name: '绕左上退出', value: 'rotateOutUpLeft' }, + { name: '绕右上退出', value: 'rotateOutUpRight' }, ], - hiddenElement: [] }, { type: 'zoom', @@ -152,7 +145,6 @@ export const ANIMATIONS_EXITS = [ { name: '从右缩小退出', value: 'zoomOutRight' }, { name: '向上缩小退出', value: 'zoomOutUp' }, ], - hiddenElement: [] }, { type: 'slide', @@ -163,7 +155,6 @@ export const ANIMATIONS_EXITS = [ { name: '从右滑出', value: 'slideOutRight' }, { name: '向上滑出', value: 'slideOutUp' }, ], - hiddenElement: [] }, { type: 'flip', @@ -172,7 +163,6 @@ export const ANIMATIONS_EXITS = [ { name: 'X轴翻转退出', value: 'flipOutX' }, { name: 'Y轴翻转退出', value: 'flipOutY' }, ], - hiddenElement: [] }, { type: 'back', @@ -183,7 +173,6 @@ export const ANIMATIONS_EXITS = [ { name: '从右缩小滑出', value: 'backOutRight' }, { name: '向上缩小滑出', value: 'backOutUp' }, ], - hiddenElement: [] }, { type: 'lightSpeed', @@ -192,6 +181,5 @@ export const ANIMATIONS_EXITS = [ { name: '从右飞出', value: 'lightSpeedOutRight' }, { name: '从左飞出', value: 'lightSpeedOutLeft' }, ], - hiddenElement: [] }, ] \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index f9efe20d..39ccfe5a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -33,7 +33,6 @@ import { Drawer, Spin, Alert, - Tabs, } from 'ant-design-vue' const app = createApp(App) @@ -63,8 +62,6 @@ app.component('Checkbox', Checkbox) app.component('Drawer', Drawer) app.component('Spin', Spin) app.component('Alert', Alert) -app.component('Tabs', Tabs) -app.component('TabPane', Tabs.TabPane) app.use(Icon) app.use(Component) diff --git a/src/store/slides.ts b/src/store/slides.ts index cd207ebc..72e71eb2 100644 --- a/src/store/slides.ts +++ b/src/store/slides.ts @@ -1,7 +1,7 @@ import { defineStore } from 'pinia' import tinycolor from 'tinycolor2' import { omit } from 'lodash' -import { Slide, SlideTheme, PPTElement } from '@/types/slides' +import { Slide, SlideTheme, PPTElement, PPTAnimation } from '@/types/slides' import { slides } from '@/mocks/slides' import { theme } from '@/mocks/theme' import { layouts } from '@/mocks/layout' @@ -16,6 +16,11 @@ interface UpdateElementData { props: Partial; } +interface FormatedAnimation { + animations: PPTAnimation[]; + autoNext: boolean; +} + export interface SlidesState { theme: SlideTheme; slides: Slide[]; @@ -38,13 +43,43 @@ export const useSlidesStore = defineStore('slides', { currentSlideAnimations(state) { const currentSlide = state.slides[state.slideIndex] - if (!currentSlide) return null - const animations = currentSlide.animations - if (!animations) return null - + if (!currentSlide?.animations) return [] + const els = currentSlide.elements const elIds = els.map(el => el.id) - return animations.filter(animation => elIds.includes(animation.elId)) + return currentSlide.animations.filter(animation => elIds.includes(animation.elId)) + }, + + // 格式化的当前页动画 + // 将触发条件为“与上一动画同时”的项目向上合并到序列中的同一位置 + // 为触发条件为“上一动画之后”项目的上一项添加自动向下执行标记 + formatedAnimations(state) { + const currentSlide = state.slides[state.slideIndex] + if (!currentSlide?.animations) return [] + + const els = currentSlide.elements + const elIds = els.map(el => el.id) + const animations = currentSlide.animations.filter(animation => elIds.includes(animation.elId)) + + const formatedAnimations: FormatedAnimation[] = [] + for (const animation of animations) { + if (animation.trigger === 'click') { + formatedAnimations.push({ animations: [animation], autoNext: false }) + } + if (animation.trigger === 'meantime') { + const last = formatedAnimations[formatedAnimations.length - 1] || { animations: [], autoNext: false } + last.animations = last.animations.filter(item => item.elId !== animation.elId) + last.animations.push(animation) + formatedAnimations[formatedAnimations.length - 1] = last + } + if (animation.trigger === 'auto') { + const last = formatedAnimations[formatedAnimations.length - 1] || { animations: [], autoNext: false } + last.autoNext = true + formatedAnimations[formatedAnimations.length - 1] = last + formatedAnimations.push({ animations: [animation], autoNext: false }) + } + } + return formatedAnimations }, layouts(state) { diff --git a/src/types/slides.ts b/src/types/slides.ts index 3c11e3ab..d08f7c67 100644 --- a/src/types/slides.ts +++ b/src/types/slides.ts @@ -572,24 +572,21 @@ export type PPTElement = PPTTextElement | PPTImageElement | PPTShapeElement | PP * * elId: 元素ID * - * type: 动画类型 - * * effect: 动画效果 * + * type: 动画类型(入场、退场) + * * duration: 动画持续时间 * - * delay: 动画延迟时间 - * - * implement: 动画启动方式(0->单击、1->与上一个一起、2->在上一个之后) + * trigger: 动画触发方式(click - 单击时、meantime - 与上一动画同时、auto - 上一动画之后) */ export interface PPTAnimation { id: string; elId: string; - type: string; effect: string; + type: 'in' | 'out'; duration: number; - delay: number; - implement: number; + trigger: 'click' | 'meantime' | 'auto'; } /** diff --git a/src/utils/emitter.ts b/src/utils/emitter.ts index c787f0a6..7403cce2 100644 --- a/src/utils/emitter.ts +++ b/src/utils/emitter.ts @@ -4,8 +4,6 @@ export const enum EmitterEvents { RICH_TEXT_COMMAND = 'RICH_TEXT_COMMAND', OPEN_CHART_DATA_EDITOR = 'OPEN_CHART_DATA_EDITOR', OPEN_LATEX_EDITOR = 'OPEN_LATEX_EDITOR', - RUN_ANIMATION = 'RUN_ANIMATION', - END_RUN_ANIMATION = 'END_RUN_ANIMATION', } export interface RichTextAction { @@ -22,8 +20,6 @@ type Events = { [EmitterEvents.RICH_TEXT_COMMAND]: RichTextCommand; [EmitterEvents.OPEN_CHART_DATA_EDITOR]: void; [EmitterEvents.OPEN_LATEX_EDITOR]: void; - [EmitterEvents.RUN_ANIMATION]: void; - [EmitterEvents.END_RUN_ANIMATION]: void; } const emitter: Emitter = mitt() diff --git a/src/views/Editor/Canvas/Operate/index.vue b/src/views/Editor/Canvas/Operate/index.vue index c4aae713..265c3d76 100644 --- a/src/views/Editor/Canvas/Operate/index.vue +++ b/src/views/Editor/Canvas/Operate/index.vue @@ -21,9 +21,9 @@
- {{elementIndexInAnimation + 1}} +
{{index + 1}}
{ const elementTypeMap = { @@ -113,9 +113,13 @@ export default defineComponent({ return elementTypeMap[props.elementInfo.type] || null }) - const elementIndexInAnimation = computed(() => { - const animations = currentSlide.value.animations || [] - return animations.findIndex(animation => animation.elId === props.elementInfo.id) + const elementIndexListInAnimation = computed(() => { + const indexList = [] + for (let i = 0; i < formatedAnimations.value.length; i++) { + const elIds = formatedAnimations.value[i].animations.map(item => item.elId) + if (elIds.includes(props.elementInfo.id)) indexList.push(i) + } + return indexList }) const rotate = computed(() => 'rotate' in props.elementInfo ? props.elementInfo.rotate : 0) @@ -125,7 +129,7 @@ export default defineComponent({ currentOperateComponent, canvasScale, toolbarState, - elementIndexInAnimation, + elementIndexListInAnimation, rotate, height, } @@ -148,13 +152,20 @@ export default defineComponent({ top: 0; left: -24px; font-size: 12px; - width: 18px; - height: 18px; - background-color: #fff; - color: $themeColor; - border: 1px solid $themeColor; - display: flex; - justify-content: center; - align-items: center; + + .index-item { + width: 18px; + height: 18px; + background-color: #fff; + color: $themeColor; + border: 1px solid $themeColor; + display: flex; + justify-content: center; + align-items: center; + + & + .index-item { + margin-top: 5px; + } + } } \ No newline at end of file diff --git a/src/views/Editor/Toolbar/ElementAnimationPanel.vue b/src/views/Editor/Toolbar/ElementAnimationPanel.vue index f64da1a6..76bc6fd9 100644 --- a/src/views/Editor/Toolbar/ElementAnimationPanel.vue +++ b/src/views/Editor/Toolbar/ElementAnimationPanel.vue @@ -7,69 +7,40 @@ @visibleChange="visible => handlePopoverVisibleChange(visible)" >