高德百度地图替换方案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);
相关推荐
qiyi.sky4 分钟前
JavaWeb——Vue组件库Element(3/6):常见组件:Dialog对话框、Form表单(介绍、使用、实际效果)
前端·javascript·vue.js
煸橙干儿~~8 分钟前
分析JS Crash(进程崩溃)
java·前端·javascript
安冬的码畜日常17 分钟前
【D3.js in Action 3 精译_027】3.4 让 D3 数据适应屏幕(下)—— D3 分段比例尺的用法
前端·javascript·信息可视化·数据可视化·d3.js·d3比例尺·分段比例尺
l1x1n01 小时前
No.3 笔记 | Web安全基础:Web1.0 - 3.0 发展史
前端·http·html
昨天;明天。今天。1 小时前
案例-任务清单
前端·javascript·css
zqx_72 小时前
随记 前端框架React的初步认识
前端·react.js·前端框架
惜.己2 小时前
javaScript基础(8个案例+代码+效果图)
开发语言·前端·javascript·vscode·css3·html5
什么鬼昵称3 小时前
Pikachu-csrf-CSRF(get)
前端·csrf
长天一色3 小时前
【ECMAScript 从入门到进阶教程】第三部分:高级主题(高级函数与范式,元编程,正则表达式,性能优化)
服务器·开发语言·前端·javascript·性能优化·ecmascript
NiNg_1_2343 小时前
npm、yarn、pnpm之间的区别
前端·npm·node.js