重要说明:本意为解析GeoJson数据并配合个人封装的天地图hooks,仅个人记录笔记,仅供参考!天地图API需要对点/线/面单独渲染,因此最终处理格式为以下geoJsonMapFormat格式。
GeoJson格式数据入门说明参考地址:https://zhuanlan.zhihu.com/p/539689986
个人封装天地图hooks参考地址:https://blog.csdn.net/YueMiaoL/article/details/134154384?spm=1001.2014.3001.5502
封装geoJson方法的hooks
useGeoJsonData.js
/**
* 处理geoJson格式数据并能回显至天地图上
**/
export const useGeoJsonData = () => {
let geoJsonData = null // 定义geoJsonData保存geoJson格式数据
// geoJson数据处理为天地图可展示的图形结构,点/线/面分别渲染
const geoJsonMapFormat = {
point: [], // 点数据
line: [], // 线数据
polygon: [] // 面数据
}
// 处理geoJson方法合集
const geoJsonFunList = {
GeometryCollection: {
fun: handleGeometryCollection, // 对应类型处理方法
paramName: 'geometries' // 方法传参
},
MultiPoint: {
fun: handleMultiPoint,
paramName: 'coordinates'
},
Point: {
fun: handlePoint,
paramName: 'coordinates'
},
FeatureCollection: {
fun: handleFeatureCollection,
paramName: 'features'
},
Feature: {
fun: handleFeature,
paramName: undefined
},
MultiLineString: {
fun: handleMultiLineString,
paramName: 'coordinates'
},
LineString: {
fun: handleLineString,
paramName: 'coordinates'
},
MultiPolygon: {
fun: handleMultiPolygon,
paramName: 'coordinates'
},
Polygon: {
fun: handlePolygon,
paramName: 'coordinates'
}
}
// 位置信息
const geoJsonSiteInfo = {
minLng: undefined, // 最小经度
maxLng: undefined, // 最大经度
minLat: undefined, // 最小纬度
maxLat: undefined // 最大纬度
}
// 自定义获取赋予geoJson数据
async function customGetGeoJsonData(data) {
geoJsonData = JSON.parse(JSON.stringify(data))
await handleGeoJsonData(geoJsonData)
return Promise.resolve()
}
// 处理geoJson数据
function handleGeoJsonData(data) {
let typeName = data.type
geoJsonFunList[typeName] && (geoJsonFunList[typeName].paramName ? geoJsonFunList[typeName].fun(data[geoJsonFunList[typeName].paramName]) : geoJsonFunList[typeName].fun(data))
}
// 处理GeometryCollection类型数据
function handleGeometryCollection(data) {
data?.forEach((item) => {
handleGeoJsonData(item)
})
}
// 处理Point类型数据
function handlePoint(data) {
handleSiteInfo(data)
const coordinate = data.join()
geoJsonMapFormat.point.push(coordinate)
}
// 处理FeatureCollection类型数据
function handleFeatureCollection(data) {
data?.forEach((item) => {
handleGeoJsonData(item)
})
}
// 处理MultiPoint类型数据
function handleMultiPoint(data) {
data?.forEach((item) => {
handlePoint(item)
})
}
// 处理Feature类型数据
function handleFeature(data) {
handleGeoJsonData(data.geometry)
}
// 处理MultiLineString类型数据
function handleMultiLineString(data) {
data?.forEach((item) => handleLineString(item))
}
// 处理LineString类型数据
function handleLineString(data) {
// 处理数据格式
const coordinateList = data?.map((item) => {
handleSiteInfo(item)
return {
lng: item[0],
lat: item[1]
}
})
// 添加线
geoJsonMapFormat.line.push(coordinateList)
}
// 处理MultiPolygon类型数据
function handleMultiPolygon(data) {
data?.forEach((item) => {
handlePolygon(item)
})
}
// 处理Polygon类型数据
function handlePolygon(data) {
// 处理数据格式
const coordinateList = data.map((item) => {
return item.map((pointItem) => {
handleSiteInfo(pointItem)
return {
lng: pointItem[0],
lat: pointItem[1]
}
})
})
geoJsonMapFormat.polygon.push(coordinateList)
}
// 处理经纬度最大值及最小值
function handleSiteInfo(site) {
geoJsonSiteInfo.minLng =
geoJsonSiteInfo.minLng != undefined && geoJsonSiteInfo.minLng < site[0] ? geoJsonSiteInfo.minLng : site[0]
geoJsonSiteInfo.maxLng =
geoJsonSiteInfo.maxLng != undefined && geoJsonSiteInfo.maxLng > site[0] ? geoJsonSiteInfo.maxLng : site[0]
geoJsonSiteInfo.minLat =
geoJsonSiteInfo.minLat != undefined && geoJsonSiteInfo.minLat < site[1] ? geoJsonSiteInfo.minLat : site[1]
geoJsonSiteInfo.maxLat =
geoJsonSiteInfo.maxLat != undefined && geoJsonSiteInfo.maxLat > site[1] ? geoJsonSiteInfo.maxLat : site[1]
}
// 图形回显天地图自适应视角算法
function geoJsonToMapAdaptiveAlgorithm() {
return new Promise((resolve, reject) => {
if (
![geoJsonSiteInfo.minLng, geoJsonSiteInfo.maxLng, geoJsonSiteInfo.minLat, geoJsonSiteInfo.maxLat].includes(
undefined
)
) {
// 处理可视化范围及层级
let coordinate = `${(geoJsonSiteInfo.minLng + geoJsonSiteInfo.maxLng) / 2},${(geoJsonSiteInfo.minLat + geoJsonSiteInfo.maxLat) / 2}` // 中心点
const diffArr = [180, 90, 45, 22, 11, 5.5, 2.75, 1.37, 0.68, 0.34, 0.17, 0.08, 0.04]
const diffLng = geoJsonSiteInfo.maxLng - geoJsonSiteInfo.minLng // 经度差
const diffLat = geoJsonSiteInfo.maxLat - geoJsonSiteInfo.minLat // 纬度差
const standardValue =
diffLng < diffLat * 2.1 ? parseInt(10000 * diffLat * 2.1) / 10000 : parseInt(10000 * diffLng) / 10000 // 设立标准值
let index = diffArr.findIndex((item) => {
return standardValue - item >= 0
})
let zoom = index != -1 ? index + 3 : 14 // 获得缩放级别
resolve({
coordinate,
zoom
})
}
reject(false)
})
}
// 重置数据
function resetGeoJsonData() {
geoJsonData = null
for (let key in geoJsonSiteInfo) {
geoJsonSiteInfo[key] = undefined
}
for (let key in geoJsonMapFormat) {
geoJsonMapFormat[key] = []
}
}
return {
geoJsonMapFormat,
customGetGeoJsonData,
geoJsonToMapAdaptiveAlgorithm,
resetGeoJsonData
}
}
需要引入天地图hooks配合使用,使用简单示例:
<template>
<div id="mapId"></div>
</template>
<script setup>
import { useTdtMap } from '@/hooks/useTdtMap'
import { useGeoJsonData } from '@/hooks/useGeoJsonData'
import mockGeoJsonData from '@/mock/data' // 模拟geojson数据
// 地图
const { mapInit, setMapScale, addMapMarker, addMapLine, addMapPolygon } = useTdtMap('mapId')
// geoJson
const { geoJsonMapFormat, customGetGeoJsonData, geoJsonToMapAdaptiveAlgorithm, resetGeoJsonData } = useGeoJsonData()
nextTick(() => {
// 初始化地图
mapInit().then(() => {
// 解析geoJson数据格式
customGetGeoJsonData(mockGeoJsonData).then((res) => {
if(res) {
// 天地图回显该数据
// 点
geoJsonMapFormat.point?.forEach((pointCoordinate) => {
addMapMarker(pointCoordinate)
})
// 线
geoJsonMapFormat.line?.forEach((lineCoordinate) => {
addMapLine(lineCoordinate)
})
// 面
geoJsonMapFormat.polygon?.forEach((polygonCoordinate) => {
addMapPolygon(polygonCoordinate)
})
// 调整自适应地图视角
geoJsonToMapAdaptiveAlgorithm().then((res) => {
let { coordinate, zoom } = res
setMapScale(coordinate, zoom)
})
}
})
})
})
onUnmounted(() => {
// 重置geoJson数据,如果需要其它geoJson数据的自适应地图视角,你则需要重置清空useGeoJsonData里的geoJson数据,否则可能会导致视角不准确
resetGeoJsonData()
})
</script>
图形回显天地图自适应视角算法(geoJsonToMapAdaptiveAlgorithm)说明,该部分可单独拎出去使用,这部分老早之前有参考过其它博主的文章但我找不到来源了,实在愧疚,如果能找到原主,请务必私信我再编辑放链接跳转的!!!
其中本质上是获取geoJson复杂图形中最大/最小经纬度确定图形展示范围和中心点,利用经纬度差值2.1倍进行估算地图展示级别,如果显示不准则根据自行分辨率和情况修“let zoom = index != -1 ? index + 3 : 14”中的3和14,关键代码如下所示:
// 位置信息
const geoJsonSiteInfo = {
minLng: undefined, // 最小经度
maxLng: undefined, // 最大经度
minLat: undefined, // 最小纬度
maxLat: undefined // 最大纬度
}
// 图形回显天地图自适应视角算法
function geoJsonToMapAdaptiveAlgorithm() {
return new Promise((resolve, reject) => {
if (
![geoJsonSiteInfo.minLng, geoJsonSiteInfo.maxLng, geoJsonSiteInfo.minLat, geoJsonSiteInfo.maxLat].includes(undefined)
) {
// 处理可视化范围及层级
let coordinate = `${(geoJsonSiteInfo.minLng + geoJsonSiteInfo.maxLng) / 2},${(geoJsonSiteInfo.minLat + geoJsonSiteInfo.maxLat) / 2}` // 中心点
const diffArr = [180, 90, 45, 22, 11, 5.5, 2.75, 1.37, 0.68, 0.34, 0.17, 0.08, 0.04]
const diffLng = geoJsonSiteInfo.maxLng - geoJsonSiteInfo.minLng // 经度差
const diffLat = geoJsonSiteInfo.maxLat - geoJsonSiteInfo.minLat // 纬度差
const standardValue =
diffLng < diffLat * 2.1 ? parseInt(10000 * diffLat * 2.1) / 10000 : parseInt(10000 * diffLng) / 10000 // 设立标准值
let index = diffArr.findIndex((item) => {
return standardValue - item >= 0
})
let zoom = index != -1 ? index + 3 : 14 // 获得缩放级别
resolve({
coordinate,
zoom
})
}
reject(false)
})
}