高德百度地图替换方案OpenLayers

一、前言

因为工作需要在使用百度/高德以外实现地图功能。。。。巴拉巴拉。。。。 前文此处省略****字

二、介绍

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);
相关推荐
y先森1 分钟前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy1 分钟前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189114 分钟前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿1 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡2 小时前
commitlint校验git提交信息
前端
虾球xz3 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇3 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒3 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员3 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐3 小时前
前端图像处理(一)
前端