pipipi-pikachu 5 jaren geleden
bovenliggende
commit
1b83e915cd
2 gewijzigde bestanden met toevoegingen van 211 en 3 verwijderingen
  1. 1 0
      src/types/slides.ts
  2. 210 3
      src/views/Editor/Toolbar/SlideAnimationPanel.vue

+ 1 - 0
src/types/slides.ts

@@ -161,4 +161,5 @@ export interface Slide {
   elements: PPTElement[];
   background?: SlideBackground;
   animations?: PPTAnimation[];
+  turningMode?: 'no' | 'fade' | 'slideX' | 'slideY';
 }

+ 210 - 3
src/views/Editor/Toolbar/SlideAnimationPanel.vue

@@ -1,13 +1,220 @@
 <template>
   <div class="slide-animation-panel">
-    slide-animation-panel
+    <div class="animation-pool">
+      <div 
+        class="animation-item" 
+        :class="{ 'active': currentTurningMode === item.value }" 
+        v-for="item in animations" 
+        :key="item.label"
+        @click="updateTurningMode(item.value)"
+      >
+        <div :class="['animation-block', item.value]"></div>
+        <div class="animation-text">{{item.label}}</div>
+      </div>
+    </div>
+    <Button style="width: 100%;" @click="applyAllSlide()">应用到全部</Button>
   </div>
 </template>
 
 <script lang="ts">
-import { defineComponent } from 'vue'
+import { computed, defineComponent, Ref } from 'vue'
+import { useStore } from 'vuex'
+import { MutationTypes, State } from '@/store'
+import { Slide } from '@/types/slides'
+import useHistorySnapshot from '@/hooks/useHistorySnapshot'
 
 export default defineComponent({
   name: 'slide-animation-panel',
+  setup() {
+    const store = useStore<State>()
+    const slides = computed(() => store.state.slides)
+    const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
+
+    const currentTurningMode = computed(() => currentSlide.value.turningMode || 'slideY')
+
+    const animations = [
+      { label: '无', value: 'no' },
+      { label: '淡入淡出', value: 'fade' },
+      { label: '左右推移', value: 'slideX' },
+      { label: '上下推移', value: 'slideY' },
+    ]
+
+    const { addHistorySnapshot } = useHistorySnapshot()
+
+    const updateTurningMode = (mode: string) => {
+      if(mode === currentTurningMode.value) return
+      store.commit(MutationTypes.UPDATE_SLIDE, { turningMode: mode })
+      addHistorySnapshot()
+    }
+
+    const applyAllSlide = () => {
+      const newSlides = slides.value.map(slide => {
+        return {
+          ...slide,
+          turningMode: currentSlide.value.turningMode,
+        }
+      })
+      store.commit(MutationTypes.SET_SLIDES, newSlides)
+      addHistorySnapshot()
+    }
+
+    return {
+      currentTurningMode,
+      animations,
+      updateTurningMode,
+      applyAllSlide,
+    }
+  },
 })
-</script>
+</script>
+
+<style lang="scss" scoped>
+.animation-pool {
+  display: flex;
+  flex-wrap: wrap;
+  margin-bottom: 10px;
+}
+.animation-item {
+  width: 50%;
+  height: 115px;
+  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;
+  position: relative;
+  cursor: pointer;
+
+  &.active {
+    border-color: $themeColor;
+    z-index: 1;
+  }
+
+  &:nth-child(2n) {
+    margin-left: -1px;
+  }
+  &:nth-child(n+3) {
+    margin-top: -1px;
+  }
+}
+.animation-block {
+  width: 64px;
+  height: 36px;
+  background: #666;
+  position: relative;
+  overflow: hidden;
+
+  &:hover {
+    animation: no 2s infinite linear;
+  }
+  &.fade:hover {
+    animation: fade 2s infinite linear;
+  }
+  &.slideX:hover {
+    &::after {
+      width: 192px;
+      height: 100%;
+      content: '';
+      position: absolute;
+      left: 0;
+      top: 0;
+      background-image: linear-gradient(to right, #666 0%, #666 64px, #d9dadb 64px, #d9dadb 128px, #666 128px, #666 192px);
+      animation: slideX 3s infinite linear;
+    }
+  }
+  &.slideY:hover {
+    &::after {
+      width: 100%;
+      height: 108px;
+      content: '';
+      position: absolute;
+      left: 0;
+      top: 0;
+      background-image: linear-gradient(to bottom, #666 0%, #666 36px, #d9dadb 36px, #d9dadb 72px, #666 72px, #666 108px);
+      animation: slideY 3s infinite linear;
+    }
+  }
+}
+.animation-text {
+  font-size: 12px;
+  color: #333;
+  text-align: center;
+}
+
+@keyframes no {
+  0% {
+    background-color: #666;
+  }
+  50% {
+    background-color: #666;
+  }
+  51% {
+    background-color: #d9dadb;
+  }
+  100% {
+    background-color: #d9dadb;
+  }
+}
+@keyframes fade {
+  0% {
+    background-color: #d9dadb;
+  }
+  50% {
+    background-color: #666;
+  }
+  51% {
+    background-color: #d9dadb;
+  }
+  100% {
+    background-color: #666;
+  }
+}
+@keyframes slideX {
+  0% {
+    left: 0;
+  }
+  17% {
+    left: -64px;
+  }
+  33% {
+    left: -64px;
+  }
+  50% {
+    left: -128px;
+  }
+  67% {
+    left: -128px;
+  }
+  84% {
+    left: -192px;
+  }
+  100% {
+    left: -192px;
+  }
+}
+@keyframes slideY {
+  0% {
+    top: 0;
+  }
+  17% {
+    top: -36px;
+  }
+  33% {
+    top: -36px;
+  }
+  50% {
+    top: -72px;
+  }
+  67% {
+    top: -72px;
+  }
+  84% {
+    top: -108px;
+  }
+  100% {
+    top: -108px;
+  }
+}
+</style>