pipipi-pikachu 5 年之前
父節點
當前提交
9c233b0ce8

+ 4 - 4
src/configs/animation.ts

@@ -34,10 +34,10 @@ export const ANIMATIONS = [
     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' },
     ],
   },
   {

+ 9 - 0
src/configs/element.ts

@@ -1,5 +1,14 @@
 const DEFAULT_COLOR = '#41464b'
 
+export const ELEMENT_TYPE = {
+  'text': '文本',
+  'image': '图片',
+  'shape': '形状',
+  'line': '线条',
+  'chart': '图表',
+  'table': '表格',
+}
+
 export const DEFAULT_TEXT = {
   content: '请输入内容',
 }

+ 2 - 2
src/views/Editor/CanvasTool/index.vue

@@ -11,13 +11,13 @@
         <PictureOutlined class="handler-item" />
       </FileInput>
       <Popover trigger="click" v-model:visible="isOpenShapePool">
-        <template v-slot:content>
+        <template #content>
           <ShapePool @select="shape => drawShape(shape)" />
         </template>
         <StarOutlined class="handler-item" />
       </Popover>
       <Popover trigger="click" v-model:visible="isOpenlinePool">
-        <template v-slot:content>
+        <template #content>
           <LinePool @select="line => drawLine(line)" />
         </template>
         <LineOutlined class="handler-item" />

+ 4 - 4
src/views/Editor/Thumbnails/index.vue

@@ -5,7 +5,7 @@
     v-click-outside="() => setThumbnailsFocus(false)"
   >
     <div class="add-slide" @click="createSlide()">+ 添加幻灯片</div>
-    <draggable 
+    <Draggable 
       class="thumbnail-list"
       :modelValue="slides"
       :animation="300"
@@ -27,25 +27,25 @@
           </div>
         </div>
       </template>
-    </draggable>
+    </Draggable>
   </div>
 </template>
 
 <script lang="ts">
 import { computed, defineComponent } from 'vue'
-import draggable from 'vuedraggable'
 import { useStore } from 'vuex'
 import { State, MutationTypes } from '@/store'
 import { fillDigit } from '@/utils/common'
 import { ContextmenuItem } from '@/components/Contextmenu/types'
 import useSlideHandler from '@/hooks/useSlideHandler'
 
+import Draggable from 'vuedraggable'
 import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'
 
 export default defineComponent({
   name: 'thumbnails',
   components: {
-    draggable,
+    Draggable,
     ThumbnailSlide,
   },
   setup() {

+ 191 - 3
src/views/Editor/Toolbar/ElementAnimationPanel.vue

@@ -1,13 +1,201 @@
 <template>
   <div class="element-animation-panel">
-    element-animation-panel
+    <div class="element-animation">
+      <Popover trigger="click">
+        <template #content>
+          <div class="animation-pool">
+            <div class="pool-type" v-for="type in animations" :key="type.name">
+              <div class="type-title">{{type.name}}:</div>
+              <div class="pool-item" v-for="item in type.children" :key="item.name">
+                <div 
+                  :class="[
+                    'box',
+                    'animate__animated',
+                    hoverPreviewAnimation === item.value && `animate__${item.value}`,
+                  ]"
+                  @mouseover="hoverPreviewAnimation = item.value"
+                ></div>
+                <div class="label">{{item.name}}</div>
+              </div>
+            </div>
+          </div>
+        </template>
+        <Button class="element-animation-btn">旋转进入</Button>
+      </Popover>
+    </div>
+    
+    <Divider />
+
+    <Draggable 
+      class="animation-sequence"
+      :modelValue="animationSequence"
+      :animation="300"
+      :scroll="true"
+      :scrollSensitivity="50"
+      itemKey="id"
+    >
+      <template #item="{ element, index }">
+        <div class="sequence-item">
+          <div class="index">{{index + 1}}</div>
+          <div class="el-type">{{element.elType}}</div>
+          <div class="animation-type">{{element.animationType}}</div>
+          <div class="handler">
+            <PlayCircleOutlined class="handler-btn" />
+            <DeleteOutlined class="handler-btn" />
+          </div>
+        </div>
+      </template>
+    </Draggable>
   </div>
 </template>
 
 <script lang="ts">
-import { defineComponent } from 'vue'
+import { computed, defineComponent, ref, Ref } from 'vue'
+import { useStore } from 'vuex'
+import { State } from '@/store'
+import { PPTAnimation, Slide } from '@/types/slides'
+import { ANIMATIONS } from '@/configs/animation'
+import { ELEMENT_TYPE } from '@/configs/element'
+
+import Draggable from 'vuedraggable'
+import { Button, Divider, Popover } from 'ant-design-vue'
+import {
+  PlayCircleOutlined,
+  DeleteOutlined,
+} from '@ant-design/icons-vue'
+
+const animationTypes: { [key: string]: string } = {}
+for(const type of ANIMATIONS) {
+  for(const animation of type.children) {
+    animationTypes[animation.value] = animation.name
+  }
+}
 
 export default defineComponent({
   name: 'element-animation-panel',
+  components: {
+    Draggable,
+    Button,
+    Divider,
+    PlayCircleOutlined,
+    DeleteOutlined,
+    Popover,
+  },
+  setup() {
+    const store = useStore<State>()
+    const currentSlideAnimations: Ref<PPTAnimation[] | null> = computed(() => store.getters.currentSlideAnimations)
+    const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
+
+    const hoverPreviewAnimation = ref('')
+
+    const animations = ANIMATIONS
+
+    const animationSequence = computed(() => {
+      if(!currentSlideAnimations.value) return []
+      const animationSequence = []
+      for(const animation of currentSlideAnimations.value) {
+        const el = currentSlide.value.elements.find(el => el.id === animation.elId)
+        if(!el) continue
+        const elType = ELEMENT_TYPE[el.type]
+        const animationType = animationTypes[animation.type]
+
+        animationSequence.push({
+          ...animation,
+          elType,
+          animationType,
+        })
+      }
+      return animationSequence
+    })
+
+    return {
+      animations,
+      animationSequence,
+      hoverPreviewAnimation,
+    }
+  },
 })
-</script>
+</script>
+
+<style lang="scss" scoped>
+.element-animation-btn {
+  width: 100%;
+}
+.animation-pool {
+  width: 400px;
+  height: 500px;
+  overflow-y: auto;
+  overflow-x: hidden;
+  font-size: 12px;
+}
+.pool-type {
+  @include grid-layout-wrapper();
+}
+.type-title {
+  width: 100%;
+  font-size: 13px;
+  margin-bottom: 10px;
+  border-left: 4px solid #aaa;
+  background-color: #eee;
+  padding-left: 10px;
+}
+.pool-item {
+  @include grid-layout-item(4, 24%);
+
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+  margin-bottom: 10px;
+  cursor: pointer;
+
+  .box {
+    width: 30px;
+    height: 30px;
+    background-color: #eee;
+    margin-bottom: 5px;
+  }
+  .label {
+    text-align: center;
+  }
+}
+
+.sequence-item {
+  height: 32px;
+  display: flex;
+  align-items: center;
+  border: 1px solid #eee;
+  padding: 6px;
+  border-radius: $borderRadius;
+  margin-bottom: 5px;
+
+  &:hover {
+    .animation-type {
+      display: none;
+    }
+    .handler {
+      display: block;
+    }
+  }
+
+  .index {
+    flex: 1;
+  }
+  .el-type {
+    flex: 2;
+  }
+  .animation-type {
+    flex: 3;
+    text-align: right;
+  }
+  .handler {
+    display: none;
+    flex: 3;
+    text-align: right;
+  }
+  .handler-btn {
+    margin-left: 10px;
+    cursor: pointer;
+  }
+}
+</style>

+ 6 - 0
src/views/Editor/Toolbar/ElementStylePanel/TextStylePanel.vue

@@ -50,6 +50,7 @@
     <div class="row">
       <div style="flex: 2;">行间距:</div>
       <Select style="flex: 3;">
+        <template #suffixIcon><ColumnHeightOutlined /></template>
         <SelectOption value="jack">Jack</SelectOption>
         <SelectOption value="lucy">Lucy</SelectOption>
         <SelectOption value="disabled">Disabled</SelectOption>
@@ -59,6 +60,7 @@
     <div class="row">
       <div style="flex: 2;">字间距:</div>
       <Select style="flex: 3;">
+        <template #suffixIcon><ColumnWidthOutlined /></template>
         <SelectOption value="jack">Jack</SelectOption>
         <SelectOption value="lucy">Lucy</SelectOption>
         <SelectOption value="disabled">Disabled</SelectOption>
@@ -96,6 +98,8 @@ import {
   AlignRightOutlined,
   OrderedListOutlined,
   UnorderedListOutlined,
+  ColumnHeightOutlined,
+  ColumnWidthOutlined,
 } from '@ant-design/icons-vue'
 
 export default defineComponent({
@@ -120,6 +124,8 @@ export default defineComponent({
     AlignRightOutlined,
     OrderedListOutlined,
     UnorderedListOutlined,
+    ColumnHeightOutlined,
+    ColumnWidthOutlined,
   },
 })
 </script>

+ 1 - 1
src/views/Editor/Toolbar/SlideStylePanel.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="slide-style-panel">
     <Popover trigger="click">
-      <template v-slot:content>
+      <template #content>
         <ColorPicker v-model="color" />
       </template>
       <button>Hover me</button>