From 6285188fc6f46c97d6cc162d57746bc37140a12e Mon Sep 17 00:00:00 2001 From: pipipi-pikachu Date: Sun, 30 Jul 2023 10:42:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=A1=A5=E5=85=85=E6=94=BE=E6=98=A0?= =?UTF-8?q?=E5=88=87=E6=8D=A2=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 | 22 ++++ src/types/slides.ts | 2 +- .../Editor/Toolbar/SlideAnimationPanel.vue | 117 +++++++++++++++--- src/views/Screen/ScreenSlideList.vue | 84 ++++++++++++- 4 files changed, 207 insertions(+), 18 deletions(-) diff --git a/src/configs/animation.ts b/src/configs/animation.ts index 3bbe54be..858a376b 100644 --- a/src/configs/animation.ts +++ b/src/configs/animation.ts @@ -1,3 +1,5 @@ +import type { TurningMode } from '@/types/slides' + export const ANIMATION_DEFAULT_DURATION = 1000 export const ANIMATION_DEFAULT_TRIGGER = 'click' export const ANIMATION_CLASS_PREFIX = 'animate__' @@ -209,4 +211,24 @@ export const ATTENTION_ANIMATIONS = [ { name: '心跳(快)', value: 'heartBeat' }, ], }, +] + +interface SlideAnimation { + label: string + value: TurningMode +} + +export const SLIDE_ANIMATIONS: SlideAnimation[] = [ + { label: '无', value: 'no' }, + { label: '随机', value: 'random' }, + { label: '左右推移', value: 'slideX' }, + { label: '上下推移', value: 'slideY' }, + { label: '左右推移(3D)', value: 'slideX3D' }, + { label: '上下推移(3D)', value: 'slideY3D' }, + { label: '淡入淡出', value: 'fade' }, + { label: '旋转', value: 'rotate' }, + { label: '上下展开', value: 'scaleY' }, + { label: '左右展开', value: 'scaleX' }, + { label: '放大', value: 'scale' }, + { label: '缩小', value: 'scaleReverse' }, ] \ No newline at end of file diff --git a/src/types/slides.ts b/src/types/slides.ts index c3b14a02..52922885 100644 --- a/src/types/slides.ts +++ b/src/types/slides.ts @@ -658,7 +658,7 @@ export interface SlideBackground { } -export type TurningMode = 'no' | 'fade' | 'slideX' | 'slideY' +export type TurningMode = 'no' | 'fade' | 'slideX' | 'slideY' | 'random' | 'slideX3D' | 'slideY3D' | 'rotate' | 'scaleY' | 'scaleX' | 'scale' | 'scaleReverse' /** * 幻灯片页面 diff --git a/src/views/Editor/Toolbar/SlideAnimationPanel.vue b/src/views/Editor/Toolbar/SlideAnimationPanel.vue index d3002ab6..4454a9c9 100644 --- a/src/views/Editor/Toolbar/SlideAnimationPanel.vue +++ b/src/views/Editor/Toolbar/SlideAnimationPanel.vue @@ -21,26 +21,17 @@ import { computed } from 'vue' import { storeToRefs } from 'pinia' import { useSlidesStore } from '@/store' import type { TurningMode } from '@/types/slides' +import { SLIDE_ANIMATIONS } from '@/configs/animation' import useHistorySnapshot from '@/hooks/useHistorySnapshot' -import { Button } from 'ant-design-vue' - -interface Animations { - label: string - value: TurningMode -} +import { Button, message } from 'ant-design-vue' const slidesStore = useSlidesStore() const { slides, currentSlide } = storeToRefs(slidesStore) const currentTurningMode = computed(() => currentSlide.value.turningMode || 'slideY') -const animations: Animations[] = [ - { label: '无', value: 'no' }, - { label: '淡入淡出', value: 'fade' }, - { label: '左右推移', value: 'slideX' }, - { label: '上下推移', value: 'slideY' }, -] +const animations = SLIDE_ANIMATIONS const { addHistorySnapshot } = useHistorySnapshot() @@ -60,6 +51,7 @@ const applyAllSlide = () => { } }) slidesStore.setSlides(newSlides) + message.success('已应用到全部') addHistorySnapshot() } @@ -72,14 +64,14 @@ const applyAllSlide = () => { } .animation-item { width: 50%; - height: 115px; + height: 100px; border: solid 1px #d6d6d6; box-sizing: border-box; display: flex; flex-direction: column; justify-content: space-between; align-items: center; - padding: 25px 0 15px 0; + padding: 20px 0 15px 0; position: relative; cursor: pointer; @@ -103,13 +95,16 @@ const applyAllSlide = () => { overflow: hidden; @mixin elAnimation($animationType) { - content: ''; + content: 'Slide'; width: 100%; height: 100%; position: absolute; left: 0; top: 0; background-color: #d9dadb; + display: flex; + justify-content: center; + align-items: center; animation: $animationType $transitionDelaySlow linear; } @@ -128,6 +123,42 @@ const applyAllSlide = () => { @include elAnimation(slideY); } } + &.slideX3D:hover { + &::after { + @include elAnimation(slideX3D); + } + } + &.slideY3D:hover { + &::after { + @include elAnimation(slideY3D); + } + } + &.rotate:hover { + &::after { + transform-origin: 0 0; + @include elAnimation(rotate); + } + } + &.scaleY:hover { + &::after { + @include elAnimation(scaleY); + } + } + &.scaleX:hover { + &::after { + @include elAnimation(scaleX); + } + } + &.scale:hover { + &::after { + @include elAnimation(scale); + } + } + &.scaleReverse:hover { + &::after { + @include elAnimation(scaleReverse); + } + } } .animation-text { font-size: 12px; @@ -159,4 +190,60 @@ const applyAllSlide = () => { transform: translateY(0); } } +@keyframes slideX3D { + 0% { + transform: translateX(100%) scale(.5); + } + 100% { + transform: translateX(0); + } +} +@keyframes slideY3D { + 0% { + transform: translateY(100%) scale(.5); + } + 100% { + transform: translateY(0); + } +} +@keyframes rotate { + 0% { + transform: rotate(-90deg); + } + 100% { + transform: rotate(0); + } +} +@keyframes scaleY { + 0% { + transform: scaleY(.1); + } + 100% { + transform: scaleY(1); + } +} +@keyframes scaleX { + 0% { + transform: scaleX(.1); + } + 100% { + transform: scaleY(1); + } +} +@keyframes scale { + 0% { + transform: scale(.25); + } + 100% { + transform: scale(1); + } +} +@keyframes scaleReverse { + 0% { + transform: scale(2); + } + 100% { + transform: scale(1); + } +} \ No newline at end of file diff --git a/src/views/Screen/ScreenSlideList.vue b/src/views/Screen/ScreenSlideList.vue index 05c28abd..c3369ccc 100644 --- a/src/views/Screen/ScreenSlideList.vue +++ b/src/views/Screen/ScreenSlideList.vue @@ -3,7 +3,7 @@
{ + return slides.value.map(slide => { + let turningMode = slide.turningMode + if (!turningMode) turningMode = 'slideY' + if (turningMode === 'random') { + const turningModeKeys = SLIDE_ANIMATIONS.filter(item => !['random', 'no'].includes(item.value)).map(item => item.value) + turningMode = turningModeKeys[Math.floor(Math.random() * turningModeKeys.length)] + } + return { + ...slide, + turningMode, + } + }) +}) + const scale = computed(() => props.slideWidth / VIEWPORT_SIZE) provide(injectKeySlideScale, scale) @@ -116,6 +132,70 @@ provide(injectKeySlideScale, scale) transform: translateY(100%); } } + &.turning-mode-slideX3D { + transition: transform .5s; + &.before { + transform: translateX(-100%) scale(.5); + } + &.after { + transform: translateX(100%) scale(.5); + } + } + &.turning-mode-slideY3D { + transition: transform .5s; + &.before { + transform: translateY(-100%) scale(.5); + } + &.after { + transform: translateY(100%) scale(.5); + } + } + &.turning-mode-rotate { + transition: transform .5s; + transform-origin: 0 0; + &.before { + transform: rotate(90deg); + } + &.after { + transform: rotate(-90deg); + } + } + &.turning-mode-scaleY { + transition: transform .5s; + &.before { + transform: scaleY(.1); + } + &.after { + transform: scaleY(.1); + } + } + &.turning-mode-scaleX { + transition: transform .5s; + &.before { + transform: scaleX(.1); + } + &.after { + transform: scaleX(.1); + } + } + &.turning-mode-scale { + transition: transform .5s; + &.before { + transform: scale(.25); + } + &.after { + transform: scale(.25); + } + } + &.turning-mode-scaleReverse { + transition: transform .5s; + &.before { + transform: scale(2); + } + &.after { + transform: scale(2); + } + } } .slide-content { background-color: #fff;