地图开发

lishihuan大约 11 分钟

地图开发

发布离线地图的多个方法 :https://blog.csdn.net/u014220146/article/details/125012813open in new window

坐标转换工具:https://www.opengps.cn/Map/offset/offset.aspxopen in new window

待整理VUE3-Cesium:https://blog.csdn.net/damadashen/article/details/125354344open in new window

公司: 谷歌地图:31.9344120986,117.2649120808 GCJ-02(火星坐标系) 百度地图:31.9405040000,117.2714210000 腾讯高德:31.9344119085,117.2649256012 GCJ-02(火星坐标系) 图吧地图:31.9378224285,117.2620342812 谷歌地球:31.9364424285,117.2594242812 WGS84坐标系 (奥维地图采集的也是 WGS84坐标系 ) 北纬N31°56′11.19″ 东经E117°15′33.93″

坐标转换

coordtransform 转换用法

coordtransform.js

  • 下载coordtransform

    cnpm i -S coordtransform   
    
  • 引入

    import coordtransform from 'coordtransform';
    

Turf.js中文网 地理空间分析库,处理各种地图算法

Turf.js中文网

1.当前互联网地图的坐标系现状

腾讯、高德是GCJ02坐标系【国标】,百度是BD09坐标系,谷歌、必应是WGS84坐标系,天地图是CGCS2000坐标系,瓦片地图都是平面墨卡托投影。WGS84和CGCS2000坐标系,近似认为它们相等就可以了。

地球坐标 (WGS84)

WGS84 是为 GPS 全球定位系统建立的坐标系统,是世界上第一个统一的地心坐标系,因此也被称为大地坐标系、原始坐标系。一般通过 GPS 记录仪记录下来的经纬度,就是基于 WGS84 坐标系的数据。Google 和高德地图定位的的经纬度(国外)都是基于WGS84坐标系的;但是在国内是不允许直接用 WGS84 坐标系标注的,必须经过加密后才能使用 【不是获取不到,比如奥维地图 就能采集到WGS84 坐标系的数据】

  • 国际标准,从 GPS 设备中取出的数据的坐标系

  • 国际地图提供商使用的坐标系

    谷歌地球 osm、谷歌、arcgisonline

火星坐标 (GCJ-02)也叫国测局坐标系

  • 中国标准,从国行移动设备中定位获取的坐标数据使用这个坐标系

  • 国家规定: 国内出版的各种地图系统(包括电子形式),必须至少采用GCJ-02对地理位置进行首次加密。

    腾讯(搜搜)地图、阿里云地图、Google和高德(国内)都是使用 GCJ02 坐标系

百度坐标 (BD-09)

  • 百度标准,百度 SDK,百度地图,Geocoding 使用
  • 在火星坐标上来个二次加密

天地图

天地图采用的是CGCS-2000坐标系(2000坐标系),但是因为CGCS-2000坐标系它与WGS84坐标系都是地心坐标系,因此两者相差不大。况且,考虑到EPSG(地图的一种唯一身份标识),天地图在调用初始化的时候,可以申明天地图采用的坐标系的类型为EPSG:4326,也就是最通用的84坐标系,如下图:

const map = new T.Map(id, { projection: "EPSG:4326" });

其他说明

水经注下载的地图,arcgis提供的卫星图是WGS84 ,矢量图等都是 GCJ-02 ,天地图全部 CGCS-2000 可以看作是 WGS84

可以认为天地图和arcgis使用的是WGS84,所以再选择自己发布的底图服务是存在位移的,如果想正常使用,可以将卫星和矢量图都换成同一坐标系下的

  1. 高德地图 (Amap)
    • 使用 GCJ02 坐标系。
  2. 百度地图 (Baidu Maps)
    • 使用 BD-09 坐标系。
  3. GPS
    • 使用 WGS84 坐标系。
  4. 谷歌地图 (Google Maps)
    • 使用 WGS84 坐标系(在中国大陆地区使用 GCJ02)。
  5. 腾讯地图 (Tencent Maps)
    • 使用 GCJ02 坐标系。
  6. 图吧地图 (Mapbar)
    • 使用 GCJ02 坐标系。
  7. 谷歌地球 (Google Earth)
    • 使用 WGS84 坐标系。

底图服务

街道图,卫星图,地形图

https://blog.csdn.net/qq_51424616/article/details/121384481open in new window

WMS、WFS、WMTS服务接口说明

https://blog.csdn.net/Tmraz/article/details/108749365open in new window

地图开发选型

https://blog.csdn.net/QQ98281642/article/details/117514585open in new window

https://blog.csdn.net/gis_witch/article/details/123419231open in new window

https://blog.csdn.net/gis1205/article/details/126299338open in new window

img
img

辅助网站

  1. 在线直观绘制或可视化图形,获取GeoJSON数据。 http://geojson.io/#map=2/20.0/0.0open in new window

  2. 在线转换地图文件,主要包括Shapefile、GeoJSON、TopoJSON、DBF、CSV。 https://mapshaper.org/open in new window

  3. 在线获取行政边界数据 http://datav.aliyun.com/portal/school/atlas/area_selectoropen in new window

    https://hxkj.vip/demo/echartsMap/open in new window

    http://horizon2021.xyz/open in new window (https://zhuanlan.zhihu.com/p/114711062open in new window)

4.GPS,经度,纬度,距离在线计算器

https://www.osgeo.cn/app/s1884open in new window

5.手动画geojson数据的地址:http://geojson.ioopen in new window

https://www.strerr.com/geojson/geojson.htmlopen in new window

https://www.strerr.com/geojson/geojson.htmlopen in new window 编辑 GeoJSON文件 (场景:生成的中国GeoJSON 文件中包含省界,需要去掉,拿到外围)

下载的数据为GCJ-02坐标系数据,需要转换为WGS84坐标系后使用。解决方案有两种: 一种是通过node cli,进行GeoJSON文件转换。

参考:https://github.com/wandergis/coordtransform-cli?spm=a2c4g.11186623.2.6.2ce3d9ef3yN0Osopen in new window

一种是通过数据库脚本,进行GeoJSON文件转换。

java组装GeoJSON格式数据

/**
	 * 根据 类型 组装 GeoJSON 格式数据
	 *
	 * @return
	 */
	public JSONObject createGeoJSONForPointByType(List<MapPointVo> queryList) {
		// 数据分组
		Map<String, List<MapPointVo>> groupMap = Maps.newHashMap();
		for (MapPointVo mapPointVo : queryList) {
			String key = mapPointVo.getSubType();
			//============containsKey是用来判断某个key是否存在
			if (!groupMap.containsKey(key)) { //=====不存在就新new一个map对象,并将此时的设备名称作为key存入。
				groupMap.put(key, Lists.newArrayList());
			}
			groupMap.get(key).add(mapPointVo);
		}

		JSONObject GeoJSONMap = new JSONObject();
		for (String key : groupMap.keySet()) {
			List<MapPointVo> groupArr = groupMap.get(key);
			GeoJSONMap.put(key, createGeoJSONForPoint(groupArr));
		}
		return GeoJSONMap;
	}
	// 返回的是 GeoJSON 中的features 数组 ,其他格式由 前端 更具需要 组装数据
	public JSONArray createGeoJSONForPoint(List<MapPointVo> groupArr) {
//		JSONObject root = new JSONObject();
//		root.put("type","FeatureCollection");
		JSONArray features = new JSONArray();
		for (MapPointVo mapPointVo : groupArr) {
//			JSONObject item = new JSONObject();
//			item.put("type","Feature");
//
//			JSONObject geometry = new JSONObject();
//			geometry.put("type","Point");
//			JSONArray coordinates = new JSONArray();
//			coordinates.add(0,Float.parseFloat(mapPointVo.getLng()));// 经度
//			coordinates.add(1,Float.parseFloat(mapPointVo.getLat()));// 纬度
//			geometry.put("coordinates",coordinates);
//			item.put("geometry",geometry);
			JSONObject properties = new JSONObject();// 存储 参数
			properties.put("id", mapPointVo.getId());
			properties.put("name", mapPointVo.getName());
			properties.put("labelName", mapPointVo.getLabelName());
			properties.put("type", mapPointVo.getType());
			properties.put("subType", mapPointVo.getSubType());
			properties.put("lng", Float.parseFloat(mapPointVo.getLng()));
			properties.put("lat", Float.parseFloat(mapPointVo.getLat()));
//			item.put("properties",properties);

			String itemStr = " { 'type': 'Feature'," +
					"      'geometry': {'type': 'Point', 'coordinates': [" + Float.parseFloat(mapPointVo.getLng()) + ',' + Float.parseFloat(mapPointVo.getLat()) + "]}," +
					"      'properties': " + properties.toString() +
					" }";

			JSONObject item = JSONObject.fromObject(itemStr);
			features.add(item);
		}
		//root.put("features",features);
		return features;
	}

坐标获取

https://cloud.tencent.com/developer/article/2220490open in new window

奥维地图apk

奥维地图 获取2个坐标

  • 第一个是wgs84 【经纬度】-- 不区分国内国外,标准的经纬度
  • 第二个是 火星坐标系【高德坐标系/国标】
image-20251011150545728
image-20251011150545728

H5通过原生定位

需要通过https

navigator.geolocation.getCurrentPosition(pos => {
  console.log('GPS坐标:', pos.coords.latitude, pos.coords.longitude);
}, error => console.error('用户拒绝授权或定位失败'));

纯IP定位(无需HTTPS)

  • 实现原理:通过客户端IP地址调用第三方接口解析地理位置(城市级精度,误差1-10公里)。
  • 示例代码(天地图API):
fetch('http://api.tianditu.gov.cn/geocoder?ds={"keyWord":"IP定位"}&tk=YOUR_KEY')
  .then(response => response.json())
  .then(data => console.log(data.location));
  • 优势:无需用户授权,兼容性强
  • 限制:仅适合粗略位置需求(如地域统计)。

通过IP地址查询位置信息

fetch('http://ip-api.com/json/你的IP?fields=61439&lang=zh-CN')
  .then(res => res.json())
  .then(data => console.log(data.lat, data.lon));

1. ip-api.comopen in new window

  • 请求示例

    JavaScriptfetch('http://ip-api.com/json/你的IP?fields=status,lat,lon&lang=zh-CN')
      .then(res => res.json())
      .then(data => console.log(data.lat, data.lon))
    

    特性

    • 支持HTTP协议,返回字段lat(纬度)、lon(经度)
    • 免费版每分钟45次请求,误差约城市级(1-10公里)。

2. ip2location.ioopen in new window

  • 请求示例

    JavaScriptfetch('https://api.ip2location.io/?key=YOUR_KEY&ip=IP地址')
      .then(res => res.json())
      .then(data => console.log(data.latitude, data.longitude))
    

    特性

    • 返回字段latitude/longitude 需注册免费API密钥
    • 支持HTTP/HTTPS,精度与ip-api类似。

IP 数据云

IP 数据云支持全球IP 定位,速度快,免费 1000次/日

官网地址:https://www.ipdatacloud.com/open in new window

API 使用方法

代码语言:javascript

https://api.ipdatacloud.com/v2/query?ip={待查询 IP}&key={用户 Key}

调用示例:

https://api.ipdatacloud.com/v2/query?ip=101.88.133.75&key=xxxxxxxxxxxx-->{"code":200,"data":{"area_code":"310100","city":"上海","city_code":"021","continent":"亚洲","country":"中国","country_code":"CN","country_english":"","district":"","elevation":"15","ip":"101.88.133.75","isp":"电信","latitude":"31.231706","local_time":"2023-01-17 22:56","longitude":"121.472644","province":"上海","street":"","version":"V4","weather_station":"CHXX0116","zip_code":"200000"},"msg":"success"}

速度很快

demo通过 ip-api 查询IP然后通过Ip查询GPS信息

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>公网IP与坐标查询</title>
    <style>
        #result { padding: 20px; margin: 20px; border: 1px solid #ccc; }
        button { padding: 10px; background: #007bff; color: white; border: none; cursor: pointer; }
    </style>
</head>
<body>
    <button onclick="getIP()">点击获取公网IP和坐标</button>
    <div id="result">等待数据...</div>

    <script>
        // 可替换的API列表(按优先级排序)
        const API_LIST = [
            'http://ip-api.com/json/?fields=61439&lang=zh-CN', // 综合数据API
            'https://api.seeip.org/jsonip?',                    // 备用API1
            'https://ipinfo.io/json'                             // 备用API2
        ];

        async function fetchIP(apiUrl) {
            try {
                const response = await fetch(apiUrl);
                if (!response.ok) throw new Error('API响应异常');
                return await response.json();
            } catch (error) {
                console.warn(`${apiUrl} 请求失败,尝试备用API`);
                return null;
            }
        }

        async function getIP() {
            let result = document.getElementById('result');
            result.innerHTML = '数据加载中...';

            // 顺序尝试API列表
            for (const api of API_LIST) {
                const data = await fetchIP(api);
                if (data) {
                    const output = `
                        <p>公网IP:${data.ip || data.query}</p>
                        <p>经纬度:${data.lat || data.latitude}, ${data.lon || data.longitude}</p>
                        <p>位置:${data.country} ${data.regionName} ${data.city}</p>
                        <p>运营商:${data.isp || data.org}</p>
                    `;
                    result.innerHTML = output;
                    return;
                }
            }
            
            result.innerHTML = '所有API均请求失败,请稍后重试或检查网络';
        }
    </script>
</body>
</html>

EPSG:3857 和 EPSG:4326

坐标投影选择 : WGS84 Web墨卡托投影(EPSG:3857)

  • EPSG:4326(WGS84,经纬度)

    • 坐标: [经度, 纬度](单位:度)
    • 范围: 经度 -180~180,纬度 -90~90
    • 用途: 通用标准坐标系,定位、接口、数据库常用
    • 优缺点: 保持真实经纬度;不能直接用于 Web 瓦片切图(非等距,缩放不均匀)
  • EPSG:3857(Web Mercator,Web 墨卡托)

    • 坐标: 平面米(单位:米)
    • 范围: x 约 -20037508~20037508,y 同
    • 用途: Web 地图瓦片的行业标准(Google/OSM/高德/WMTS 常用)
    • 优缺点: 贴图/切片效率高,缩放分辨率规则;高纬度形变大(面积被拉伸)

在 OpenLayers 中怎么用

  • 地图 View 通常用 EPSG:3857(便于加载切片):
new View({ projection: 'EPSG:3857', center: fromLonLat([117.27, 31.88]), zoom: 10 })
  • 经纬度转 Web 墨卡托(4326 -> 3857):
import { fromLonLat } from 'ol/proj'
const xy3857 = fromLonLat([lng, lat]) // 输入经纬度
  • Web 墨卡托转经纬度(3857 -> 4326):
import { toLonLat } from 'ol/proj'
const [lng, lat] = toLonLat([x, y]) // 输出经纬度

选择建议

  • 需要显示瓦片图(WMTS/XYZ)→ 用 EPSG:3857
  • 需要存储/交互真实坐标、对接接口/GIS 数据 → 用 EPSG:4326,渲染时再转换为 3857

如果你计划后续切换到卫星图层(如 ahwx16),继续使用 EPSG:3857 是最佳实践;点、线、面数据可用 4326 存储,渲染前用 fromLonLat 转换即可。

地图瓦片介绍

XYZ瓦片与WMTS瓦片对比总结

1)概述

地图瓦片是将大幅地图切分成小块图片的技术,主要有两种标准:XYZ瓦片(事实标准)和WMTS瓦片(OGC标准)

目前XYZ瓦片 可以配合nginx 直接使用,而WMTS瓦片需要使用GeoServerMapServer 进行部署【本身服务就存在漏洞,在严格情况下可能无法使用】

2) 选型

选择XYZ瓦片的情况:

  • ✅ 简单的地图展示需求
  • 希望部署简单(只需nginx) -- 也是选择XYZ瓦片 的优势
  • ✅ 瓦片数据相对固定
  • ✅ 性能要求高

选择WMTS瓦片的情况:

  • ✅ 需要多种坐标系支持
  • ✅ 需要动态样式切换
  • ✅ 企业级GIS应用
  • ✅ 需要丰富的元数据

3)瓦片生成工具

XYZ瓦片生成:

WMTS瓦片生成:

  • GeoServer - 最常用 【目前被扫除有漏洞】
  • MapServer - 开源选择
  • ArcGIS Server - 商业方案

水经注离线地图下载

https://blog.csdn.net/m0_53584457/article/details/136217224open in new window

image-20251013101211946
image-20251013101211946
image-20250923192344524
image-20250923192344524

水经注的"导出大图、导出瓦片、导出离线包"是第三种导出方式介绍

地图开发触屏双指缩放导致页面变化

1️⃣ 防止浏览器页面缩放 - index.html

<!-- 之前 -->
<meta name="viewport" content="... maximum-scale=1, user-scalable=no">

<!-- 现在 -->
<meta name="viewport" content="... maximum-scale=1, minimum-scale=1, user-scalable=no">
                                                    ↑新增
/* 之前 */
html, body, #app {
  height: 100%;
}

/* 现在 */
html, body, #app {
  height: 100%;
  touch-action: pan-x pan-y;  /* 只允许水平/垂直平移,禁止缩放 */
}

2️⃣ 地图容器特殊处理 - OlMap.vue

.map {
  flex: 1;
  touch-action: none;  /* 地图内触摸完全由OpenLayers接管 */
}

作用分层:

  • 页面级别(html/body):禁止双指缩放页面
  • 地图容器(.map):允许OpenLayers处理触摸(地图平移、缩放)