Selaa lähdekoodia

refactor: adjust some player styles

Casper Dai 3 vuotta sitten
vanhempi
sitoutus
540be9bfb9

+ 74 - 98
src/components/external/DevicePlayer/index.vue

@@ -1,29 +1,28 @@
 <template>
   <div
     class="o-video"
-    :class="{ offline: !online }"
-    @mouseenter.stop="mouseOver"
-    @mouseleave.stop="mouseLeave"
+    :class="{ offline: !online, mask: showMask }"
   >
-    <video
-      v-if="online"
-      ref="player"
-      class="o-video__player o-simple-video"
-      muted
-      :poster="poster"
-    />
-    <slot />
-    <div
-      v-show="maskShow"
-      class="o-video__mask"
-    >
-      <div
-        class="l-flex--row center o-video__btn u-pointer"
-        @click="onClick"
-      >
-        <i :class="iconClass" />
+    <template v-if="online">
+      <video
+        ref="video"
+        class="o-video__player o-simple-video"
+        :poster="poster"
+        autoplay
+        muted
+        @pause="onPause"
+        @play="onPlay"
+      />
+      <div class="o-video__mask">
+        <div
+          class="l-flex--row center o-video__btn u-pointer"
+          @click="onClick"
+        >
+          <i :class="iconClass" />
+        </div>
       </div>
-    </div>
+    </template>
+    <slot />
   </div>
 </template>
 
@@ -40,10 +39,6 @@ export default {
       type: Object,
       required: true
     },
-    simple: {
-      type: [Boolean, String],
-      default: false
-    },
     autoplay: {
       type: [Boolean, String],
       default: false
@@ -53,12 +48,14 @@ export default {
     return {
       poster: videoPoster,
       loading: false,
-      maskShow: false,
       refreshShow: false,
-      paused: !this.autoplay
+      paused: false
     }
   },
   computed: {
+    showMask () {
+      return this.loading || this.refreshShow || this.paused
+    },
     iconClass () {
       if (this.loading) {
         return 'el-icon-loading'
@@ -79,20 +76,21 @@ export default {
     }
   },
   beforeDestroy () {
-    if (this.$player) {
-      this.destroyPlay()
-    }
+    this.destroyPlayer()
     this.$timer = null
   },
   methods: {
-    mouseOver () {
-      if (!this.online) {
-        return
-      }
-      this.maskShow = true
+    onPause () {
+      this.paused = true
     },
-    mouseLeave () {
-      this.maskShow = false
+    onPlay () {
+      this.paused = false
+      if (this.loading) {
+        this.loading = false
+        if (!this.autoplay) {
+          this.$player.pause()
+        }
+      }
     },
     onClick () {
       if (this.loading) {
@@ -100,7 +98,7 @@ export default {
       }
       if (this.refreshShow) {
         if (this.$player) {
-          this.destroyPlay()
+          this.destroyPlayer()
         }
         this.getAuthCode()
       } else {
@@ -124,94 +122,72 @@ export default {
           }
         },
         () => {
-          this.refreshShow = true
+          this.destroyPlayer()
         }
-      ).finally(() => {
-        this.loading = false
-      })
+      )
     },
     createPlayer ({ timestamp, token, expire }) {
       if (flvjs.isSupported()) {
-        // 创建一个flvjs实例
-        this.$player = flvjs.createPlayer({
+        const player = flvjs.createPlayer({
           type: 'flv',
           isLive: true,
           hasAudio: false,
           url: `${GATEWAY}/live/${this.device.id}.flv?authorization=${token}&timestamp=${timestamp}&expire=${expire}`
         })
-        this.$player.on('error', () => {
-          this.refreshShow = true
-          this.destroyPlay()
+        player.on(flvjs.Events.ERROR, e => {
+          console.log('flvjs', this.device.name, flvjs.Events.ERROR, e)
+          this.destroyPlayer()
           this.$message({
             type: 'warning',
-            message: '设备视频流出错'
+            message: `${this.device.name} 视频流出错`
           })
         })
-        let decodedFrames = 0
-        this.$player.on('statistics_info', res => {
-          decodedFrames = res.decodedFrames
+        player.on(flvjs.Events.METADATA_ARRIVED, () => {
+          console.log('flvjs', this.device.name, flvjs.Events.METADATA_ARRIVED)
+          clearTimeout(this.$timer)
         })
-        this.$timer = setTimeout(() => {
-          if (decodedFrames === 0) {
-            this.destroyPlay()
-            this.$message({
-              type: 'warning',
-              message: `${this.device.name}设备没有视频流`
-            })
-            this.refreshShow = true
-          }
-        }, 10000)
-        // 将实例挂载到video元素上面
-        this.$player.attachMediaElement(this.$refs.player)
 
         try {
-          // 开始运行加载 只要流地址正常 就可以在h5页面中播放出画面了
-          this.$player.load()
-          this.$player.play()
-          if (this.paused) {
-            this.$player.pause()
-          }
           this.refreshShow = false
+          this.$player = player
+          this.$timer = setTimeout(() => {
+            if (this.loading) {
+              this.destroyPlayer()
+              this.$message({
+                type: 'warning',
+                message: `暂未获取到 ${this.device.name} 的视频流`
+              })
+            }
+          }, 10000)
+          player.attachMediaElement(this.$refs.video)
+          player.load()
         } catch (error) {
-          console.log('连接websocker异常', error)
+          console.log('连接异常', error)
+          this.destroyPlayer()
         }
       }
     },
-    destroyPlay () {
+    destroyPlayer () {
       clearTimeout(this.$timer)
-      this.$player.pause()
-      this.$player.unload()
-      this.$player.detachMediaElement()
-      this.$player.destroy()
-      this.$player = null
+      this.loading = false
+      this.refreshShow = true
+      const player = this.$player
+      if (player) {
+        player.pause()
+        player.unload()
+        player.detachMediaElement()
+        player.destroy()
+        this.$player = null
+      }
     }
   }
 }
 </script>
 
 <style lang="scss" scoped>
-.o-video {
-  &__mask {
-    position: absolute;
-    top: 0;
-    left: 0;
-    width: 100%;
-    height: 100%;
-    background-color: rgba(0, 0, 0, 0.3);
-    z-index: 2;
-  }
-
-  &__btn {
-    position: absolute;
-    left: 50%;
-    top: 50%;
-    width: 64px;
-    height: 64px;
-    color: #fff;
-    font-size: 48px;
-    border-radius: 50%;
-    background-color: rgba(#000, 0.5);
-    transform: translate(-50%, -50%);
+.o-video:hover {
+  .o-video__mask {
+    display: inline-block;
   }
 }
 </style>

+ 3 - 3
src/components/external/camera/CameraDetail/index.vue

@@ -9,10 +9,10 @@
     </div>
     <video
       ref="player"
-      class="c-traffic-camera-detail__player o-simple-video"
-      muted
-      autoplay
+      class="c-traffic-camera-detail__video o-simple-video"
       :poster="poster"
+      autoplay
+      muted
     />
     <div class="c-traffic-camera-detail__footer has-padding">
       <div class="l-flex--row c-sibling-item--v c-video-controls">

+ 37 - 23
src/components/external/camera/CameraPlayer/index.vue

@@ -1,16 +1,23 @@
 <template>
   <div
     class="o-video"
-    :class="{ offline: !online }"
+    :class="{ offline: !online, mask: loading }"
   >
-    <video
-      v-if="online"
-      ref="video"
-      class="o-video__player o-simple-video"
-      muted
-      autoplay
-      :poster="poster"
-    />
+    <template v-if="online">
+      <video
+        ref="video"
+        class="o-video__player o-simple-video"
+        :poster="poster"
+        autoplay
+        muted
+        @play="onPlay"
+      />
+      <div class="o-video__mask">
+        <div class="l-flex--row center o-video__btn">
+          <i class="el-icon-loading" />
+        </div>
+      </div>
+    </template>
     <div
       v-else
       class="o-video__tag"
@@ -35,7 +42,8 @@ export default {
   },
   data () {
     return {
-      poster: videoPoster
+      poster: videoPoster,
+      loading: false
     }
   },
   computed: {
@@ -60,42 +68,48 @@ export default {
     this.destroyPlayer()
   },
   methods: {
+    onPlay () {
+      if (this.loading) {
+        this.loading = false
+      }
+    },
     createPlayer () {
       this.destroyPlayer()
       if (flvjs.isSupported()) {
         const { identifier } = this.camera
-        // 创建一个flvjs实例
         const player = flvjs.createPlayer({
           type: 'flv',
           isLive: true,
           hasAudio: false,
           url: `${GATEWAY_CAMERA}/${identifier}?authorization=${this.token}`
         })
-        player.on('error', e => {
-          console.log(e)
+        player.on(flvjs.Events.ERROR, e => {
+          console.log('flvjs', this.camera.name, flvjs.Events.ERROR, e)
           this.$message({
             type: 'warning',
             message: e
           })
         })
-        // 将实例挂载到video元素上面
-        player.attachMediaElement(this.$refs.video)
         try {
-          // 开始运行加载 只要流地址正常 就可以在h5页面中播放出画面了
+          this.loading = true
+          this.$player = player
+          player.attachMediaElement(this.$refs.video)
           player.load()
-          player.play()
         } catch (error) {
-          console.log('连接websocker异常', error)
+          console.log('连接异常', error)
+          this.destroyPlayer()
         }
-        this.$player = player
       }
     },
     destroyPlayer () {
+      this.loading = false
       if (this.$player) {
-        this.$player.pause()
-        this.$player.unload()
-        this.$player.detachMediaElement()
-        this.$player.destroy()
+        const player = this.$player
+        player.pause()
+        player.unload()
+        player.detachMediaElement()
+        player.destroy()
+        this.$player = null
       }
     }
   }

+ 33 - 0
src/scss/bem/_object.scss

@@ -286,6 +286,12 @@
   border-radius: $radius--mini;
   overflow: hidden;
 
+  &.mask {
+    .o-video__mask {
+      display: inline-block;
+    }
+  }
+
   &.offline {
     background: url("~@/assets/image_offline.svg") 0 0 / 100% 100% no-repeat;
 
@@ -296,6 +302,10 @@
         content: "离线";
       }
     }
+
+    .o-video__mask {
+      display: none;
+    }
   }
 
   &__player {
@@ -324,4 +334,27 @@
       content: "在线";
     }
   }
+
+  &__mask {
+    display: none;
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, 0.3);
+  }
+
+  &__btn {
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    width: 64px;
+    height: 64px;
+    color: #fff;
+    font-size: 48px;
+    border-radius: 50%;
+    background-color: rgba(#000, 0.5);
+    transform: translate(-50%, -50%);
+  }
 }