一、前言
因为工作需要在使用百度/高德以外实现地图功能。。。。巴拉巴拉。。。。 前文此处省略****字
二、介绍
WebGIS四大地图框架:Leaflet、OpenLayers、Mapbox、Cesium
Leaflet
Leaflet是一个轻量级、易于使用的开源JavaScript库,为开发者提供了创建交互式地图的强大工具。它具有丰富的地图功能和插件生态系统,支持各种地图数据源,从基本的点标记到复杂的地图覆盖物都可以轻松实现。Leaflet的优势在于其简洁性和易用性,使得它成为初学者和专业开发者的首选。
除了在普通地图应用程序中广泛应用外,Leaflet在公共卫生和生物计算等领域也有着广泛的应用。
在公共卫生领域,Leaflet可以用于疫情数据的可视化展示。例如,在新冠疫情期间,Leaflet被广泛应用于疫情数据的可视化展示,以帮助公众更好地了解疫情的传播和分布情况。同时,Leaflet还可以将疫苗接种点的分布数据可视化展示在地图上,以帮助公众查找附近的疫苗接种点和了解疫苗接种进展情况。
OpenLayers
OpenLayers 是一个开源的地图库,用于在 Web 应用中展示交互式地图。它使用 JavaScript 构建,并且支持多种地图数据源,包括 OpenStreetMap、Google Maps、Bing Maps 等。OpenLayers 提供了丰富的地图功能和交互性,使开发者能够在网页中轻松集成地图,并实现各种地理信息展示和交互。
在招聘市场中,OpenLayers的地位也是不可小觑的,能够帮助开发者使网页程序拥有强大的地图功能,用于实施各种项目,包括地理空间搜索、室内分析、地图影像分析和动画模拟等。例如,使用OpenLayers,开发者可以创建支持多个空间图层的互动Web应用程序,可以显示不同底图和支持多种地图操作,比如缩放和平移。此外,开发者还可以在其中添加自定义内容,如文字标签和街景,使Web地图更加完整和生动。
Mapbox
mapbox是一个开源的地图类库,通过使用mapbox的类库,可以很方便的构建web、app等地图应用,支持的地图sdk有web、ios、Android和Unity。
mapbox gl js是mapbox地图的一部分,使用了webgl技术渲染地图上的一些酷炫的效果。
网址:docs.mapbox.com/mapbox-gl-j...
mapbox gl要使用mapbox在线的一些资源,所以,要申请开发者的key才能进行开发使用。
mapbox gl包括了二维三维地图的交互,三维地图是在平面地图的基础上进行立体展示,三维模型是简单的颜色形状渲染,能够基于geojson数据进行渲染,渲染的数据量还是挺可观的,并可以进行数据的交互。
Cesium
Cesium是一个用于创建三维地球和地图应用程序的JavaScript库。它利用WebGL技术实现高性能的地球渲染,为开发者提供了强大的地理空间分析和可视化功能。Cesium不仅支持地球表面的三维渲染,还可以展示地球上的各种数据,如卫星轨道、地质信息等。借助Cesium,开发者可以在Web浏览器中实现惊人的三维地球应用
Cesium目前的功能: 3D地球可视化漫游和导航地形和影像数据3D建筑模型3D TilesCZML实时位置追踪地下和空中场景天文数据集成其他GIS工具
平面:Leaflet,OpenLayers
3D:Mapbox,Cesium
以OpenLayers为例
OpenLayer中的基本对象结构
Map:地图容器,通过target指定地图绘制的容器id,如代码中的map;
Layer:图层,map拥有1个获多个图层,可以理解成PS绘图中的图层概念,整个map是由一个个图层堆叠出来的;
View:可视区域,这个类主要是控制地图与人的交互,如进行缩放,调节分辨率、地图的旋转等控制。同时可以设置投影,默认为球形墨卡托,代码中olProj.fromLonLat方法也是将经纬度转换成对应的坐标,这块不做拓展,有需要的同学可自行去学习GIS的理论。
source:数据来源,即图层Layers的数据组成部分,上文代码中TileLayer就是使用了一个高德地图XYZ格式的切片数据绘制而成,
三、具体实现
本项目基于vue开发
定义瓦片图资源,以天地图为例
js
typeMapping: {
img: 'http://t{0-7}.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=',
cia: 'http://t{0-7}.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=',
vec: 'http://t{0-7}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=',
cva: 'http://t{0-7}.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk='
},
js
// 添加地图层
plugins?.forEach((e) => {
layers.push(
new TileLayer({
title: '****图',
id: `${e}-mapLayer`,
className: `${e}-mapLayer`,//增加className属性
source: new XYZ({
wrapX: true,
url: `${this.typeMapping[e]}${key}`,
})
})
)
})
保存不同的图层便于后期操作
js
this.markerSource = new VectorSource({ id: 'clusterMarker' });
this.regionSource = new VectorSource({ id: 'region' });
OpenLayers点聚合使用聚合类Cluster
官方文档:openlayers.org/en/v6.15.1/...
使用Cluster类来添加Marker点
js
try {
let features = []
PointData.forEach((e, i) => {
const feature = new Feature({
type: 'Point',
id: e.id || `clusterMarker${i}`,
geometry: new Point(e.position),
item: e,
image: e.content.src,
style: new VectorStyle({
image: new Icon(e.content),
id: e.id || `clusterMarker${i}`,
geometryName: e.geometryName || `clusterMarker${i}`,
})
});
features.push(feature)
})
this.markerSource.addFeatures(features)
let clusterStrategy = new Cluster({
distance: parseInt(40, 10),
minDistance: 20,
})
clusterStrategy.setSource(this.markerSource)
this.geometryLayer.setSource(clusterStrategy)
} catch (err) {
console.error('点聚合生成错误', err)
}
在 new VectorLayer 中styl实现聚合点不同的动态展示逻辑
js
// 生成标记点图层
layers.push(this.geometryLayer = new VectorLayer({
id: `geometryLayer`,
className: `geometryLayer`,
zIndex: 999,
source: this.markerSource,
style: (feature) => {
let size = feature.get('features')?.length || 1;
let moreIconMap = new Map
let moreIcon = { key: '', value: 0 }
let style
if (size > 1) {
feature.get('features').forEach(e => {
try {
let iconPath = ****.png`)
if (moreIconMap.has(iconPath)) {
moreIconMap.set(iconPath, moreIconMap.get(iconPath) + 1)
} else {
moreIconMap.set(iconPath, 1)
}
}catch(err){
console.error('图片读取错误',err)
}
})
moreIconMap.forEach((value, key) => {
if (moreIcon.value < value) {
moreIcon.value = value
moreIcon.key = key
}
})
// 计算出现最多的图标
style = new VectorStyle({
image: new Icon({
src: moreIcon.key,
scale: 0.8,
}),
text: new Text({
font: 'bold 1rem myFont ',
offsetY: -39,
offsetX: 26.9,
text: size.toString() <= 99?size.toString():'99+',
fill: new Fill({
color: '#fff',
})
})
});
return style;
} else {
return feature.get('features')[0].values_.style
}
}
}))
如果需要使用国标2000 需要 使用proj4 自定义添加
projection = "EPSG:4326"
js
import proj4 from 'proj4';
proj4.defs(
"EPSG:4490",
'GEOGCS["China Geodetic Coordinate System 2000",DATUM["China_2000",SPHEROID["CGCS2000",6378137,298.257222101,AUTHORITY["EPSG","1024"]],AUTHORITY["EPSG","1043"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4490"]]'
);
register(proj4);