类名 common/document/layer/VideoMapLayer.js
import { Zondy } from '../../base'
import { LoadStatus, VideoSourceType } from '../../base/enum'
import { defaultValue, defined, getVideoType, Log } from '../../util'
import { Layer } from './baseLayer'

/**
 * 视频地图图层
 * @private
 * @class VideoMapLayer
 * @moduleEX LayerModule
 * @extends Evented
 * @param {Object} options 构造参数
 * @param {Extent} [options.Extent = undefined] 图层范围
 * @param {String} [options.id = ''] 图层ID
 * @param {Boolean} [options.visible = true] 图层可见性
 * @param {String} [options.description = ''] 图层描述信息
 * @param {String} [options.copyright = '中地数码版权所有'] 版权
 * @param {SpatialReference} [options.spatialReference = undefined] 图层坐标系
 * @param {String} [options.loadStatus = LoadStatus.notLoaded] 图层状态
 * @param {String} [options.source] 视频地图图层视频源地址
 * @param {String} [options.container] 视频图层容器
 */
class VideoMapLayer extends Layer {
  constructor(options) {
    super(options)
    options = defaultValue(options, {})

    this._source = defaultValue(options.source, null)

    if (!this._source) {
      Log.error('The video source is lost.')
      return
    }

    if (typeof options.container === 'string') {
      this._container = document.getElementById(options.container)
    } else {
      this._container = options.container
    }
    if (!this._container) {
      Log.error('The videoHTML container is lost.')
      return
    }

    if (!defined(window.videojs)) {
      Log.error('The video.js library is lost.')
      return
    }

    this._videoHtml = null
    this._hlsPlayer = null
    this._rtmpPlayer = null
    this._width = 0
    this._height = 0
  }

  get videoHtml() {
    return this._videoHtml
  }

  get rtmpPlayer() {
    return this._rtmpPlayer
  }

  get width() {
    return this._width
  }

  get height() {
    return this._height
  }

  /**
   * @function VideoMapLayer.prototype.isLoaded
   * @description 判断图层是否加载成功
   * @return {Boolean} 图层加载状态
   */
  isLoaded() {
    if (this.loadStatus === LoadStatus.loaded) {
      return true
    } else {
      return false
    }
  }

  /**
   * @function VideoMapLayer.load
   * @description 图层资源加载
   * @return {Promise<Layer>} 资源加载完毕的图层
   */
  load() {
    const videoType = getVideoType(this._source)
    return new Promise((resolve, reject) => {
      if (videoType === VideoSourceType.videoPlayer) {
        this._source.on('play', () => {
          this._width = this._source.videoWidth()
          this._height = this._source.videoHeight()
          resolve(this)
        })
        return
      } else if (videoType === VideoSourceType.videoHTML) {
        this._width = this._source.videoWidth
        this._height = this._source.videoHeight
        resolve(this)
        return
      }

      this._videoHtml = document.createElement('video')
      this._videoHtml.id = 'video'
      this._videoHtml.style.position = 'absolute'
      this._videoHtml.style.zIndex = '0'
      this._container.appendChild(this._videoHtml)
      // rtmp流中所有的标签页都需要有width,height
      // **特别注意必须要先设置样式的width和height**,否则rtmp视频流不会播放
      this._videoHtml.style.width = '100%'
      this._videoHtml.style.height = '100%'

      if (videoType === VideoSourceType.mp4) {
        // ---------mp4-----------
        this._videoHtml.crossOrigin = 'anonymous'
        this._videoHtml.autoplay = true
        this._videoHtml.loop = true
        this._videoHtml.src = this._source
        this._videoHtml.play()
        this._videoHtml.controls = true
      } else if (videoType === VideoSourceType.hls) {
        // ---------hls-----------
        this._hlsPlayer = videojs(this._videoHtml)
        this._hlsPlayer.src({
          type: 'application/x-mpegURL',
          src: this._source
        })
        this._hlsPlayer.load(this._source)
        this._hlsPlayer.play()
        this._hlsPlayer.loop(true)
        const videoHTML = this._hlsPlayer.el().querySelector('video')
        videoHTML.controls = true
      } else if (videoType === VideoSourceType.rtmp) {
        // ---------rtmp-----------
        this._rtmpPlayer = videojs(
          this._videoHtml,
          {
            sources: [
              {
                src: this._source,
                type: 'rtmp/flv'
              }
            ]
          },
          () => {
            this._rtmpPlayer.play()
            this._rtmpPlayer.loop(true)
          }
        )
        this._rtmpPlayer.on('play', () => {
          this._rtmpPlayer.width(this._rtmpPlayer.videoWidth())
          this._rtmpPlayer.height(this._rtmpPlayer.videoHeight())
          this._videoHtml.oncanplay()
        })
      }

      this._videoHtml.oncanplay = () => {
        this.loadStatus = LoadStatus.loaded
        this.loaded = true
        this._width = this._videoHtml.videoWidth
          ? this._videoHtml.videoWidth
          : this._rtmpPlayer
          ? this._rtmpPlayer.videoWidth()
          : 1
        this._height = this._videoHtml.videoHeight
          ? this._videoHtml.videoHeight
          : this._rtmpPlayer
          ? this._rtmpPlayer.videoHeight()
          : 1
        this._videoHtml.style.width = this._width
        this._videoHtml.style.height = this._height
        resolve(this)
      }
      this._videoHtml.onerror = () => {
        let err = '未知错误'
        switch (this._videoHtml.error.code) {
          case 1:
            err = '视频加载中断'
            break
          case 2:
            err = '网络链接错误'
            break
          case 3:
            err = '视频解码失败'
            break
          case 4:
            err = '不支持的视频'
            break
        }
        Log.error(`出现错误:${err}错误代码:${this._videoHtml.error.code}`)
        this.loadStatus = LoadStatus.failed
        reject(this._videoHtml.error)
      }
    })
  }
}
Zondy.Layer.VideoMapLayer = VideoMapLayer
export default VideoMapLayer
构造函数
成员变量
方法
事件