Ver código fonte

feat: video player

chenlei 8 meses atrás
pai
commit
fd232f4c7b

BIN
packages/base/images/第四单元-伟大复兴的奋进.jpg


Diferenças do arquivo suprimidas por serem muito extensas
+ 43 - 42
packages/base/index.js


BIN
packages/base/videos/start-m.mp4


BIN
packages/base/videos/start.mp4


BIN
packages/mobile/src/assets/images/cover.png


BIN
packages/mobile/src/assets/images/tab_liulan-min.png


+ 31 - 2
packages/mobile/src/components/VideoCover.vue

@@ -1,9 +1,10 @@
 <template>
   <div class="video-cover">
     <video
+      ref="video"
+      preload
+      poster="@/assets/images/cover.png"
       :src="StartVideo"
-      :autoplay="true"
-      :muted="true"
       x5-playsinline="true"
       playsinline="true"
       webkit-playsinline="true"
@@ -12,17 +13,30 @@
       @ended="goToScene"
     />
 
+    <div v-if="showBtn" class="video-cover__start" @click="play">
+      请您开启展览
+    </div>
+
     <div class="video-cover__btn" @click="goToScene">跳过</div>
   </div>
 </template>
 
 <script setup>
+import { ref } from "vue";
 import { SCENE_URL } from "@syjy/base/utils";
 import StartVideo from "@syjy/base/videos/start-m.mp4";
 
+const video = ref(null);
+const showBtn = ref(true);
+
 const goToScene = () => {
   location.href = SCENE_URL;
 };
+
+const play = () => {
+  showBtn.value = false;
+  video.value.play();
+};
 </script>
 
 <style lang="scss" scoped>
@@ -39,6 +53,21 @@ const goToScene = () => {
     height: 100%;
     object-fit: cover;
   }
+  &__start {
+    position: absolute;
+    left: 50%;
+    bottom: 198px;
+    width: 367px;
+    height: 100px;
+    line-height: 100px;
+    text-align: center;
+    color: white;
+    font-size: 37px;
+    cursor: pointer;
+    transform: translateX(-50%);
+    background: url("@/assets/images/tab_liulan-min.png") no-repeat center /
+      contain;
+  }
   &__btn {
     position: absolute;
     right: 33px;

+ 1 - 0
packages/pc/package.json

@@ -13,6 +13,7 @@
     "element-plus": "^2.6.0",
     "vue": "^3.5.13",
     "vue-router": "^4.0.3",
+    "vue3-video-play": "^1.3.2",
     "vuex": "^4.0.0"
   },
   "devDependencies": {

BIN
packages/pc/src/assets/images/tab_liulan-min.png


+ 30 - 2
packages/pc/src/components/VideoCover/index.vue

@@ -1,9 +1,9 @@
 <template>
   <div class="video-cover">
     <video
+      ref="video"
+      preload
       :src="StartVideo"
-      :autoplay="true"
-      :muted="true"
       x5-playsinline="true"
       playsinline="true"
       webkit-playsinline="true"
@@ -12,17 +12,30 @@
       @ended="goToScene"
     />
 
+    <div v-if="showBtn" class="video-cover__start" @click="play">
+      请您开启展览
+    </div>
+
     <div class="video-cover__btn" @click="goToScene">跳过</div>
   </div>
 </template>
 
 <script setup>
+import { ref } from "vue";
 import { SCENE_URL } from "@syjy/base/utils";
 import StartVideo from "@syjy/base/videos/start.mp4";
 
+const video = ref(null);
+const showBtn = ref(true);
+
 const goToScene = () => {
   location.href = SCENE_URL;
 };
+
+const play = () => {
+  showBtn.value = false;
+  video.value.play();
+};
 </script>
 
 <style lang="scss" scoped>
@@ -39,6 +52,21 @@ const goToScene = () => {
     height: 100%;
     object-fit: cover;
   }
+  &__start {
+    position: absolute;
+    left: 50%;
+    bottom: 68px;
+    width: 220px;
+    height: 60px;
+    line-height: 60px;
+    text-align: center;
+    color: white;
+    font-size: 24px;
+    cursor: pointer;
+    transform: translateX(-50%);
+    background: url("@/assets/images/tab_liulan-min.png") no-repeat center /
+      contain;
+  }
   &__btn {
     position: absolute;
     right: 34px;

+ 16 - 22
packages/pc/src/views/exhibition/index.vue

@@ -87,7 +87,7 @@
                 :style="
                   item.style || { top: item.y + 'px', left: item.x + 'px' }
                 "
-                @click="curImgIndex = index + 1"
+                @click="handlePoint(index + 1)"
               >
                 <span>{{ item.name }}</span>
               </div>
@@ -111,7 +111,7 @@
                 >
                   <div
                     :class="{ active: index === curImgIndex }"
-                    @click="curImgIndex = index"
+                    @click="handlePoint(index)"
                   >
                     <ElImage :src="imgItem.url" fit="cover" />
                   </div>
@@ -126,11 +126,11 @@
                 class="exhibition-cover-img__close"
                 @click="curImgIndex = 0"
               />
-              <video
+              <Vue3VideoPlay
                 v-if="imgList[curImgIndex]?._data?.type === 'video'"
-                controls
-                disablePictureInPicture
-                controlsList="nodownload nofullscreen noplaybackrate"
+                control
+                :volume="0.6"
+                :controlBtns="['audioTrack', 'volume', 'speedRate']"
                 :poster="imgList[curImgIndex]?.url"
                 :src="imgList[curImgIndex]?._data?.url"
               />
@@ -227,7 +227,7 @@
 </template>
 
 <script setup>
-import { ref, computed, watch } from "vue";
+import { ref, computed, watch, nextTick } from "vue";
 import { data } from "@syjy/base";
 import { flattenData } from "@syjy/base/utils";
 import { ElScrollbar, ElTooltip } from "element-plus";
@@ -235,6 +235,8 @@ import { useRoute } from "vue-router";
 import { SCENE_URL } from "@syjy/base/utils";
 // import VideoPopup from "@/components/VideoPopup/index.vue";
 import VideoCover from "@/components/VideoCover/index.vue";
+import "vue3-video-play/dist/style.css";
+import Vue3VideoPlay from "vue3-video-play";
 
 const route = useRoute();
 const showVideo = ref(false);
@@ -328,17 +330,9 @@ const goToTargetScene = () => {
   location.href = SCENE_URL + "&" + point.value.query;
 };
 
-// const handlePoint = (item) => {
-//   switch (item.type) {
-//     case "video":
-//       checkedPoint.value = item;
-//       videoVisible.value = true;
-//       break;
-//     case "index":
-//       curImgIndex.value = Number(item.target);
-//       break;
-//   }
-// };
+const handlePoint = (index) => {
+  curImgIndex.value = index;
+};
 
 watch(
   route,
@@ -560,16 +554,16 @@ watch(
         font-size: 16px;
         color: #614c3e;
       }
-      video,
+      #refPlayerWrap,
       .el-image {
+        position: relative;
         flex: 1;
         width: 0;
         height: 100%;
       }
       video {
-        &::-webkit-media-controls-fullscreen-button {
-          display: none;
-        }
+        width: 100%;
+        height: 100%;
       }
       &__close {
         position: absolute;

+ 25 - 0
pnpm-lock.yaml

@@ -86,6 +86,9 @@ importers:
       vue-router:
         specifier: ^4.0.3
         version: 4.0.3(vue@3.5.13)
+      vue3-video-play:
+        specifier: ^1.3.2
+        version: 1.3.2
       vuex:
         specifier: ^4.0.0
         version: 4.0.0(vue@3.5.13)
@@ -2533,6 +2536,9 @@ packages:
   highlight.js@10.7.3:
     resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==}
 
+  hls.js@1.5.18:
+    resolution: {integrity: sha512-znxR+2jecWluu/0KOBqUcvVyAB5tLff10vjMGrpAlz1eFY+ZhF1bY3r82V+Bk7WJdk03iTjtja9KFFz5BrqjSA==}
+
   hosted-git-info@2.8.9:
     resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
 
@@ -3873,6 +3879,10 @@ packages:
     peerDependencies:
       webpack: ^4.27.0 || ^5.0.0
 
+  throttle-debounce@3.0.1:
+    resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==}
+    engines: {node: '>=10'}
+
   thunky@1.1.0:
     resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==}
 
@@ -4097,6 +4107,9 @@ packages:
   vue-template-es2015-compiler@1.9.1:
     resolution: {integrity: sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==}
 
+  vue3-video-play@1.3.2:
+    resolution: {integrity: sha512-eEwCJ0NIkfVQgTj0I3Kf9b1E/04Qne8mQQiE8r77BocblHsZ2T6af3q8l8Zzs/OvjlpQAQvkN/ACVUOJC3RSXg==}
+
   vue@3.5.12:
     resolution: {integrity: sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==}
     peerDependencies:
@@ -7004,6 +7017,8 @@ snapshots:
 
   highlight.js@10.7.3: {}
 
+  hls.js@1.5.18: {}
+
   hosted-git-info@2.8.9: {}
 
   hpack.js@2.1.6:
@@ -8311,6 +8326,8 @@ snapshots:
       schema-utils: 3.3.0
       webpack: 5.96.1
 
+  throttle-debounce@3.0.1: {}
+
   thunky@1.1.0: {}
 
   to-regex-range@5.0.1:
@@ -8592,6 +8609,14 @@ snapshots:
 
   vue-template-es2015-compiler@1.9.1: {}
 
+  vue3-video-play@1.3.2:
+    dependencies:
+      hls.js: 1.5.18
+      throttle-debounce: 3.0.1
+      vue: 3.5.13
+    transitivePeerDependencies:
+      - typescript
+
   vue@3.5.12:
     dependencies:
       '@vue/compiler-dom': 3.5.12