VideoWindow.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /* 引入Cesium */
  2. // import * as Cesium from 'Cesium';
  3. import Videojs from 'video.js'; //video.js7.0以后版本默认支持hls(m3u8)格式
  4. import "video.js/dist/video-js.css"; // 引入video.js的css
  5. // video 6.0及以上版本,需要引入videojs-flash库(5.0及以下版本,flash在其核心库中,高版本分离了flash)
  6. // rtmp流的视频格式为flv,只有flash能播放
  7. import "videojs-flash"; // 播放rtmp流需要的插件,flash插件。
  8. import "videojs-flvjs-es6"; //flv格式
  9. import {
  10. getGuid,
  11. } from "../common/common.js";
  12. import '../../Assets/styles/PopupWindow/VideoWindow.css';
  13. /**
  14. * 视频窗口
  15. */
  16. class VideoWindow {
  17. /**
  18. * 初始化
  19. * @author joy/创睿
  20. * @param {Object} viewer 三维场景viewer对象
  21. * @param {Cesium.Cartesian3} position 坐标位置
  22. * @param {Object} videoInfo 属性
  23. * @param {String} videoInfo.type 监控类型 hls 、 rtmp 、flv、mp4
  24. * @param {String} videoInfo.name 监控名称
  25. * @param {String} videoInfo.url 监控路径
  26. */
  27. constructor(viewer, position, videoInfo, offsetHeight) {
  28. if (!viewer) throw new Cesium.DeveloperError('no viewer object!');
  29. if (!position) throw new Cesium.DeveloperError('no position object!');
  30. this.viewer = viewer; //弹窗创建的viewer
  31. this.position = position; //弹窗挂载的位置
  32. this.offsetHeight = offsetHeight;
  33. //弹窗挂载的位置
  34. if (position instanceof Cesium.Cartesian3) {
  35. this.position = position;
  36. } else {
  37. this.position = Cesium.Cartesian3.fromDegrees(position[0], position[1], position[2] || 0);
  38. }
  39. //如果有div就移除
  40. if (document.getElementsByClassName("popup-video").length > 0) {
  41. document.getElementsByClassName("popup-video")[0].remove();
  42. viewer.entities.remove(viewer.entities.getById("videoPopupPoint"));
  43. }
  44. this.id = "popup_video_" + getGuid();
  45. this.popupDiv = document.createElement("div");
  46. this.popupDiv.classList.add("popup-video");
  47. this.popupDiv.id = this.id;
  48. // 将字符串模板生成的内容添加到DOM上
  49. this.viewer.container.append(this.popupDiv);
  50. // this.viewer.cesiumWidget.container.appendChild(this.popupDiv);
  51. //创建Html
  52. this.popupDiv.innerHTML = this._createHtml(videoInfo);
  53. switch (videoInfo.type) {
  54. case "hls":
  55. this.videotype = "application/x-mpegURL"; // 告诉videojs,这是一个hls流
  56. break;
  57. case "rtmp":
  58. this.videotype = "rtmp/flv"; // 告诉videojs这是一个rtmp流视频
  59. // 设置flash路径,用于在videojs发现浏览器不支持HTML5播放器的时候自动唤起flash播放器
  60. // Videojs.options.flash.swf = 'https://cdn.bootcss.com/videojs-swf/5.4.1/video-js.swf';
  61. break;
  62. case "flv":
  63. this.videotype = "video/x-flv"; // 告诉videojs这是一个flv
  64. break;
  65. case "mp4":
  66. this.videotype = "video/mp4"; // 告诉videojs这是一个mp4,普通视频
  67. break;
  68. }
  69. this.videoPlayer = Videojs(document.querySelector('#myvideo'), {
  70. controls: true, //开启交互,即是用户可控。用户可以与之交互的控件
  71. autoplay: 'muted', //自动播放
  72. loop: true, //视频一结束就重新开始
  73. muted: false, //开启视频时是否静音,默认情况下将使所有音频静音
  74. fluid: true, //根据外层css样式大小,自动填充宽高!比较实用,可搭配响应式
  75. aspectRatio: "16:9", //显示比率
  76. reload: "auto", //重载
  77. fullscreen: {
  78. options: {
  79. navigationUI: 'hide'
  80. }
  81. },
  82. sources: [{ //注意,如果是以option方式设置的src,是不能实现 换台的 (即使监听了nowPlayVideoUrl也没实现)
  83. src: videoInfo.url,
  84. type: this.videotype,
  85. }],
  86. }, function onPlayerReady() {
  87. console.log('onPlayerReady', this);
  88. })
  89. //添加场景事件,实时更新窗口的位置
  90. this.viewer.scene.postRender.addEventListener(this.postRender, this);
  91. this.initPoint();
  92. //绑定关闭事件
  93. document.getElementsByClassName("popup-video1-close-button")[0].onclick = () => {
  94. this.close();
  95. };
  96. }
  97. /**
  98. * 场景渲染事件 实时更新窗口的位置 使其与笛卡尔坐标一致
  99. * @ignore
  100. */
  101. postRender() {
  102. const canvasHeight = this.viewer.scene.canvas.height;
  103. const windowPosition = new Cesium.Cartesian2();
  104. Cesium.SceneTransforms.wgs84ToWindowCoordinates(
  105. this.viewer.scene,
  106. this.position,
  107. windowPosition
  108. );
  109. let elWidth = this.popupDiv.offsetWidth;
  110. let elHeight = this.popupDiv.offsetHeight;
  111. //elHeight 值需要设置一个合适的,否则很容易导致场景拖动的时候,弹窗存在偏移
  112. if (!!this.offsetHeight) {
  113. elHeight += this.offsetHeight;
  114. }
  115. this.popupDiv.style.left = windowPosition.x - elWidth / 2 + "px";
  116. this.popupDiv.style.top = windowPosition.y - elHeight + "px";
  117. const camerPosition = this.viewer.camera.position;
  118. let height = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(camerPosition).height;
  119. height += this.viewer.scene.globe.ellipsoid.maximumRadius;
  120. if ((!(Cesium.Cartesian3.distance(camerPosition, this.position) > height)) && this.viewer.camera.positionCartographic.height < 50000000) {
  121. this.popupDiv.style.display = "block";
  122. } else {
  123. this.popupDiv.style.display = "none";
  124. }
  125. }
  126. /**
  127. * 生成Html
  128. * @ignore
  129. * @param {Object} videoInfo
  130. */
  131. _createHtml(videoInfo) {
  132. let html = `
  133. <div class="popup-video-header">
  134. ${videoInfo.name }
  135. <span class="popup-video1-close-button">×</span>
  136. </div>
  137. <div class="popup-video-content">
  138. <video id="myvideo" class="video-js vjs-big-play-centered vjs-fluid" controls preload="auto" width="100%" height="100%"></video>
  139. </div>
  140. <div class="popup-video-tip">
  141. </div>
  142. `
  143. return html;
  144. }
  145. /**
  146. * 用于调试弹窗是否对得上位置,弹窗对上了该点,不然很容易出现弹窗偏移的问题
  147. * @ignore
  148. */
  149. initPoint() {
  150. this.billboard = new Cesium.Entity({
  151. id: "videoPopupPoint",
  152. name: "popupPoint",
  153. position: this.position, // 点的经纬度坐标
  154. billboard: {
  155. image: 'jt3dSDK/imgs/point/point.png',
  156. horizontalOrigin: Cesium.HorizontalOrigin.center,
  157. verticalOrigin: Cesium.VerticalOrigin.bottom,
  158. scale: 1,
  159. pixelOffset: new Cesium.Cartesian2(0, 0),
  160. disableDepthTestDistance: Number.POSITIVE_INFINITY,
  161. },
  162. });
  163. this.viewer.entities.add(this.billboard);
  164. }
  165. }
  166. /**
  167. * 通用对外公开函数
  168. */
  169. Object.assign(VideoWindow.prototype, /** @lends VideoWindow.prototype */ {
  170. /**
  171. * 关闭按钮
  172. */
  173. close() {
  174. this.popupDiv.remove();
  175. this.viewer.scene.postRender.removeEventListener(this.postRender, this);
  176. this.viewer.entities.remove(this.billboard);
  177. Videojs("myvideo").dispose() //销毁video实例,避免出现节点不存在 但是flash一直在执行,报 this.el.......is not function
  178. this.videoPlayer.dispose() //销毁video实例
  179. }
  180. });
  181. export default VideoWindow;