pipipi-pikachu 5 år sedan
förälder
incheckning
462f5120af

+ 7 - 7
package-lock.json

@@ -2300,7 +2300,7 @@
         },
         "fork-ts-checker-webpack-plugin-v5": {
           "version": "npm:fork-ts-checker-webpack-plugin@5.2.1",
-          "resolved": "https://registry.npm.taobao.org/fork-ts-checker-webpack-plugin/download/fork-ts-checker-webpack-plugin-5.2.1.tgz",
+          "resolved": "https://registry.npm.taobao.org/fork-ts-checker-webpack-plugin/download/fork-ts-checker-webpack-plugin-5.2.1.tgz?cache=0&sync_timestamp=1607084938170&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffork-ts-checker-webpack-plugin%2Fdownload%2Ffork-ts-checker-webpack-plugin-5.2.1.tgz",
           "integrity": "sha1-eTJthpeXkG+osk4qvPlCH8gFRQ0=",
           "dev": true,
           "optional": true,
@@ -2359,7 +2359,7 @@
         },
         "supports-color": {
           "version": "7.2.0",
-          "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1608033330722&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz",
+          "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-7.2.0.tgz?cache=0&sync_timestamp=1606205010380&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-7.2.0.tgz",
           "integrity": "sha1-G33NyzK4E4gBs+R4umpRyqiWSNo=",
           "dev": true,
           "optional": true,
@@ -3199,6 +3199,11 @@
       "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=",
       "dev": true
     },
+    "animate.css": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npm.taobao.org/animate.css/download/animate.css-4.1.1.tgz",
+      "integrity": "sha1-YU7FqBEx1+TcNipYFD90BqvWgHU="
+    },
     "ansi-colors": {
       "version": "3.2.4",
       "resolved": "https://registry.npm.taobao.org/ansi-colors/download/ansi-colors-3.2.4.tgz",
@@ -15918,11 +15923,6 @@
         }
       }
     },
-    "vue-router": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npm.taobao.org/vue-router/download/vue-router-4.0.1.tgz?cache=0&sync_timestamp=1607347245114&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-router%2Fdownload%2Fvue-router-4.0.1.tgz",
-      "integrity": "sha1-MJJA5QUksefU6C4n8KD6Jf49HXE="
-    },
     "vue-style-loader": {
       "version": "4.1.2",
       "resolved": "https://registry.npm.taobao.org/vue-style-loader/download/vue-style-loader-4.1.2.tgz",

+ 1 - 0
package.json

@@ -9,6 +9,7 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
+    "animate.css": "^4.1.1",
     "ant-design-vue": "^2.0.0-rc.3",
     "clipboard": "^2.0.6",
     "core-js": "^3.6.5",

+ 1 - 1
public/index.html

@@ -15,6 +15,6 @@
     <div id="app"></div>
     <!-- built files will be auto injected -->
     
-    <script src="//at.alicdn.com/t/font_2266335_1ahwvgfxj4ej.js"></script>
+    <script src="//at.alicdn.com/t/font_2266335_di5qehm4txu.js"></script>
   </body>
 </html>

+ 38 - 0
src/configs/animation.ts

@@ -0,0 +1,38 @@
+export const ANIMATIONS = [
+  { name: '渐显', value: 'fadeIn' },
+  { name: '向右进入', value: 'fadeInLeft' },
+  { name: '向左进入', value: 'fadeInRight' },
+  { name: '向上进入', value: 'fadeInUp' },
+  { name: '向下进入', value: 'fadeInDown' },
+  { name: '向右长距进入', value: 'fadeInLeftBig' },
+  { name: '向左长距进入', value: 'fadeInRightBig' },
+  { name: '向上长距进入', value: 'fadeInUpBig' },
+  { name: '向下长距进入', value: 'fadeInDownBig' },
+  { name: '旋转进入', value: 'rotateIn' },
+  { name: '左顺时针旋转', value: 'rotateInDownLeft' },
+  { name: '右逆时针旋转', value: 'rotateInDownRight' },
+  { name: '左逆时针旋转', value: 'rotateInUpLeft' },
+  { name: '右逆时针旋转', value: 'rotateInUpRight' },
+  { name: '弹入', value: 'bounceIn' },
+  { name: '向右弹入', value: 'bounceInLeft' },
+  { name: '向左弹入', value: 'bounceInRight' },
+  { name: '向上弹入', value: 'bounceInUp' },
+  { name: '向下弹入', value: 'bounceInDown' },
+  { name: '光速从右进入', value: 'lightSpeedInRight' },
+  { name: '光速从左进入', value: 'lightSpeedInLeft' },
+  { name: '光速从右退出', value: 'lightSpeedOutRight' },
+  { name: '光速从左退出', value: 'lightSpeedOutLeft' },
+  { name: 'Y轴旋转', value: 'flip' },
+  { name: '中心X轴旋转', value: 'flipInX' },
+  { name: '中心Y轴旋转', value: 'flipInY' },
+  { name: '左长半径旋转', value: 'rollIn' },
+  { name: '由小变大进入', value: 'zoomIn' },
+  { name: '左变大进入', value: 'zoomInLeft' },
+  { name: '右变大进入', value: 'zoomInRight' },
+  { name: '向上变大进入', value: 'zoomInUp' },
+  { name: '向下变大进入', value: 'zoomInDown' },
+  { name: '向右滑动展开', value: 'slideInLeft' },
+  { name: '向左滑动展开', value: 'slideInRight' },
+  { name: '向上滑动展开', value: 'slideInUp' },
+  { name: '向下滑动展开', value: 'slideInDown' },
+]

+ 56 - 0
src/hooks/useAnimation.ts

@@ -0,0 +1,56 @@
+import { computed, Ref, ref } from 'vue'
+import { useStore } from 'vuex'
+import { State } from '@/store'
+import { Slide } from '@/types/slides'
+
+const prefix = 'animate__'
+
+export default (elId: string) => {
+  const animationIndex = ref(-1)
+  const needWaitAnimation = ref(false)
+
+  const store = useStore<State>()
+  const currentSlide: Ref<Slide> = computed(() => store.getters.currentSlide)
+  const animations = computed(() => currentSlide.value.animations || [])
+
+  const elementIndexInAnimation = animations.value.findIndex(animation => animation.elId === elId)
+  if(elementIndexInAnimation !== -1 && elementIndexInAnimation < animationIndex.value) {
+    needWaitAnimation.value = true
+  }
+
+  const runAnimation = () => {
+    const animations = currentSlide.value.animations || []
+    if(!animations.length) return
+    if(animationIndex.value >= animations.length - 1) return
+
+    animationIndex.value += 1
+    const animation = animations[animationIndex.value]
+
+    const elRef = document.querySelector(`#screen-el-${animation.elId}`)
+    if(elRef) {
+      const animationName = `${prefix}${animation.type}`
+      elRef.classList.add(`${prefix}animated`, animationName)
+    }
+  }
+
+  const revokeAnimation = () => {
+    const animations = currentSlide.value.animations || []
+    if(!animations.length) return
+    if(animationIndex.value <= 0) return
+
+    animationIndex.value -= 1
+    const animation = animations[animationIndex.value]
+
+    const elRef = document.querySelector(`#screen-el-${animation.elId}`)
+    if(elRef) {
+      const animationName = `${prefix}${animation.type}`
+      elRef.classList.remove(`${prefix}animated`, animationName)
+    }
+  }
+
+  return {
+    needWaitAnimation,
+    runAnimation,
+    revokeAnimation,
+  }
+}

+ 1 - 0
src/main.ts

@@ -3,6 +3,7 @@ import App from './App.vue'
 import store from './store'
 
 import '@/assets/styles/global.scss'
+import 'animate.css'
 
 import IconFont from '@/components/IconFont.vue'
 import contextmenu from './plugins/contextmenu'

+ 12 - 0
src/mocks/index.ts

@@ -60,6 +60,18 @@ export const slides: Slide[] = [
         src: 'https://img.lessonplan.cn/IMG/Show/ppt/3ab74e91-c34f-499d-9711-166e423d4dd6/62d9adb3-e7a6-4dc4-a352-095cffb49f08/b1be1a2f-f893-47d3-a8a3-eac7d04d395f/1596159381259v2-b2c69096d25ae16bf6ca09e30add3e65_hd.jpg',
       },
     ],
+    animations: [
+      {
+        elId: 'xxx1',
+        type: 'rotateIn',
+        duration: 1000,
+      },
+      {
+        elId: 'xxx2',
+        type: 'zoomInDown',
+        duration: 1000,
+      },
+    ],
   },
   {
     id: 'sajd172',

+ 1 - 1
src/views/Editor/Canvas/Operate/ImageElementOperate.vue

@@ -156,7 +156,7 @@ export default defineComponent({
     }
   }
 
-  &.multi-select:not(.selected) .operate-border-line {
+  &.multi-select:not(.active) .operate-border-line {
     border-color: rgba($color: $themeColor, $alpha: .3);
   }
 

+ 1 - 1
src/views/Editor/Canvas/Operate/TextElementOperate.vue

@@ -118,7 +118,7 @@ export default defineComponent({
     }
   }
 
-  &.multi-select:not(.selected) .operate-border-line {
+  &.multi-select:not(.active) .operate-border-line {
     border-color: rgba($color: $themeColor, $alpha: .3);
   }
 

+ 1 - 0
src/views/Editor/Canvas/index.vue

@@ -31,6 +31,7 @@
         :key="element.id"
         :elementInfo="element"
         :isSelected="activeElementIdList.includes(element.id)"
+        :isActive="handleElementId === element.id"
         :isActiveGroupElement="activeGroupElementId === element.id"
         :isMultiSelect="activeElementIdList.length > 1"
         :rotateElement="rotateElement"

+ 35 - 2
src/views/Editor/EditorHeader/index.vue

@@ -1,6 +1,22 @@
 <template>
   <div class="editor-header">
-    
+    <div class="left">
+      <div class="menu-item">文件</div>
+      <div class="menu-item">编辑</div>
+      <div class="menu-item">设置</div>
+      <div class="menu-item">素材</div>
+      <div class="menu-item">演示</div>
+      <div class="menu-item">帮助</div>
+    </div>
+
+    <div class="right">
+      <div class="menu-item">
+        <IconFont class="icon" type="icon-play-circle" />
+      </div>
+      <div class="menu-item icon">
+        <IconFont class="icon" type="icon-github-fill" />
+      </div>
+    </div>
   </div>
 </template>
 
@@ -16,7 +32,24 @@ export default defineComponent({
 .editor-header {
   background-color: #fff;
   user-select: none;
-  overflow: hidden;
   border-bottom: 1px solid #eee;
+  display: flex;
+  justify-content: space-between;
+  padding: 0 10px;
+}
+.left, .right {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.menu-item {
+  font-size: 13px;
+  color: $themeColor;
+  margin: 0 10px;
+  cursor: pointer;
+
+  .icon {
+    font-size: 20px;
+  }
 }
 </style>