mapboxgl/overlay/MapvLayer.js Source
import mapboxgl from '@mapgis/mapbox-gl';
import '../core/Base';
import { MapvBaseLayer } from "./mapv/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);
 */
export 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() {
        var 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() {
        var 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() {
        var canvas = document.createElement('canvas');
        var 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;
        var canvas = this.canvas;
        var 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();
        var 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) {
        var layer = document.getElementById(this.layerID);
        before = before !== undefined ? before : true;
        if (before) {
            var beforeLayer = document.getElementById(layerID);
            if (layer && beforeLayer) {
                beforeLayer.parentNode.insertBefore(layer, beforeLayer);
            }
            return;
        }
        var 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;
    }

}

mapboxgl.zondy.MapvLayer = MapvLayer;