前端基于shp地图数据生成路径点地图
一般省级市级地图数据我们可以通过各种地图工具较为轻易的提取,但如果涉及到乡镇级的地图,通常来讲保密程度会比较高,地图工具不会直观的提供给你,而网上提供的多为shp格式的地图数据,这里我们可以使用一个mapshaper这个工具网站将shp格式转化为我们需要的json
导出的json一般为如下格式
json
{
"type": "GeometryCollection",
"geometries": [
{
"type": "Polygon",
"coordinates": [
[
[116.64977017, 28.96650577],
[116.65436517, 28.96539679],
...
]
]
},
{
"type": "Polygon",
"coordinates": [
[
[116.77645317, 29.41624014],
[116.77658917, 29.41628714],
...
]
]
}
...
]
}这个格式无法被echart的map类型图表直接使用,我们需要将数据重新格式化,生成下方的格式
json
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "鄱阳镇"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[116.64977017, 28.96650577],
[116.65436517, 28.96539679],
...
]
]
}
},
{
"type": "Feature",
"properties": {
"name": "凰岗镇"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[116.77645317, 29.41624014],
[116.77658917, 29.41628714],
...
]
]
}
},
]
}我们将新的json数据导入echart,就生成了一张乡镇级别精度的地图
javascript
<template>
<div class="map-container" ref="mapContainer"></div>
</template>
<script>
import * as echarts from 'echarts';
import geoJson from '@/assets/map/poyang.json';
export default {
mounted() {
this.initMap();
},
methods: {
initMap() {
// 创建地图实例
const mapContainer = this.$refs.mapContainer;
const chart = echarts.init(mapContainer);
echarts.registerMap('poyang', geoJson);
// 设置地图配置项
const option = {
geo: {
map: 'poyang',
show: true,
roam: true, // 地图是否支持缩放和平移
center: [116.78284549760457, 29.230851059087044],
zoom: 1, //当前视角缩放比例
label: {
normal: { // 文字的默认样式
show: true,
textStyle: {
color: '#fff'
}
},
emphasis: { // 文字的激活样式
show: true,
textStyle: {
color: '#fff'
}
}
},
itemStyle: {
normal: { // 地图区域的默认样式
areaColor: '#3a7fd5',
borderColor: '#0a53e9', //线
shadowColor: '#092f8f', //外发光
shadowBlur: 20
},
emphasis: { // 地图区域的激活样式
areaColor: '#0a2dae' //悬浮区背景
}
}
}
};
chart.setOption(option);
}
}
};
</script>
<style scoped>
.map-container {
width: 100%;
height: 100%;
}
</style>效果如下图:

如果你的需求只是生成一张这样的平面图的话,那到这里就已经完成了
但有的时候需求会要求设计出一些视觉效果更为复杂,或是对地图进行一些旋转/倾斜视角等变化,echart就无法满足这类效果的实现了
我们需要将这张地图进行处理,生成UI可以直接转化为路径点的图片
首先我们去掉背景、每个区域的边界颜色、文字等要素,同时给每个区域添加对比度比较强的填充,生成新的echart地图
javascript
// 设置地图配置项
const option = {
geo: {
map: 'poyang',
show: true,
roam: true, // 地图是否支持缩放和平移
center: [116.78284549760457, 29.230851059087044],
zoom: 1, // 当前视角缩放比例
itemStyle: {
normal: {
borderColor: 'transparent' // 线
}
}
},
regions: [
{ name: '鄱阳镇', itemStyle: { areaColor: '#673ab7' } },
{ name: '谢家滩镇', itemStyle: { areaColor: '#f00' } },
{ name: '石门街镇', itemStyle: { areaColor: '#00f' } },
{ name: '四十里街镇', itemStyle: { areaColor: '#0ff' } },
{ name: '油墩街镇', itemStyle: { areaColor: '#f0f' } },
{ name: '田畈街镇', itemStyle: { areaColor: '#ff9800' } },
{ name: '金盘岭镇', itemStyle: { areaColor: '#0f0' } },
{ name: '高家岭镇', itemStyle: { areaColor: '#f00' } },
{ name: '凰岗镇', itemStyle: { areaColor: '#00f' } },
{ name: '双港镇', itemStyle: { areaColor: '#ff9800' } },
{ name: '古县渡镇', itemStyle: { areaColor: '#ff9800' } },
{ name: '饶丰镇', itemStyle: { areaColor: '#ff0' } },
{ name: '乐丰镇', itemStyle: { areaColor: '#0f0' } },
{ name: '饶埠镇', itemStyle: { areaColor: '#f00' } },
{ name: '侯家岗乡', itemStyle: { areaColor: '#00f00f' } },
{ name: '莲花山乡', itemStyle: { areaColor: '#0ff' } },
{ name: '响水滩乡', itemStyle: { areaColor: '#ff9800' } },
{ name: '枧田街乡', itemStyle: { areaColor: '#ff0' } },
{ name: '柘港乡', itemStyle: { areaColor: '#0f0' } },
{ name: '鸦鹊湖乡', itemStyle: { areaColor: '#f00' } },
{ name: '银宝湖乡', itemStyle: { areaColor: '#00f' } },
{ name: '游城乡', itemStyle: { areaColor: '#0ff' } },
{ name: '珠湖乡', itemStyle: { areaColor: '#f0f' } },
{ name: '白沙洲乡', itemStyle: { areaColor: '#ff0' } },
{ name: '团林乡', itemStyle: { areaColor: '#0f0' } },
{ name: '昌洲乡', itemStyle: { areaColor: '#f00' } },
{ name: '庙前乡', itemStyle: { areaColor: '#00f' } },
{ name: '莲湖乡', itemStyle: { areaColor: '#0ff' } },
{ name: '芦田乡', itemStyle: { areaColor: '#f0f' } },
{ name: '农科所', itemStyle: { areaColor: '#ff0' } }
]
}效果如下:

将这张图发给UI,UI通过Adobe AI工具根据每个区域的色值区分范围生成路径点图片,将其导出为svg文件,我们就得到了所需要的路径点path标签的集合
我们使用svg的g加path 标签构建我们的路径点图形,并给图形加上交互样式
g标签是SVG中的分组(group)元素,用于将多个SVG元素进行组合。它仅仅作为一个容器元素,如果你追求代码的简洁,将相关的样式、操作属性绑定在path上也是可以的,但使用g标签整体的维护性和拓展性会更强一些
javascript
<template>
<div class="test-map-container">
<svg viewBox="0 0 596 669">
<!-- 如果有背景图,可以使用最外层g标签的translate属性控制路径点图形组的偏移以匹配背景图 -->
<g transform="translate(-26,-100)">
<g class="mapItem mapPoint" id="响水滩乡">
<path
class="mapPath"
fill="none"
d="M278.6,100.2c0.6,0.4......100.2z"
/>
</g>
<g class="mapItem mapPoint" id="响水滩乡">
<path
class="mapPath"
fill="none"
d="M278.6,100.2......100.2z"
/>
</g>
...
</g>
</svg>
</div>
</template>
<script>
export default {
name: 'Map'
};
</script>
<style scoped lang="less">
.test-map-container {
position: absolute;
margin: auto;
left: 0;
right: 0;
bottom: 0;
top: 0;
width: 596px;
height: 669px;
overflow: hidden;
}
.mapItem {
&.mapPoint {
cursor: pointer;
.mapPath { // 默认样式
fill: rgba(235, 178, 95, 0.2);
stroke: rgba(235, 178, 95, 1);
}
&:hover { // hover效果
.mapPath {
fill: rgba(235, 178, 95, 0.5);
stroke: rgba(235, 178, 95, 1);
}
}
&.selected { // 点击效果
.mapPath {
fill: rgba(235, 178, 95, 1);
stroke: rgba(235, 178, 95, 1);
}
}
}
}
</style>效果如下: 20d2 
我们也可以给路径点添加背景图、路径的阴影效果、点击事件等等,达成更为丰富的效果

参考项目:
最后更新于:2023-07-21