@map-library/supermap
v1.6.0
Published
SuperMap 适配器是基于 Leaflet 和 SuperMap iClient 的地图组件,它为统一地图库提供了兼容 SuperMap 的功能实现。该适配器封装了复杂的底层接口,提供简单易用的 API,支持标记管理、图层控制和点聚合等高级功能。
Readme
SuperMap 适配器
SuperMap 适配器是基于 Leaflet 和 SuperMap iClient 的地图组件,它为统一地图库提供了兼容 SuperMap 的功能实现。该适配器封装了复杂的底层接口,提供简单易用的 API,支持标记管理、图层控制和点聚合等高级功能。
版本更新
v1.5.9
- 新增按需加载功能:优化包体积,支持按需引入组件,默认导出WMTSLayer 和 TiledMapLayer
- 增强坐标系统支持:crs可自定义传入,不传默认是L.CRS.EPSG4326
import { MapFactory } from '@map-library/core';
import '@map-library/supermap'; // 必须显式导入以触发注册
import '@map-library/supermap/style'; // 正确导入CSS路径
import 'proj4leaflet';
const crs = new L.Proj.CRS(
'EPSG:xxx', '+proj=longlat +ellps=GRS80 +no_defs +type=crs',
{
matrixIds: matrixIds,
resolutions: resolutions,
origin: [-180, 90]
}
);
this.map = MapFactory.createMap('supermap', {
container: 'map-container', // 地图容器ID或DOM元素
config: {
longitude: , // 初始中心点经度
latitude: , // 初始中心点纬度
crs: crs
}
});功能特性
- 基于 Leaflet 和 SuperMap iClient 开发
- 支持多图层管理
- 支持点标记、线、面等地图元素
- 支持点聚合功能
- 支持轨迹播放功能
- 支持绘制几何图形功能
- 提供统一的事件处理机制
- 集成 Leaflet.markercluster 实现高效聚合
- 支持绘图工具,可通过配置快速启用
安装
npm install @map-library/supermap @map-library/core基本用法
初始化地图
import { MapFactory } from '@map-library/core';
import '@map-library/supermap'; // 必须显式导入以触发注册
import '@map-library/supermap/style'; // 正确导入CSS路径
// 创建地图实例
const map = MapFactory.createMap('supermap',{
container: 'map-container', // 地图容器ID或DOM元素
config: {
serviceUrl: 'https://iserver.supermap.io/iserver/services/map-world/rest/maps/World', // SuperMap服务地址
longitude: 108, // 初始中心点经度
latitude: 34, // 初始中心点纬度
zoom: 5, // 初始缩放级别
maxZoom: 18 // 最大缩放级别
}
});
// 初始化地图
await map.initialize();添加标记
// 添加圆形标记
const circleMarker = map.addMarker({
position: [116.4, 39.9], // [lng, lat]格式
type: 'circle',
style: {
color: 'red',
radius: 8,
fillColor: 'red',
fillOpacity: 0.6
},
title: '北京',
popupContent: '<div>北京市</div>'
});
// 添加图标标记
const iconMarker = map.addMarker({
position: [121.4, 31.2],
type: 'icon',
style: {
iconUrl: 'https://unpkg.com/[email protected]/dist/images/marker-icon.png',
iconSize: [25, 41],
iconAnchor: [12, 41]
},
title: '上海',
popupContent: '<div>上海市</div>'
});
// 添加默认标记
const defaultMarker = map.addMarker({
position: [114.3, 30.6],
type: 'default',
title: '武汉',
popupContent: '<div>武汉市</div>'
});创建图标
// 创建普通图标
const customIcon = map.createIcon({
iconUrl: 'path/to/icon.png',
iconSize: [32, 32],
iconAnchor: [16, 32]
});
// 创建HTML图标(DIV图标)
const htmlIcon = map.createHtmlIcon({
html: '<div class="my-custom-pin">📍</div>',
className: 'custom-icon',
iconSize: [30, 30],
iconAnchor: [15, 30]
});
// 使用创建的图标
map.addMarker({
position: [116.4, 39.9],
type: 'icon',
title: '自定义图标标记',
style: {
icon: customIcon
}
});图层管理
// 创建新图层
const customLayer = map.createLayer('customLayer');
// 添加标记到指定图层
map.addMarker({
position: [113.3, 23.1],
type: 'default',
title: '广州',
layerId: 'customLayer' // 指定图层
});
// 显示/隐藏图层
map.hideLayer('customLayer');
map.showLayer('customLayer');
// 清空图层
map.clearLayer('customLayer');
// 移除图层
map.removeLayer('customLayer');地图控制
// 设置地图中心点
map.setCenter([108, 34]);
// 设置缩放级别
map.setZoom(6);
// 添加缩放控件
map.addControl({
type: 'zoom',
position: 'topright'
});
// 销毁地图
map.destroy();点聚合功能
SuperMap 适配器提供强大的点聚合功能,可以有效处理大量标记的展示问题。
创建点聚合
// 初始化点聚合
const markerCluster = map.initMarkerCluster({
id: 'cities', // 聚合ID,可选
distance: 80, // 聚合距离,默认80像素
maxZoom: 16, // 最大聚合缩放级别
spiderfyOnMaxZoom: true, // 在最大缩放级别时展开
showCoverageOnHover: true, // 悬停时显示聚合范围
zoomToBoundsOnClick: true, // 点击聚合时缩放到边界
animate: true, // 开启聚合动画效果
// 可选:初始数据
data: [
{
position: [116.4, 39.9],
title: '北京',
popupContent: '<div>北京市</div>'
},
{
position: [121.4, 31.2],
title: '上海',
popupContent: '<div>上海市</div>'
}
],
// 可选:自定义默认图标
defaultIcon: {
iconUrl: 'path/to/custom-icon.png',
iconSize: [32, 32],
iconAnchor: [16, 32]
}
});添加聚合点数据
// 添加单个点
markerCluster.addMarker({
position: [120.2, 30.3],
title: '杭州',
popupContent: '<div>杭州市</div>',
// 自定义图标
type: 'icon',
icon: {
iconUrl: 'path/to/hangzhou-icon.png',
iconSize: [24, 24]
},
// 点击事件处理
onClick: (e, pointData) => {
console.log('点击了杭州', pointData);
}
});
// 批量添加点
markerCluster.addData([
{
position: [113.3, 23.1],
title: '广州',
popupContent: '<div>广州市</div>'
},
{
position: [114.1, 22.5],
title: '深圳',
popupContent: '<div>深圳市</div>'
}
]);
// 替换所有点数据
markerCluster.setData(newCitiesData);聚合图层管理
// 获取点聚合实例
const cluster = map.getMarkerCluster('cities');
// 获取特定条件的点
const southernCities = cluster.getMarkers(point => {
return point.position[1] < 30; // 获取所有纬度小于30的城市
});
// 清空聚合图层
cluster.clear();
// 控制聚合图层可见性
cluster.setVisible(false);
cluster.setVisible(true);
// 销毁聚合图层
cluster.destroy();轨迹播放功能
SuperMap适配器提供轨迹播放功能,支持轨迹动画、控制播放速度、暂停/继续播放等操作。
初始化轨迹播放
// 准备轨迹数据 - 格式为经纬度数组 [[lng1, lat1], [lng2, lat2], ...]
const trackData = [
[116.391, 39.916], // 北京
[117.200, 39.084], // 天津
[118.146, 39.628], // 唐山
[119.586, 39.942], // 秦皇岛
[121.471, 31.233] // 上海
];
// 初始化轨迹播放器
const track = map.initTrack({
data: trackData, // 轨迹点位数据,必填
interval: 2, // 两点间动画时间间隔,默认1秒
multiple: 1, // 播放速度倍数,默认1倍
// 可选: 自定义轨迹点标记选项
markerOptions: {
title: '轨迹点',
// 使用适配器提供的createIcon方法创建图标
icon: map.createIcon({
iconUrl: 'path/to/vehicle-icon.png',
iconSize: [32, 32],
iconAnchor: [16, 16]
})
},
// 可选: 自定义轨迹线样式
pathOptions: {
color: '#FF5722',
weight: 5,
opacity: 0.7,
dashArray: '10, 10', // 虚线样式
lineCap: 'round'
}
});轨迹播放控制
// 开始播放轨迹
track.play({
startIndex: 0, // 从指定索引处开始播放,可选
autoFocus: true // 是否自动聚焦到轨迹点,默认true
});
// 暂停播放
track.pause();
// 继续播放
track.resume();
// 停止播放
track.stop({
resetPosition: true // 是否重置到起点,默认true
});
// 跳转到指定位置
track.moveTo(2, { // 跳转到第3个点
autoFocus: true // 是否自动聚焦,默认true
});
// 调整播放速度
track.setSpeed(2); // 2倍速播放轨迹事件监听
// 监听轨迹移动事件
track.onMove(event => {
console.log('当前位置索引:', event.index);
console.log('当前坐标:', event.position);
console.log('播放进度(0-1):', event.progress);
console.log('是否已完成:', event.isCompleted);
// 更新UI进度条示例
document.getElementById('progress-bar').style.width = `${event.progress * 100}%`;
// 更新当前位置信息
document.getElementById('position-info').textContent =
`经度: ${event.position[0].toFixed(4)}, 纬度: ${event.position[1].toFixed(4)}`;
});
// 移除特定监听器
track.offMove(specificCallback);
// 移除所有移动监听器
track.offMove();获取轨迹状态与销毁
// 获取当前状态
const state = track.getState();
console.log('当前索引:', state.index);
console.log('是否播放中:', state.playing);
console.log('是否暂停:', state.paused);
console.log('是否已完成:', state.completed);
console.log('播放进度:', state.progress);
// 销毁轨迹实例
track.destroy();绘制图形功能
SuperMap适配器提供了丰富的绘制功能,支持点、线、多边形、矩形和圆形等几何图形的绘制和编辑。
绘制几何图形
使用 MouseTool方法可以激活绘制模式,并在绘制完成后获取绘制的图形数据。
// 绘制点
map.MouseTool({
type: 'point', // 绘制类型: point
callback: (e) => {
console.log('绘制点完成', e.coordinates); // 输出: [经度, 纬度]
console.log('图形对象:', e.feature); // Leaflet Layer对象
}
});
// 绘制线
map.MouseTool({
type: 'polyline', // 绘制类型: polyline
callback: (e) => {
console.log('绘制线完成', e.coordinates); // 输出: [[经度1, 纬度1], [经度2, 纬度2], ...]
console.log('图形对象:', e.feature); // Leaflet Layer对象
}
});
// 绘制多边形
map.MouseTool({
type: 'polygon', // 绘制类型: polygon
callback: (e) => {
console.log('绘制多边形完成', e.coordinates); // 输出: [[经度1, 纬度1], [经度2, 纬度2], ...]
console.log('图形对象:', e.feature); // Leaflet Layer对象
}
});
// 绘制矩形
map.MouseTool({
type: 'rectangle', // 绘制类型: rectangle
callback: (e) => {
console.log('绘制矩形完成', e.coordinates); // 输出矩形的四个角坐标
console.log('图形对象:', e.feature); // Leaflet Layer对象
}
});
// 绘制圆形
map.MouseTool({
type: 'circle', // 绘制类型: circle
callback: (e) => {
console.log('绘制圆形完成');
console.log('圆心坐标:', e.center); // 输出: [经度, 纬度]
console.log('半径(米):', e.radius); // 圆形半径,单位米
console.log('图形对象:', e.feature); // Leaflet Layer对象
}
});自定义绘制样式
可以通过options参数自定义绘制过程中和绘制完成后的样式:
map.MouseTool({
type: 'polygon',
options: {
shapeOptions: {
color: '#3388ff', // 边框颜色
weight: 3, // 边框宽度
opacity: 0.8, // 边框透明度
fillColor: '#3388ff', // 填充颜色
fillOpacity: 0.2, // 填充透明度
dashArray: '5, 5' // 虚线样式
}
},
callback: (e) => {
console.log('绘制完成', e.coordinates);
}
});图形编辑功能
使用 MouseToolEditor方法可以编辑已绘制的几何图形:
// 编辑单个图形
map.MouseToolEditor({
feature: drawnPolygon, // 要编辑的图形对象(Leaflet Layer)
callback: (e) => {
console.log('编辑完成');
console.log('编辑后的坐标:', e.coordinates);
console.log('编辑后的图形对象:', e.feature);
}
});
// 编辑多个图形
map.MouseToolEditor({
features: [drawnPoint, drawnLine, drawnPolygon], // 要编辑的图形对象数组
callback: (e) => {
console.log('编辑完成');
console.log('编辑后的图形:', e.features); // 返回编辑后的所有图形
// 获取每个图形的编辑后坐标
e.features.forEach(feature => {
console.log(feature.type, feature.coordinates);
});
}
});停止绘制或编辑
可以随时停止当前激活的绘制或编辑操作:
// 停止绘制
map.deactivateMouseTool();
// 停止编辑
map.deactivateMouseToolEditor();实际应用示例
下面是一个结合绘制和编辑功能的完整示例:
// 定义绘制完成的回调
const drawCallback = (e) => {
console.log('绘制完成:', e);
// 存储绘制的图形以便后续编辑
const drawnFeature = e.feature;
// 启动编辑模式
document.getElementById('edit-btn').onclick = () => {
map.MouseToolEditor({
feature: drawnFeature,
callback: (editEvent) => {
console.log('编辑完成:', editEvent);
}
});
};
};
// 创建绘制工具栏
const createDrawingControls = () => {
const controls = document.createElement('div');
controls.className = 'drawing-controls';
['point', 'polyline', 'polygon', 'rectangle', 'circle'].forEach(type => {
const btn = document.createElement('button');
btn.textContent = type.charAt(0).toUpperCase() + type.slice(1);
btn.onclick = () => {
map.deactivateMouseTool(); // 先停止当前绘制
map.MouseTool({
type: type,
callback: drawCallback
});
};
controls.appendChild(btn);
});
const editBtn = document.createElement('button');
editBtn.textContent = 'Edit';
editBtn.id = 'edit-btn';
editBtn.disabled = true;
controls.appendChild(editBtn);
const stopBtn = document.createElement('button');
stopBtn.textContent = 'Stop';
stopBtn.onclick = () => {
map.deactivateMouseTool();
map.deactivateMouseToolEditor();
};
controls.appendChild(stopBtn);
document.body.appendChild(controls);
};
// 初始化地图后创建控件
map.initialize().then(() => {
createDrawingControls();
});高级用法
自定义点聚合图标
const customCluster = map.initMarkerCluster({
id: 'custom-cluster',
// 自定义聚合图标创建函数
iconCreateFunction: (cluster) => {
const count = cluster.getChildCount();
let size, className;
if (count < 10) {
size = 30;
className = 'cluster-small';
} else if (count < 100) {
size = 40;
className = 'cluster-medium';
} else {
size = 50;
className = 'cluster-large';
}
return map.createHtmlIcon({
html: `<div><span>${count}</span></div>`,
className: `custom-cluster ${className}`,
iconSize: [size, size]
});
}
});使用自定义标记
// 添加自定义标记
map.addMarker({
position: [110, 38],
type: 'custom',
customCreator: (position, style) => {
// 创建自定义标记
return L.marker(position, {
icon: map.createHtmlIcon({
html: '<div class="pulse-marker"></div>',
className: 'custom-div-icon',
iconSize: [30, 30]
})
});
},
title: '自定义标记'
});事件处理
// 添加带事件的标记
const eventMarker = map.addMarker({
position: [118, 36],
type: 'default',
title: '事件标记',
onClick: (e) => {
console.log('标记被点击', e);
}
});
// 在聚合点上添加事件
markerCluster.addMarker({
position: [119, 32],
title: '南京',
onClick: (e, data) => {
console.log('点击了聚合点', data);
}
});注意事项
- 确保在使用任何方法前调用
initialize()方法初始化地图 - 图标路径默认使用CDN地址,若需自定义图标,请提供完整URL
- 聚合功能需要正确引入
leaflet.markercluster相关资源 - 轨迹播放使用
requestAnimationFrame实现,确保在现代浏览器中使用 - 创建图标时使用适配器提供的
createIcon或createHtmlIcon方法,避免直接使用Leaflet API - 销毁地图时使用
destroy()方法释放资源 - 点聚合和轨迹播放实例在不需要时应调用其
destroy()方法清理资源 - 使用绘制功能需要正确引入
leaflet-draw相关资源
浏览器兼容性
SuperMap适配器兼容所有支持现代JavaScript的浏览器,包括:
- Chrome 60+
- Firefox 60+
- Safari 12+
- Edge 16+
- IE 11 (需要polyfill)
许可证
MIT
绘图工具功能
SuperMap 适配器集成了 Leaflet.draw 库,支持各种几何图形的绘制和编辑功能。可以通过两种方式使用:
方式一:初始化时配置
在创建地图实例时通过 drawing 配置项启用绘图工具:
// 创建地图实例并配置绘图工具
const map = new SuperMapAdapter({
container: 'map-container',
config: {
serviceUrl: 'https://iserver.supermap.io/iserver/services/map-world/rest/maps/World',
longitude: 108,
latitude: 34,
zoom: 5
},
drawing: {
enabled: true, // 是否启用绘图工具
position: 'topleft', // 控件位置
draw: {
// 配置绘制工具,设为 false 可禁用某类工具
polyline: true, // 线
polygon: true, // 多边形
rectangle: true, // 矩形
circle: true, // 圆
marker: true // 标记点
},
edit: {
remove: true // 允许删除
},
// 绘制完成的回调
onCreate: (e) => {
console.log('绘制完成', e.layer);
},
// 编辑完成的回调
onEdit: (e) => {
console.log('编辑完成', e.layers);
},
// 删除完成的回调
onDelete: (e) => {
console.log('删除完成', e.layers);
}
}
});
// 初始化地图
await map.initialize();方式二:动态启用绘图工具
也可以在地图初始化后,通过 setDrawingTools 方法动态启用绘图工具:
// 创建地图实例
const map = new SuperMapAdapter({
container: 'map-container',
config: {
serviceUrl: 'https://iserver.supermap.io/iserver/services/map-world/rest/maps/World',
longitude: 108,
latitude: 34,
zoom: 5
}
});
// 初始化地图
await map.initialize();
// 动态启用绘图工具
map.setDrawingTools({
enabled: true,
position: 'topleft',
draw: {
polyline: true,
polygon: true,
rectangle: true,
circle: true,
marker: true
},
edit: {
remove: true
},
onCreate: (e) => {
console.log('绘制完成', e.layer);
}
});获取和管理绘制的图形
// 获取所有绘制的图形
const features = map.getDrawnItems();
console.log('当前绘制的图形:', features);
// 清空所有绘制的图形
map.clearDrawnItems();
// 禁用绘图工具
map.setDrawingTools({
enabled: false
});绘图工具高级配置
// 创建地图实例并配置绘图工具的高级选项
const map = new SuperMapAdapter({
container: 'map-container',
config: {
serviceUrl: 'https://iserver.supermap.io/iserver/services/map-world/rest/maps/World',
longitude: 108,
latitude: 34,
zoom: 5
},
drawing: {
enabled: true,
position: 'topleft',
draw: {
// 自定义线条样式
polyline: {
shapeOptions: {
color: '#f357a1',
weight: 3
}
},
// 自定义多边形样式
polygon: {
allowIntersection: false, // 禁止相交
drawError: {
color: '#e1e100', // 错误时的颜色
message: '多边形不能相交!'
},
shapeOptions: {
color: '#bada55'
}
},
// 自定义圆形样式
circle: {
shapeOptions: {
color: '#662d91'
}
},
// 自定义矩形样式
rectangle: {
shapeOptions: {
color: '#fca45d'
}
},
// 禁用标记
marker: false
},
edit: {
remove: true
}
}
});
// 初始化地图
await map.initialize();使用额外的SuperMap模块
本适配器默认只封装了SuperMap iClient的部分常用功能。如果您需要使用适配器未直接提供的SuperMap iClient功能,您可以按照以下方式操作:
直接使用SuperMap iClient原生模块
当您安装了 @map-library/supermap后,@supermapgis/iclient-leaflet包已作为依赖被自动安装。因此,您可以直接在代码中导入并使用SuperMap iClient的任何模块,无需在您的package.json中额外添加依赖:
// 1. 首先导入适配器
import { MapFactory } from '@map-library/core';
import '@map-library/supermap';
import '@map-library/supermap/style';
// 2. 直接导入需要的SuperMap iClient模块
import {
HeatMapLayer,
QueryByBoundsService,
RankSymbolThemeLayer,
GeoFeatureThemeLayer
} from '@supermapgis/iclient-leaflet';
// 3. 在您的组件中使用这些模块
export default {
async mounted() {
// 创建地图实例
const map = MapFactory.createMap('supermap', {
container: 'map-container',
config: {
serviceUrl: 'https://iserver.supermap.io/iserver/services/map-world/rest/maps/World',
latitude: 34,
longitude: 108,
zoom: 5
}
});
await map.initialize();
// 获取原始的Leaflet地图实例
const leafletMap = map.getMap(); // 假设有一个getMap方法来获取Leaflet实例
// 使用SuperMap模块
const heatLayer = new HeatMapLayer("heatmap", {
map: leafletMap,
radius: 25,
gradient: {0.4: 'blue', 0.65: 'yellow', 0.85: 'orange', 1.0: 'red'}
});
// 添加数据到热力图层
heatLayer.addPoints([
{lng: 108, lat: 34, count: 100},
{lng: 109, lat: 35, count: 50},
// 更多数据点...
]);
// 创建查询服务
const queryService = new QueryByBoundsService("https://iserver.supermap.io/iserver/services/data-world/rest/data");
// ...使用查询服务
}
}结合使用适配器和原生模块
您可以同时使用本适配器提供的封装功能和SuperMap iClient的原生功能:
import { MapFactory } from '@map-library/core';
import '@map-library/supermap';
import { GraphThemeLayer } from '@supermapgis/iclient-leaflet';
export default {
async mounted() {
const map = MapFactory.createMap('supermap', {
// 适配器配置...
});
await map.initialize();
// 使用适配器提供的功能
const marker = map.addMarker({
position: [116.4, 39.9],
type: 'icon',
title: '北京'
});
// 使用适配器创建图层
const customLayer = map.createLayer('customLayer');
// 获取底层Leaflet实例
const leafletMap = map.getMap(); // 假设有此方法
// 使用SuperMap原生功能
const themeLayer = new GraphThemeLayer("GraphThemeLayer", {
map: leafletMap,
// 配置...
});
// 添加到地图
themeLayer.addTo(leafletMap);
}
}注意事项
- 版本兼容性:本适配器使用的是
@supermapgis/iclient-leafletv11.2.x版本。如果您需要使用特定版本,可以在您的package.json中明确指定版本号。 - 事件处理:当同时使用适配器和原生模块时,请注意事件处理机制可能有所不同。适配器提供了统一的事件API,而原生模块使用Leaflet事件系统。
- 内存管理:在组件销毁时,请确保同时调用适配器的destroy方法和手动清理通过原生API创建的图层和服务,以防止内存泄漏。
- CSS样式:适配器已经导入了基本样式,但某些高级组件可能需要额外的CSS。请参考SuperMap iClient官方文档确认是否需要导入额外样式。
- 内网环境:如果在内网环境使用,请确保所有依赖包(包括
@supermapgis/iclient-leaflet)都已正确安装在您的内网环境中。
获取更多帮助
更多关于SuperMap iClient的使用方法,请参考SuperMap官方文档:
