类名 view/utils/mapV/MapVLayerPlugin.js
import * as L from '@mapgis/leaflet'
import { MapvBaseLayer } from './MapvBaseLayer'
import { getMapRotateBounds } from '../support/utils'

const MapvLayerConstruct = L.Layer.extend({
  initialize(map, dataset, mapvoption, options) {
    this.map = map
    this.dataset = dataset || {}
    this.mapvoption = mapvoption

    options = options || {}
    this.render = this.render.bind(this)
    L.Util.setOptions(this, options)
    this._canvas = this._createCanvas()

    L.stamp(this)
    // 下面5个是leaflet专属事件,clickEvent和mousemoveEvent是mapv内部自带的方法不放出来
    this.innerMoveStartEvent = this.moveStartEvent.bind(this)
    this.innerMoveEndEvent = this.moveEndEvent.bind(this)
    this.innnerZoomstart = this.zoomStartEvent.bind(this)
    this.innerViewreset = this.viewresetEvent.bind(this)
    this.innerResize = this.resizeEvent.bind(this)
    this.innerRotate = this.rotateEvent.bind(this)
  },

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

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

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

  _createCanvas() {
    const canvas = document.createElement('canvas')
    canvas.style.position = 'absolute'
    canvas.style.top = '0px'
    canvas.style.left = '0px'
    canvas.style.pointerEvents = 'none'
    canvas.style.zIndex = this.options.zIndex || 100

    const size = this.map.getSize()
    canvas.width = size.x
    canvas.height = size.y
    canvas.style.width = `${size.x}px`
    canvas.style.height = `${size.y}px`

    const devicePixelRatio = this.devicePixelRatio
    canvas.getContext('2d').scale(devicePixelRatio, devicePixelRatio)
    if (this.mapvoption.context === '2d') {
      canvas.getContext('2d').scale(devicePixelRatio, devicePixelRatio)
    }
    return canvas
  },

  onAdd(map) {
    const tilePane = this.getPane()
    const _container = L.DomUtil.create('div', 'leaflet-layer', tilePane)
    _container.appendChild(this._canvas)

    this._container = _container

    this.mapvBaseLayer = new MapvBaseLayer(
      map,
      this.dataset,
      this.mapvoption,
      this
    )
    this.bindEvent()

    if (this.options.tileLoader) {
      this._initTileLoader()
    }

    this._reset()
    this.fire('loaded')
  },

  bindEvent() {
    const map = this.map
    map.on('movestart', this.innerMoveStartEvent)
    map.on('moveend', this.innerMoveEndEvent)
    map.on('zoomend', this.innerMoveEndEvent)
    map.on('zoomstart', this.innnerZoomstart)
    map.on('viewreset', this.innerViewreset)
    map.on('resize ', this.innerResize)
    map.on('rotate', this.innerRotate)
    this.mapvBaseLayer.bindEvent()
  },

  unbindEvent() {
    const map = this.map
    map.off('movestart', this.innerMoveStartEvent)
    map.off('moveend', this.innerMoveEndEvent)
    map.on('zoomend', this.innerMoveEndEvent)
    map.off('zoomstart', this.innnerZoomstart)
    map.off('viewreset', this.innerViewreset)
    map.off('resize ', this.innerResize)
    map.off('rotate', this.innerRotate)
    this.removeAllData()
    this.mapvBaseLayer.unbindEvent()
  },

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

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

  zoomStartEvent() {
    this._unvisiable()
  },

  viewresetEvent() {
    this._reset()
    this._visiable()
  },

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

  rotateEvent() {
    this._reset()
    this._visiable()
  },

  _animateZoom() {
    if (!this._animating) {
      this._animating = true
    }
  },

  _endZoomAnim() {},

  getCanvas() {
    return this._canvas
  },

  getAttribution() {
    return this.options.attribution
  },

  draw() {
    return this._reset()
  },

  onRemove() {
    L.DomUtil.remove(this._container)
    this.unbindEvent()
    this.disposeFlag = true
  },

  /**
   * 设置透明度
   * @function L.zondy.MapvLayer.prototype.setOpacity
   * @param opacity - {Number} 1.0.
   */
  setOpacity(opacity) {
    this._canvas.style.opacity = opacity
  },

  /**
   * 设置Zindex
   * @function L.zondy.MapvLayer.prototype.setZIndex
   * @param zIndex - {Number} 10.
   */
  setZIndex(zIndex) {
    this._canvas.style.zIndex = zIndex
  },

  bringToFront() {
    return this
  },

  bringToBack() {
    return this
  },

  _reset() {
    this.resizeCanvas()
    this.fixPosition()
    this.onResize()
    this.render()
  },

  _visiable() {
    this.getCanvas().style.display = 'block'
  },

  _unvisiable() {
    this.getCanvas().style.display = 'none'
  },

  _render() {
    this.render()
  },

  /**
   * @description 拖动的时候和放大缩小的时候自定义图层不见得会和地图的像素坐标同步计算
   * 因此再绘制自定义图层的时候需要重新计算对应的位置,这里主要是对齐左上角
   * */
  fixPosition() {
    const topleft = this.map.getBounds().getNorthWest()
    const offset = this.map.latLngToLayerPoint(topleft)
    if (topleft) {
      L.DomUtil.setPosition(this._canvas, {
        x: offset.x,
        y: offset.y
      })
    }
  },

  resizeCanvas() {
    let size
    // 根据旋转的范围改变覆盖物图层的容器大小
    if (this.map._rotate) {
      size = getMapRotateBounds(this.map).getSize()
    } else {
      size = this.map.getSize()
    }
    const canvas = this.getCanvas()
    canvas.width = size.x
    canvas.height = size.y
    canvas.style.width = `${size.x}px`
    canvas.style.height = `${size.y}px`
  },

  // use direct: true if you are inside an animation frame call
  redraw(direct) {
    this.resizeCanvas()
    this.fixPosition()

    if (direct) {
      this.render()
    } else {
      this.render()
    }
  },
  /**
   * 显示图层
   * @function L.zondy.MapvLayer.prototype.show
   */
  show() {
    this._visiable()
  },
  /**
   * 隐藏图层
   * @function L.zondy.MapvLayer.prototype.hide
   */
  hide() {
    this._unvisiable()
  },
  /**
   * 销毁图层
   * @function L.zondy.MapvLayer.prototype.destroy
   */
  destroy() {
    L.DomUtil.remove(this._container)
    this.unbindEvent()
    this.disposeFlag = true
  },
  /**
   * 更新图层
   * @function L.zondy.MapvLayer.prototype.update
   * @param opt.data - {Array} 需要更新的数据
   * @param opt.options - {Object} 需要更新的样式
   */
  update(opt) {
    if (opt === undefined) {
      return
    }
    this.mapvBaseLayer.updateData(opt.data, opt.options)
  },

  /**
   * @function L.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) {
    if (this.mapvBaseLayer) {
      this.mapvBaseLayer.removeData(filter)
    }
  },

  /**
   * @function L.zondy.MapvLayer.prototype.removeAllData
   * @description 移除全部数据
   */
  removeAllData() {},

  onResize() {},

  render() {
    this.mapvBaseLayer._canvasUpdate()
  }
})

const MapvLayer = function (dataSet, mapVOptions, options) {
  return new MapvLayerConstruct(dataSet, mapVOptions, options)
}

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