Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 免费观看欧美一区二区三区,亚洲激情网站,国产亚洲高清在线精品99

          整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          全網(wǎng)最全的Cesium跟隨彈窗的全框架實(shí)現(xiàn)原理剖析

          全網(wǎng)最全的Cesium跟隨彈窗的全框架實(shí)現(xiàn)原理剖析

          ---

          **引言:揭開Cesium三維地球彈窗跟隨的秘密面紗**

          Cesium是一個(gè)開源的Web 3D地球可視化庫(kù),常用于地理信息系統(tǒng)、虛擬現(xiàn)實(shí)和導(dǎo)航等領(lǐng)域。而在Cesium中實(shí)現(xiàn)地圖上的彈窗跟隨功能,即當(dāng)視角發(fā)生變化時(shí),彈窗始終保持在目標(biāo)對(duì)象附近的固定相對(duì)位置,是一種常見且實(shí)用的需求。本文將全面解析如何在Cesium中實(shí)現(xiàn)跟隨彈窗的全框架,深入挖掘其背后的實(shí)現(xiàn)原理,并通過詳盡的代碼示例,讓您切實(shí)掌握這一技術(shù)難點(diǎn)。

          ---

          **【第一部分】Cesium基礎(chǔ)環(huán)境搭建**

          **標(biāo)題:Cesium入門與基本地圖加載**

          首先,我們需要引入Cesium庫(kù),并創(chuàng)建一個(gè)基本的地圖視圖。以下是簡(jiǎn)單的HTML結(jié)構(gòu)與JavaScript代碼:

          ```html

          <!DOCTYPE html>

          <html lang="en">

          <head>

          <meta charset="UTF-8">

          <title>Cesium跟隨彈窗示例</title>

          <link href="https://cesium.com/downloads/cesiumjs/releases/1.87/Build/Cesium/Widgets/widgets.css" rel="stylesheet">

          </head>

          <body>

          <div id="cesiumContainer"></div>

          <script src="https://cesium.com/downloads/cesiumjs/releases/1.87/Build/Cesium/Cesium.js"></script>

          <script src="app.js"></script>

          </body>

          </html>

          ```

          ```javascript

          // app.js

          var viewer = new Cesium.Viewer('cesiumContainer', {

          imageryProvider: Cesium.createWorldImagery(),

          baseLayerPicker: false,

          geocoder: false,

          homeButton: false,

          infoBox: false,

          sceneModePicker: false,

          navigationHelpButton: false,

          timeline: false,

          animation: false

          });

          // 加載地球模型或地標(biāo)等

          viewer.entities.add({

          position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),

          billboard: {

          image: 'marker.png',

          heightReference: Cesium.HeightReference.CLAMP_TO_GROUND

          }

          });

          ```

          ---

          **【第二部分】實(shí)現(xiàn)跟隨彈窗的核心原理**

          **標(biāo)題:利用實(shí)體與視錐體裁剪技術(shù)**

          跟隨彈窗的核心是保持彈窗相對(duì)于屏幕的位置不變,這就需要監(jiān)控視角的變化,并依據(jù)視角計(jì)算彈窗的位置。主要步驟包括:

          1. **獲取目標(biāo)對(duì)象的世界坐標(biāo)**:通過Cesium的實(shí)體(Entity)獲取其世界坐標(biāo)。

          2. **投影到視口坐標(biāo)**:利用`scene.mapProjection.project`方法將世界坐標(biāo)轉(zhuǎn)換為視口坐標(biāo)。

          3. **利用視錐體裁剪**:當(dāng)視角變化時(shí),通過監(jiān)聽`viewer.camera.moveEnd`事件,判斷彈窗是否在視錐體內(nèi),若不在,則將其重新定位到視錐體邊緣附近。

          ```javascript

          let targetEntity; // 初始化目標(biāo)實(shí)體

          let popupElement; // 彈窗元素

          // 監(jiān)聽視角變化

          viewer.camera.moveEnd.addEventListener(function () {

          const targetCartesian = targetEntity.position.getValue(Cesium.JulianDate.now());

          const targetPixel = viewer.scene.mapProjection.project(targetCartesian);

          // 判斷彈窗是否在視口范圍內(nèi)

          const isInViewport = isElementInViewport(popupElement, targetPixel);

          if (!isInViewport) {

          // 重新計(jì)算并設(shè)置彈窗位置

          const newPosition = calculatePopupPosition(targetPixel);

          setPopupPosition(newPosition);

          }

          });

          ```

          ---

          **【第三部分】彈窗元素定位與樣式**

          **標(biāo)題:CSS與JavaScript聯(lián)動(dòng)實(shí)現(xiàn)彈窗跟隨**

          為了讓彈窗在屏幕上正確顯示并跟隨目標(biāo)對(duì)象,需要對(duì)彈窗元素進(jìn)行CSS樣式設(shè)置,并在JavaScript中動(dòng)態(tài)調(diào)整其位置。

          ```css

          .popup {

          position: absolute;

          background-color: white;

          border-radius: 5px;

          padding: 10px;

          pointer-events: none;

          z-index: 1000;

          }

          ```

          ```javascript

          // 創(chuàng)建并添加彈窗元素

          popupElement = document.createElement('div');

          popupElement.className = 'popup';

          document.body.appendChild(popupElement);

          // 計(jì)算并設(shè)置彈窗位置函數(shù)

          function calculatePopupPosition(targetPixel) {

          // 根據(jù)目標(biāo)像素位置和屏幕尺寸計(jì)算彈窗位置

          // ...

          return newPosition;

          }

          function setPopupPosition(position) {

          popupElement.style.left = position.x + 'px';

          popupElement.style.top = position.y + 'px';

          }

          ```

          ---

          **【第四部分】?jī)?yōu)化與拓展**

          **標(biāo)題:處理邊界條件與適應(yīng)多目標(biāo)跟隨**

          在實(shí)際應(yīng)用中,還需考慮邊界條件,如彈窗超出屏幕邊界時(shí)的處理,以及多個(gè)目標(biāo)對(duì)象時(shí)如何分配彈窗位置等。可通過計(jì)算視口邊界、設(shè)置最大偏移量等方式優(yōu)化跟隨效果。

          ---

          **結(jié)語:領(lǐng)略Cesium跟隨彈窗的魅力**

          通過上述步驟,我們不僅掌握了在Cesium中實(shí)現(xiàn)跟隨彈窗的基礎(chǔ)方法,還洞察到了其背后的數(shù)學(xué)原理與邏輯思考。跟隨彈窗的實(shí)現(xiàn)不僅僅是簡(jiǎn)單的坐標(biāo)轉(zhuǎn)換,更是一次Web 3D空間思維與前端開發(fā)技術(shù)的深度融合。希望本文能幫助廣大開發(fā)者在Cesium開發(fā)道路上走得更遠(yuǎn),創(chuàng)造出更多有趣而實(shí)用的應(yīng)用場(chǎng)景。

          很早之前就有寫過一個(gè)wcPop.js彈窗插件,并且在h5酒店預(yù)訂、h5聊天室項(xiàng)目中都有使用過,效果還不錯(cuò)。當(dāng)初想著有時(shí)間整合一個(gè)Vue版本,剛好趁著國(guó)慶節(jié)空閑時(shí)間搗鼓了個(gè)vue.js版自定義模態(tài)彈出框組件VPopup

          v-popup 一款聚合Msg、Dialog、Popup、ActionSheet、Toast等功能的輕量級(jí)移動(dòng)端Vue彈窗組件。

          整合了有贊VantNutUI等熱門Vue組件庫(kù)中Popup彈出層、Toast輕提示、Notify消息提示、Dialog對(duì)話框及ActionSheet動(dòng)作面板等功能。

          使用組件

          // 在main.js中全局引入
          import Vue from 'vue'
          
          import Popup from './components/popup'
          Vue.use(Popup)

          支持如下兩種方式調(diào)用組件。

          • 標(biāo)簽式調(diào)用
          <v-popup
            v-model="showPopup"
            title="標(biāo)題內(nèi)容" 
            content="彈窗內(nèi)容,告知當(dāng)前狀態(tài)、信息和解決方法,描述文字盡量控制在三行內(nèi)"
            type="android"
            shadeClose="false"
            xclose
            z-index="2000"
            :btns="[
              {...},
              {...},
            ]"
          />
          • 函數(shù)式調(diào)用

          this.$vpopup({...}),傳入?yún)?shù)即可使用,該函數(shù)會(huì)返回彈窗組件實(shí)例。

          let $el = this.$vpopup({
            title: '標(biāo)題內(nèi)容',
            content: '彈窗內(nèi)容,描述文字盡量控制在三行內(nèi)',
            type: 'android',
            shadeClose: false,
            xclose: true,
            zIndex: 2000,
            btns: [
              {text: '取消'},
              {
                text: '確認(rèn)',
                style: 'color:#f60;',
                click: () => {
                  $el.close()
                }
              },
            ]
          });

          你可根據(jù)喜好或項(xiàng)目需要任意選擇一種調(diào)用方式即可。下面就開始講解下組件的實(shí)現(xiàn)。

          在components目錄下新建popup.vue頁(yè)面。

          組件參數(shù)配置

          <!-- Popup 彈出層模板 -->
          <template>
            <div v-show="opened" class="nuxt__popup" :class="{'nuxt__popup-closed': closeCls}" :id="id">
              <div v-if="JSON.parse(shade)" class="nuxt__overlay" @click="shadeClicked" :style="{opacity}"></div>
              <div class="nuxt__wrap">
                <div class="nuxt__wrap-section">
                  <div class="nuxt__wrap-child" :class="['anim-'+anim, type&&'popui__'+type, round&&'round', position]" :style="popupStyle">
                    <div v-if="title" class="nuxt__wrap-tit" v-html="title"></div>
                    <div v-if="type=='toast'&&icon" class="nuxt__toast-icon" :class="['nuxt__toast-'+icon]" v-html="toastIcon[icon]"></div>
                    <template v-if="$slots.content">
                      <div class="nuxt__wrap-cnt"><slot name="content" /></div>
                    </template>
                    <template v-else>
                      <div v-if="content" class="nuxt__wrap-cnt" v-html="content"></div>
                    </template>
                    <slot />
                    <div v-if="btns" class="nuxt__wrap-btns">
                      <span v-for="(btn,index) in btns" :key="index" class="btn" :class="{'btn-disabled': btn.disabled}" :style="btn.style" @click="btnClicked($event,index)" v-html="btn.text"></span>
                    </div>
                    <span v-if="xclose" class="nuxt__xclose" :class="xposition" :style="{'color': xcolor}" @click="close"></span>
                  </div>
                </div>
              </div>
            </div>
          </template>
          <script>
            // 彈窗索引,遮罩次數(shù),定時(shí)器
            let $index = 0, $lockCount = 0, $timer = {};
            export default {
              props: {
                ...
              },
              data() {
                return {
                  opened: false,
                  closeCls: '',
                  toastIcon: {
                    loading: '<svg viewBox="25 25 50 50"><circle fill="none" cx="50" cy="50" r="20"></circle></svg>',
                    success: '<svg viewBox="0 0 1024 1024"><path fill="none" d="M75.712 445.712l240.176 185.52s13.248 6.624 29.808 0l591.36-493.872s84.272-17.968 68.64 71.488c-57.04 57.968-638.464 617.856-638.464 617.856s-38.096 21.536-74.544 0C256.272 790.256 12.816 523.568 12.816 523.568s-6.672-64.592 62.896-77.856z"/></svg>',
                    fail: '<svg viewBox="0 0 1024 1024"><path fill="none" d="M450.602 665.598a62.464 62.464 0 0 0 122.88 0l40.96-563.198A102.615 102.615 0 0 0 512.042 0a105.256 105.256 0 0 0-102.4 112.64l40.96 552.958zm61.44 153.6a102.4 102.4 0 1 0 102.4 102.4 96.74 96.74 0 0 0-102.4-102.4z"/></svg>',
                  }
                }
              },
              watch: {
                value(val) {
                  const type = val ? 'open' : 'close';
                  this[type]();
                },
              },
              methods: {
                // 打開彈窗
                open() {
                  if(this.opened) return;
                  this.opened = true;
                  this.$emit('open');
                  typeof this.onOpen === 'function' && this.onOpen();
                  this.$el.style.zIndex = this.getZIndex() + 1;
                  
                  if(JSON.parse(this.shade)) {
                    if(!$lockCount) {
                      document.body.classList.add('nt-overflow-hidden');
                    }
                    $lockCount++;
                  }
                  
                  // 倒計(jì)時(shí)關(guān)閉
                  if(this.time) {
                    $index++;
                    // 防止重復(fù)點(diǎn)擊
                    if($timer[$index] !== null) clearTimeout($timer[$index])
                    $timer[$index] = setTimeout(() => {
                      this.close();
                    }, parseInt(this.time) * 1000);
                  }
          
                  // 長(zhǎng)按/右鍵彈窗
                  if(this.follow) {
                    // 避免獲取不到彈窗寬高
                    this.$nextTick(() => {
                      let obj = this.$el.querySelector('.nuxt__wrap-child');
                      let oW, oH, winW, winH, pos;
          
                      oW = obj.clientWidth;
                      oH = obj.clientHeight;
                      winW = window.innerWidth;
                      winH = window.innerHeight;
                      pos = this.getPos(this.follow[0], this.follow[1], oW, oH, winW, winH);
          
                      obj.style.left = pos[0] + 'px';
                      obj.style.top = pos[1] + 'px';
                    });
                  }
                },
                // 關(guān)閉彈窗
                close() {
                  if(!this.opened) return;
                  
                  this.closeCls = true;
                  setTimeout(() => {
                    this.opened = false;
                    this.closeCls = false;
                    if(JSON.parse(this.shade)) {
                      $lockCount--;
                      if(!$lockCount) {
                        document.body.classList.remove('nt-overflow-hidden');
                      }
                    }
                    if(this.time) {
                      $index--;
                    }
                    this.$emit('input', false);
                    this.$emit('close');
                    typeof this.onClose === 'function' && this.onClose();
                  }, 200);
                },
          
                // 點(diǎn)擊遮罩層
                shadeClicked() {
                  if(JSON.parse(this.shadeClose)) {
                    this.close();
                  }
                },
                // 按鈕事件
                btnClicked(e, index) {
                  let btn = this.btns[index];
                  if(!btn.disabled) {
                    typeof btn.click === 'function' && btn.click(e)
                  }
                },
                // 獲取彈窗層級(jí)
                getZIndex() {
                  for(var $idx = parseInt(this.zIndex), $el = document.getElementsByTagName('*'), i = 0, len = $el.length; i < len; i++)
                    $idx = Math.max($idx, $el[i].style.zIndex)
                  return $idx;
                },
                // 獲取彈窗坐標(biāo)點(diǎn)
                getPos(x, y, ow, oh, winW, winH) {
                  let l = (x + ow) > winW ? x - ow : x;
                  let t = (y + oh) > winH ? y - oh : y;
                  return [l, t];
                }
              },
            }
          </script>

          通過監(jiān)聽v-model值調(diào)用open和close方法。

          watch: {
              value(val) {
                  const type = val ? 'open' : 'close';
                  this[type]();
              },
          },

          如果想要實(shí)現(xiàn)函數(shù)式調(diào)用this.$vpopup({...}),則需要使用到Vue.extend擴(kuò)展實(shí)例構(gòu)造器。

          import Vue from 'vue';
          import VuePopup from './popup.vue';
          
          let PopupConstructor = Vue.extend(VuePopup);
          
          let $instance;
          
          let VPopup = function(options = {}) {
              // 同一個(gè)頁(yè)面中,id相同的Popup的DOM只會(huì)存在一個(gè)
              options.id = options.id || 'nuxt-popup-id';
          
              $instance = new PopupConstructor({
                  propsData: options
              });
          
              $instance.vm = $instance.$mount();
              
              let popupDom = document.querySelector('#' + options.id);
              if(options.id && popupDom) {
                  popupDom.parentNode.replaceChild($instance.$el, popupDom);
              } else {
                  document.body.appendChild($instance.$el);
              }
          
              Vue.nextTick(() => {
                  $instance.value = true;
              })
          
              return $instance;
          }
          
          VPopup.install = () => {
              Vue.prototype['$vpopup'] = VPopup;
              Vue.component('v-popup', VuePopup);
          }
          
          export default VPopup;

          這樣就實(shí)現(xiàn)了引入 Popup 組件后,會(huì)自動(dòng)在 Vue 的 prototype 上掛載 $vpopup 方法和注冊(cè) v-popup 組件。

          下面就可以愉快的使用標(biāo)簽式及函數(shù)式調(diào)用組件了。

          • 設(shè)置圓角及關(guān)閉按鈕

          <v-popup v-model="showActionPicker" anim="footer" type="actionsheetPicker" round title="標(biāo)題內(nèi)容"
              :btns="[
                  {text: '取消', click: () => showActionPicker=false},
                  {text: '確定', style: 'color:#00e0a1;', click: () => null},
              ]"
          >
              <ul class="goods-list" style="padding:50px;text-align:center;">
                  <li>雙肩包</li>
                  <li>鞋子</li>
                  <li>運(yùn)動(dòng)褲</li>
              </ul>
          </v-popup>
          
          <v-popup v-model="showBottom" position="bottom" round xclose title="標(biāo)題內(nèi)容">
              <ul class="goods-list" style="padding:50px;text-align:center;">
                  <li>雙肩包</li>
                  <li>鞋子</li>
                  <li>運(yùn)動(dòng)褲</li>
              </ul>
          </v-popup>
          • 設(shè)置按鈕禁用狀態(tài)

          按鈕設(shè)置disabled: true即可禁用按鈕事件。

          <v-popup v-model="showActionSheet" anim="footer" type="actionsheet" :z-index="2020"
              content="彈窗內(nèi)容,描述文字盡量控制在三行內(nèi)"
              :btns="[
                  {text: '拍照', style: 'color:#09f;', disabled: true, click: handleInfo},
                  {text: '從手機(jī)相冊(cè)選擇', style: 'color:#00e0a1;', click: handleInfo},
                  {text: '保存圖片', style: 'color:#e63d23;', click: () => null},
                  {text: '取消', click: () => showActionSheet=false},
              ]"
          />

          另外還支持自定義slot插槽內(nèi)容,當(dāng) content 和 自定義插槽 內(nèi)容同時(shí)存在,只顯示插槽內(nèi)容。

          <v-popup v-model="showComponent" xclose xposition="bottom" content="這里是內(nèi)容信息"
              :btns="[
                  {text: '確認(rèn)', style: 'color:#f60;', click: () => showComponent=false},
              ]"
              @open="handleOpen" @close="handleClose"
          >
              <template #content>當(dāng) content 和 自定義插槽 內(nèi)容同時(shí)存在,只顯示插槽內(nèi)容!</template>
              <div style="padding:30px 15px;">
                  <img src="assets/apple3.jpg" style="width:100%;" @click="handleContextPopup" />
              </div>
          </v-popup>

          好了,就分享到這里。希望對(duì)大家有所幫助。目前該組件正在項(xiàng)目中實(shí)戰(zhàn)測(cè)試,后續(xù)會(huì)分享相關(guān)使用情況。

          視頻采集和管理是多模態(tài)大數(shù)據(jù)應(yīng)用場(chǎng)景必不可少的環(huán)節(jié),在基于Vue2前端框架實(shí)現(xiàn)的Web界面如何進(jìn)行視頻的展示和播放是開發(fā)人員會(huì)遇到的一個(gè)主要技術(shù)問題。本文提供基于Vue2+video.js實(shí)現(xiàn)視頻的預(yù)覽的方案。

          采集的視頻數(shù)據(jù)在前端視頻管理模塊列表中展示,然后用彈窗查看視頻詳情并預(yù)覽播放。最開始使用 vue-mini-player 組件,可輕松實(shí)現(xiàn)視頻在編輯界面的彈窗中播放,但是遇到兩個(gè)問題:1)彈窗中播放著視頻,關(guān)閉窗口后,視頻流不會(huì)停止。2)關(guān)閉窗口,重新打開新的視頻編輯窗口后,依舊是繼續(xù)播放之前的視頻。其原因應(yīng)該是關(guān)閉舊的窗口后,視頻播放的控件沒有銷毀,導(dǎo)致新打開的控件其實(shí)還是舊控件的實(shí)例。查了很多關(guān)于vue-mini-player的文檔和使用樣例,沒有找到如何銷毀vue-mini-player控件。

          視頻列表

          單條視頻數(shù)據(jù)編輯界面

          video.js 是一個(gè)通用的可嵌入網(wǎng)頁(yè)的視頻播放器JS庫(kù),在Vue2中引用video.js可以創(chuàng)建播放組件對(duì)象,關(guān)閉視頻時(shí)能進(jìn)行操作。基于Vue2使用video.js方法如下。

          1. 安裝video.js:
          npm install video.js@6.13.0
          1. main.js注冊(cè)
          import videoJs from 'video.js'
          import 'video.js/dist/video-js.css'
          Vue.prototype.videoJs = videoJs //注冊(cè)
          1. vue代碼文件中使用組件

          創(chuàng)建<video>組件,可放在彈窗中任何需要的地方。重點(diǎn)是給出id值,設(shè)置屬性時(shí)需要用到。

          <template>
            <el-dialog :title="title" :visible.sync="open" width="900px" append-to-body>
                <video id="casvideoplayer" ref="videoPlayerRef" class="video-js">
                    <source :src="playUrl" type="video/mp4">
                </video>
                ...
                <div slot="footer" class="dialog-footer">
                  	<el-button type="primary" @click="submitForm">確 定</el-button>
                  	<el-button @click="cancel">取 消</el-button>
                </div>
              </el-dialog>
          </template>
          export default {
          data() {
              return {
              // 使用video.js播放視頻配置
              videoJsPlayer: null,
              playUrl:"", 			//視頻文件鏈接
              videoPlayerOption: {
                  controls: true, 			//確定播放器是否具有用戶可以與之交互的控件。沒有控件,啟動(dòng)視頻播放的唯一方法是使用autoplay屬性或通過Player API。
                  // url: "", 							//要嵌入的視頻資源url(不起作用?)
                  poster: '',   					//封面
                   autoplay: false, 	//自動(dòng)播放屬性, true/false/"muted"(靜音播放)
                  muted: false, 				//靜音播放
                  preload: 'none', 		//建議瀏覽器是否應(yīng)在<video>加載元素后立即開始下載視頻數(shù)據(jù)。
                  fluid: false, 					//是否自適應(yīng)布局,播放器將會(huì)有流體體積。換句話說,它將縮放以適應(yīng)容器。
                  width: "850px", 		//視頻播放器的顯示寬度(以像素為單位)(fluid=false時(shí)起作用)
                  height: "600px", 		//視頻播放器的顯示高度(以像素為單位)(fluid=false時(shí)起作用)
               },
          };
          methods: {
             // 視頻列表的“修改”按鈕,點(diǎn)擊后顯示修改彈窗
             handleUpdate(row) {
                  // 從后臺(tái)獲取視頻信息
                  getVedio(row.id).then(response => {
                      this.form = response.data;    //修改彈窗其他字段信息賦值
                      this.title = "修改視頻管理";
                      this.open = true;    								// 顯示修改彈窗
          
                      // video.js組件播放視頻
                      this.videoPlayerOption.poster = response.data.avator;
                      this.playUrl = response.data.contentsOrg;
                      this.showVideoWindow();   //設(shè)置視頻播放控件
                  });
               },
                 
              //(重點(diǎn)是這里)
              // 使用video.js組件播放視頻
               showVideoWindow(){
                  // 如果視頻播放控件已經(jīng)存在,切換視頻url,重新播放;如果控件不存在,創(chuàng)建
                  if(this.videoJsPlayer){
                      this.videoJsPlayer.src([
                           {
                              src: this.playUrl,
                              type: "video/mp4"
                           }
                       ]);
                      // 如何圖片不為空,設(shè)置視頻封面
                      if(this.videoPlayerOption.poster != null && this.videoPlayerOption.poster != ""){
                      		this.videoJsPlayer.poster(this.videoPlayerOption.poster);
                       }
                      this.videoJsPlayer.load(this.playUrl);
                      // this.videoJsPlayer.play();      //自動(dòng)播放(打開后,切換視頻后需自動(dòng)播放)
                   }else{
                      // 最開始創(chuàng)建一次視頻播放組件
                      this.$nextTick(() => {
                          this.videoJsPlayer = this.videoJs(
                              "casvideoplayer", 				//播放器控件id
                              this.videoPlayerOption //播放器設(shè)置項(xiàng)(這里設(shè)置的poster屬性不生效,需要在后面單獨(dú)設(shè)置)
                           );
                          this.videoJsPlayer.poster(this.videoPlayerOption.poster);  //貌似不生效?
                       })
                   }
               },
                 
              // 編輯彈窗頁(yè)面的“取消”按鈕
              cancel() {
                  // 重置視頻控件數(shù)據(jù)(video.js組件)
                  if(this.videoJsPlayer){
                      this.videoJsPlayer.reset();
                   }
          					this.reset();
           		},
          }

          以上代碼實(shí)現(xiàn)了在Vue2彈窗中播放視頻組件的功能,注意關(guān)閉彈窗時(shí)要使用“取消”按鈕。如果通過點(diǎn)擊彈窗右上角X關(guān)閉彈窗,視頻還可以在后臺(tái)繼續(xù)播放,但是打開一個(gè)新的視頻修改彈窗后,播放的視頻會(huì)終止,并切換到新視頻播放界面。即使這樣,目前的功能已經(jīng)不影響用戶正常使用。

          video.js還有一個(gè)強(qiáng)大功能,看到喜歡的畫面點(diǎn)擊右鍵可以保存視頻幀,另外支持畫中畫、設(shè)備投放等功能。

          video.js右鍵功能

          后續(xù)優(yōu)化改進(jìn)工作包括:1)把video.js視頻播放功能做成Vue組件,方便在不同的Vue代碼文件中調(diào)用。2)捕獲窗口關(guān)閉的事件(如點(diǎn)擊X關(guān)閉,或者鼠標(biāo)失焦點(diǎn)后關(guān)閉),關(guān)閉視頻流。

          video.js

          Vue

          【參考材料】

          video.js官方網(wǎng)站:https://videojs.com/

          其他編碼材料:

          https://blog.csdn.net/qq_60533482/article/details/128015308

          https://blog.csdn.net/Uookic/article/details/116131535

          https://www.cnblogs.com/DL-CODER/p/16833222.html


          主站蜘蛛池模板: 日韩精品视频一区二区三区| eeuss鲁片一区二区三区| 亚洲综合无码一区二区痴汉 | 无码人妻精品一区二区三区久久久 | 国产精品盗摄一区二区在线| 国产成人无码一区二区在线观看 | 美日韩一区二区三区| 色欲精品国产一区二区三区AV| 午夜福利一区二区三区高清视频| 无码乱人伦一区二区亚洲 | 色狠狠AV一区二区三区| 国产精品区AV一区二区| eeuss鲁片一区二区三区| 亚洲国产精品无码第一区二区三区| 性色av闺蜜一区二区三区| 精品福利一区二区三区免费视频 | 久久国产午夜精品一区二区三区 | 久久国产精品视频一区| 国产一区二区精品久久凹凸| 亚洲AV综合色区无码一区| 国产在线精品一区免费香蕉 | 伊人色综合一区二区三区| 国产精品区AV一区二区| 中文字幕一区二区视频| 亚洲Av高清一区二区三区| 少妇无码一区二区二三区| 无码国产精品一区二区免费vr| 欧美亚洲精品一区二区| 精品国产免费一区二区| 日韩视频在线一区| 一区二区三区在线观看视频| www一区二区三区| 国产激情视频一区二区三区| 人妻无码第一区二区三区| 精品福利一区二区三区免费视频 | 综合无码一区二区三区四区五区 | 亚洲国产激情在线一区| 亚洲乱码av中文一区二区| 国产精品一区二区三区久久| 亚洲视频在线一区二区| 一本一道波多野结衣AV一区|