@ciniki/iclient-maplibregl
Version:
@supermapgis/iclient-maplibregl 是一套基于 Maplibre GL 的云 GIS 网络客户端开发平台, 支持访问 SuperMap iServer / iEdge / iPortal / iManager / Online 的地图、服务和资源,为用户提供了完整专业的 GIS 能力, 同时提供了优秀的可视化功能。
268 lines (252 loc) • 8.39 kB
JavaScript
/* Copyright© 2000 - 2025 SuperMap Software Co.Ltd. All rights reserved.
* This program are made available under the terms of the Apache License, Version 2.0
* which accompanies this distribution and is available at http://www.apache.org/licenses/LICENSE-2.0.html.*/
import maplibregl from 'maplibre-gl';
import { MapvRenderer } from '@ciniki/iclient-common/overlay/mapv/MapvRenderer';
import { Util as CommonUtil } from '@ciniki/iclient-common/commontypes/Util';
import {
getMeterPerMapUnit
} from '@ciniki/iclient-common/util/MapCalculateUtil';
/**
* @class MapvLayer
* @category Visualization MapV
* @classdesc Mapv 图层类。MapV 是一款地理信息可视化开源库,MapV 图层可以用来展示大量地理信息数据,点、线、面的数据,每种数据也有不同的展示类型,如直接打点、热力图、网格、聚合等方式展示数据。<br>
* 展示大量的点数据:如热力图、网格、蜂窝状、点聚合、按颜色区间、按半径大小等方式。<br>
* 展示大量的线数据:如普通画线、高亮叠加、热力线数据展示等方式,适合展示大量轨迹的场景。<br>
* 展示大量的自定义面数据:按颜色区间来展示,如展示行政区划数据。
* @version 11.1.0
* @modulecategory Overlay
* @param {maplibregl.Map} map - MapLibreGL Map 对象,将在下个版本弃用,请用 map.addLayer() 方法添加图层。
* @param {Mapv.DataSet} dataSet - MapV 图层数据集。
* @param {Object} options - Mapv 参数。
* @param {string} [options.layerID] - 图层 ID。默认使用 CommonUtil.createUniqueID("mapvLayer_") 创建专题图层 ID。
* @usage
*/
export class MapvLayer {
constructor(dataSet, options) {
this.id = options.layerID ? options.layerID : CommonUtil.createUniqueID('mapvLayer_');
delete options['layerID'];
this.options = options;
this.dataSet = dataSet;
this.type = 'custom';
this.isPitching = false;
this.pitchStartEvent = this._pitchStart.bind(this);
this.pitchEndEvent = this._pitchEnd.bind(this);
this.renderingMode = '3d';
this.context = this.options.context || '2d';
this.overlay = true;
}
/**
* @function MapvLayer.prototype.onAdd
* @description 添加该图层
*/
onAdd(map) {
this.map = map;
this.mapContainer = map.getCanvasContainer();
this.renderer = new MapvRenderer(map, this.dataSet, this.options, {
transferCoordinate: this._transferCoordinate,
getCenterPixel: this._getCenterPixel,
getResolution: this._getResolution,
validZoom: this._validZoom.bind(this)
}, { id: this.id, targetElement: this.mapContainer, mapElement: this.map.getCanvas() });
this.mapContainer.style.perspective = this.map.transform.cameraToCenterDistance + 'px';
this._bindEvent();
}
/**
* @function MapvLayer.prototype.onRemove
* @description 添加该图层
*/
onRemove() {
this.renderer.destroy();
this._unbindEvent();
}
/**
* @function MapvLayer.prototype.render
* @description 添加该图层
*/
render() {
if (this.map.isZooming() || this.map.isRotating() || this.isPitching) {
this.renderer.visible() && this.renderer.hide();
return;
}
!this.renderer.visible() && this.renderer.show();
this.renderer.draw();
}
/**
* @function MapvLayer.prototype.hide
* @description 隐藏该图层
*/
hide() {
this.renderer && this.renderer.hide();
return this;
}
/**
* @function MapvLayer.prototype.show
* @description 显示该图层
*/
show() {
this.renderer && this.renderer.show();
return this;
}
_validZoom() {
var self = this;
if (
(self.options.minZoom && this.map.getZoom() < self.options.minZoom) ||
(self.options.maxZoom && this.map.getZoom() > self.options.maxZoom)
) {
return false;
}
return true;
}
_transferCoordinate() {
let map = this.map;
var bounds = map.getBounds(),
dw = bounds.getEast() - bounds.getWest(),
dh = bounds.getNorth() - bounds.getSouth();
var resolutionX = dw / this.map.getCanvas().getBoundingClientRect().width,
resolutionY = dh / this.map.getCanvas().getBoundingClientRect().height;
// 一个像素是多少米
var center = map.getCenter();
var centerPx = map.project(center);
var self = this;
return function (coordinate) {
if (map.transform.rotationMatrix || self.context === '2d') {
var worldPoint = map.project(new maplibregl.LngLat(coordinate[0], coordinate[1]));
return [worldPoint.x, worldPoint.y];
}
var pixel = [(coordinate[0] - center.lng) / resolutionX, (center.lat - coordinate[1]) / resolutionY];
return [pixel[0] + centerPx.x, pixel[1] + centerPx.y];
}
}
_getResolution() {
var bounds = this.map.getBounds();
var dw = bounds.getEast() - bounds.getWest();
var rect = this.map.getCanvas().getBoundingClientRect();
var resolutionX = dw / rect.width;
// 一个像素是多少米
return getMeterPerMapUnit('DEGREE') * resolutionX;
}
_getCenterPixel() {
return this.map.project(new maplibregl.LngLat(0, 0));
}
/**
* @function MapvLayer.prototype.getTopLeft
* @description 获取左上的坐标。
*/
getTopLeft() {
var map = this.map;
var topLeft;
if (map) {
var bounds = map.getBounds();
topLeft = bounds.getNorthWest();
}
return topLeft;
}
/**
* @function MapvLayer.prototype.addData
* @description 追加数据。
* @param {Object} data - 要追加的数据。
* @param {Object} options - 要追加的值。
*/
addData(data, options) {
this.renderer.addData(data, options);
}
/**
* @function MapvLayer.prototype.update
* @description 更新图层。
* @param {Object} opt - 待更新的数据。
* @param {Object} opt.data - mapv 数据集。
* @param {Object} opt.options - mapv 绘制参数。
*/
update(opt) {
this.renderer.update(opt);
}
/**
* @function MapvLayer.prototype.getData
* @description 获取数据。
* @returns {Mapv.DataSet} mapv 数据集。
*/
getData() {
if (this.renderer) {
this.dataSet = this.renderer.getData();
}
return this.dataSet;
}
/**
* @function MapvLayer.prototype.removeData
* @description 删除符合过滤条件的数据。
* @param {function} [filter] - 过滤条件。条件参数为数据项,返回值为 true,表示删除该元素;否则表示不删除。
* @example
* filter=function(data){
* if(data.id=="1"){
* return true
* }
* return false;
* }
*/
removeData(filter) {
this.renderer && this.renderer.removeData(filter);
}
/**
* @function MapvLayer.prototype.clearData
* @description 清除数据。
*/
clearData() {
this.renderer.clearData();
}
_bindEvent() {
var map = this.map;
map.on('pitchstart', this.pitchStartEvent);
map.on('pitchend', this.pitchEndEvent);
if (this.options.methods) {
if (this.options.methods.click) {
map.on('click', this.renderer.clickEvent);
}
if (this.options.methods.mousemove) {
map.on('mousemove', this.renderer.mousemoveEvent);
}
}
}
_unbindEvent() {
let map = this.map;
map.off('pitchstart', this.pitchStartEvent);
map.off('pitchend', this.pitchEndEvent);
if (this.options.methods) {
if (this.options.methods.click) {
map.off('click', this.renderer.clickEvent);
}
if (this.options.methods.mousemove) {
map.off('mousemove', this.renderer.mousemoveEvent);
}
}
}
/**
* @function MapvLayer.prototype.setVisibility
* @description 设置图层可见性。
* @param {boolean} [visibility] - 是否显示图层(当前地图的 resolution 在最大最小 resolution 之间)。
*/
setVisibility(visibility) {
if (visibility !== this.visibility) {
this.visibility = visibility;
if (visibility) {
this.show();
} else {
this.hide();
}
}
}
/**
* @function MapvLayer.prototype.setZIndex
* @description 设置 canvas 层级。
* @param {number} zIndex - canvas 层级。
*/
setZIndex(z) {
this.renderer.setZIndex(z);
}
_pitchStart() {
this.isPitching = true;
}
_pitchEnd() {
this.isPitching = false;
}
}