类名 view/utils/mapV/MapVLayerPlugin.js
import mapboxgl from '@mapgis/mapbox-gl'
import MapvBaseLayer from './MapvBaseLayer'

/**
 * @origin author kyle / http://nikai.us/
 * @author 基础平台/创新中心 潘卓然 ParnDeedlit
 * @class module:客户端可视化.MapvLayer
 * @classdesc 基于mapboxgl的Layer对象进行的拓展
 * @param map - {Object} 传入的mapboxgl的地图对象
 * @param dataset - {MapvDataSet} 传入的mapv的属性。 <br>
 * @param mapvoption - {MapvOption} 可选参数。<br>
 * @see https://github.com/huiyan-fe/mapv/blob/master/API.md
 * @example
 * var options = {
      size: 13,
      gradient: {
        0.25: "rgb(0,0,255)",
        0.55: "rgb(0,255,0)",
        0.85: "yellow",
        1.0: "rgb(255,0,0)"
      },
      max: 60,
      animation: {
        type: 'time',
        stepsRange: {
          start: 0,
          end: 100
        },
        trails: 10,
        duration: 4,
      },
      draw: 'heatmap'
    }

 var mapvLayer = new mapboxgl.zondy.MapvLayer(map, dataSet, options);
 */
class MapvLayer {
  constructor(map, dataSet, mapVOptions) {
    this.map = map
    this.layerID = mapVOptions.layerID
    delete mapVOptions['layerID']
    this.mapvBaseLayer = new MapvBaseLayer(map, dataSet, mapVOptions, this)
    this.mapVOptions = mapVOptions

    this.initDevicePixelRatio()

    this.canvas = this._createCanvas()

    this.render = this.render.bind(this)

    this.bindEvent()

    this.mapContainer = map.getCanvasContainer()
    this.mapContainer.appendChild(this.canvas)
    // this.mapContainer.style.perspective = this.map.transform.cameraToCenterDistance + 'px';

    this._reset()
  }

  initDevicePixelRatio() {
    this.devicePixelRatio = window.devicePixelRatio || 1
  }

  // -----------------------------------Event Methods----------------------------------------
  bindEvent() {
    const map = this.map
    // 下面几个是mapboxgl专属事件,clickEvent和mousemoveEvent是mapv内部自带的方法不放出来
    this.innerMoveStart = this.moveStartEvent.bind(this)
    this.innerMoveEnd = this.moveEndEvent.bind(this)

    this.innnerZoomStart = this.zoomStartEvent.bind(this)
    this.innnerZoomEnd = this.zoomEndEvent.bind(this)

    this.innnerRotateStart = this.rotateStartEvent.bind(this)
    this.innnerRotateEnd = this.rotateEndEvent.bind(this)

    this.innerResize = this.resizeEvent.bind(this)

    this.innerRemove = this.removeEvent.bind(this)

    map.on('resize', this.innerResize)

    map.on('zoomstart', this.innnerZoomStart)
    map.on('zoomend', this.innnerZoomEnd)

    map.on('rotatestart', this.innnerRotateStart)
    map.on('rotateend', this.innnerRotateEnd)

    map.on('movestart', this.innerMoveStart)
    map.on('moveend', this.innerMoveEnd)

    this.map.on('remove', this.innerRemove)
  }

  unbindEvent() {
    const map = this.map
    map.off('resize', this.innerResize)

    map.off('zoomstart', this.innnerZoomStart)
    map.off('zoomend', this.innnerZoomEnd)

    map.off('rotatestart', this.innnerRotateStart)
    map.off('rotateend', this.innnerRotateEnd)

    map.off('movestart', this.innerMoveStart)
    map.off('moveend', this.innerMoveEnd)
  }

  moveStartEvent() {
    this.mapvBaseLayer.animatorMovestartEvent()
    this._unvisiable()
  }

  moveEndEvent() {
    this.mapvBaseLayer.animatorMoveendEvent()
    this._reset()
    this._visiable()
  }

  zoomStartEvent() {
    this._unvisiable()
  }

  zoomEndEvent() {
    this._unvisiable()
  }

  rotateStartEvent() {
    this.mapvBaseLayer.animatorMovestartEvent()
    this._unvisiable()
  }

  rotateEndEvent() {
    this.mapvBaseLayer.animatorMoveendEvent()
    this._reset()
    this._visiable()
  }

  resizeEvent() {
    this._reset()
    this._visiable()
  }

  removeEvent() {
    this.mapContainer.removeChild(this.canvas)
  }
  // -----------------------------------Event Methods----------------------------------------

  // -----------------------------------Start Data Operation---------------------------------
  /**
   * 增加数据
   * @function mapboxgl.zondy.MapvLayer.prototype.addData
   *
   * @param data - {Array} 数据.
   * @param options - {Object} 只做额外增加的字段作用
   */
  addData(data, options) {
    this.mapvBaseLayer.addData(data, options)
  }

  /**
   * 更新数据
   * @function mapboxgl.zondy.MapvLayer.prototype.updateData
   *
   * @param data - {Array} 数据.
   * @param options - {Object} 只做额外增加的字段作用
   */
  updateData(data, options) {
    this.mapvBaseLayer.updateData(data, options)
  }

  getData() {
    if (this.mapvBaseLayer) {
      this.dataSet = this.mapvBaseLayer.getData()
    }
    return this.dataSet
  }

  /**
   * @function mapboxgl.zondy.MapvLayer.prototype.removeData
   * @param filter - {Function} 过滤函数,返回true的保留
   * @description 移除满足过滤条件的数据
   * @example
   * filter: function(item){
            if (item.count > 10 && item.count < 50) {
                return true;
            } else {
                return false;
            }
        }
   */
  removeData(filter) {
    this.mapvBaseLayer && this.mapvBaseLayer.removeData(filter)
  }

  /**
   * @function mapboxgl.zondy.MapvLayer.prototype.removeAllData
   * @description 移除全部数据
   */
  removeAllData() {
    this.mapvBaseLayer.clearData()
  }
  // -----------------------------------End Data Operation---------------------------------

  _visiable() {
    this.canvas.style.display = 'block'
    return this
  }

  _unvisiable() {
    this.canvas.style.display = 'none'
    return this
  }

  _createCanvas() {
    const canvas = document.createElement('canvas')
    const devicePixelRatio = this.devicePixelRatio
    canvas.id = this.layerID
    canvas.style.position = 'absolute'
    canvas.style.top = '0px'
    canvas.style.left = '0px'
    canvas.width = parseInt(this.map.getCanvas().style.width) * devicePixelRatio
    canvas.height =
      parseInt(this.map.getCanvas().style.height) * devicePixelRatio
    if (!this.mapVOptions.context || this.mapVOptions.context == '2d') {
      canvas.getContext('2d').scale(devicePixelRatio, devicePixelRatio)
    }
    canvas.style.width = this.map.getCanvas().style.width
    canvas.style.height = this.map.getCanvas().style.height
    return canvas
  }

  _reset() {
    if (this.canvas == null) {
      return
    }
    this.resizeCanvas()
    this.fixPosition()
    this.onResize()
    this.render()
  }

  draw() {
    return this._reset()
  }

  /**
   * 显示图层
   * @function mapboxgl.zondy.MapvLayer.prototype.show
   */
  show() {
    this._visiable()
  }

  /**
   * 隐藏图层
   * @function mapboxgl.zondy.MapvLayer.prototype.hide
   */
  hide() {
    this._unvisiable()
  }

  /**
   * 更新图层
   * @function mapboxgl.zondy.MapvLayer.prototype.update
   * @param opt.data - {Array} 需要更新的数据
   * @param opt.options - {Object} 需要更新的样式
   */
  update(opt) {
    if (opt == undefined) {
      return
    }
    this.updateData(opt.data, opt.options)
  }

  resizeCanvas() {
    this.mapContainer.style.perspective = `${this.map.transform.cameraToCenterDistance}px`
    if (this.canvas == undefined || this.canvas == null) return
    const canvas = this.canvas
    const devicePixelRatio = this.devicePixelRatio
    canvas.style.position = 'absolute'
    canvas.style.top = '0px'
    canvas.style.left = '0px'
    canvas.width = parseInt(this.map.getCanvas().style.width) * devicePixelRatio
    canvas.height =
      parseInt(this.map.getCanvas().style.height) * devicePixelRatio
    // canvas.style.width = this.map.getCanvas().style.width;
    // canvas.style.height = this.map.getCanvas().style.height;
    if (!this.mapVOptions.context || this.mapVOptions.context == '2d') {
      canvas.getContext('2d').scale(devicePixelRatio, devicePixelRatio)
    }
  }

  fixPosition() {}

  onResize() {}

  originPosition() {
    this.originPitch = this.map.getPitch()
    this.originBearing = this.map.getBearing()
    const origin = this.map.project(new mapboxgl.LngLat(0, 0))
    this.originX = origin.x
    this.originY = origin.y
  }

  render() {
    if (this.mapvBaseLayer == undefined) return
    this.mapvBaseLayer._canvasUpdate()
  }

  moveTo(layerID, before) {
    const layer = document.getElementById(this.layerID)
    before = before !== undefined ? before : true
    if (before) {
      const beforeLayer = document.getElementById(layerID)
      if (layer && beforeLayer) {
        beforeLayer.parentNode.insertBefore(layer, beforeLayer)
      }
      return
    }
    const nextLayer = document.getElementById(layerID)
    if (layer) {
      if (nextLayer.nextSibling) {
        nextLayer.parentNode.insertBefore(layer, nextLayer.nextSibling)
        return
      }
      nextLayer.parentNode.appendChild(layer)
    }
  }

  /**
   * 移除图层,清空所有的事件与数据,与destroy效果一致,保持接口与mapboxgl本身一致
   * @function mapboxgl.zondy.MapvLayer.prototype.remove
   */
  remove() {
    this.removeAllData()
    this.unbindEvent()
    this.mapContainer.removeChild(this.canvas)
    this.disposeFlag = true
  }

  /**
   * 销毁图层,清空所有的事件与数据,与remove效果一致
   * @function mapboxgl.zondy.MapvLayer.prototype.destroy
   */
  destroy() {
    this.removeAllData()
    this.unbindEvent()
    this.mapContainer.removeChild(this.canvas)
    this.disposeFlag = true
  }
}

export default MapvLayer
构造函数
成员变量
方法
事件