首先是turf.js(英文官网),也有中文网不过也就目录翻译了一下.
高德官网自行获得key
echarts官网
使用turf的isobands
api实现.
数据: 需要准备geojson格式经纬度信息+业务值(比如温度,高度,光照只要是number值什么数据都可以)
国内各地区geojson数据点这里获得
参考的是这位大佬写的内容
主要区别:
- 高德地图版本: 会有详细的路线,地区名称等背景. 但是需要项目允许连接外网或者有本地的地图图块
- echarts版本: 本质是两个或多个geojosn的叠加,背景的详细度取决于的geojson详细度,优点就是需要加载的内容少,无需连接外网
我的实例是以贵州为基础的
业务值 使用的是随机值
高德地图版本
<style scoped lang="scss">
.About{
height: 100%;
width: 100%;
position: relative;
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
}
</style>
<template>
<div class="About">
<div id='map'></div>
</div>
</template>
<script>
import * as turf from '@turf/turf'
import mapData from "../assets/json/guizhougexiancenter.json";
import guizhoulunkuo from "../assets/json/guizhoulunkuo.json";
import { onMounted, ref } from 'vue'
import AmapLoader from '@amap/amap-jsapi-loader'
export default {
name: 'About',
components: {
},
setup () {
console.log('mapData', mapData)
const calculateContourLines = () => {
// 第一步 生成点位
// 计算贵州东南西北最远坐标
var bbox = turf.bbox(guizhoulunkuo); // 数组组合 01 03 21 23
console.log('bbox', bbox)
let coordinates = [
...(mapData.features[0].geometry.coordinates[0][0][0]),
[bbox[0], bbox[1]],
[bbox[2], bbox[1]],
[bbox[2], bbox[3]],
[bbox[0], bbox[3]],
]
// 绑定各经纬度第三个业务值
let centerPositionList = coordinates.map((item, index) => {
return {
type: "Feature",
properties: {
// 这个value就是温度;气温;光照等,除经纬度外影响划分区域的业务值
value: (Math.random() * 100).toFixed(2)
},
geometry: {
type: "Point",
coordinates: item //经纬度
}
}
})
// points为每个点数据
let points = {
type: "FeatureCollection",
features: centerPositionList
}
// 第二步 网格点
let interpolate_options = {
// 点位
gridType: "points",
// property中取那个元素
property: "value",
// 单位
units: "degrees",
// 权重
weight: 10
};
// interpolate中第一是点位数据 第二个是精细度(值越小画的点越多) 配置项
// grid网格点
let grid = turf.interpolate(points, 0.05, interpolate_options);
// value保留两位小数 经过interpolate计算后value会变得很长
grid.features.map((i) => (i.properties.value = i.properties.value.toFixed(2)));
// 第三步 等压线
// 规定样式配置
let isobands_options = {
zProperty: "value",
commonProperties: {
"fill-opacity": 0.8
},
breaksProperties: [
{ fill: "#e3e3ff" },
{ fill: "#c6c6ff" },
{ fill: "#a9aaff" },
{ fill: "#8e8eff" },
{ fill: "#7171ff" },
{ fill: "#5554ff" },
{ fill: "#3939ff" },
{ fill: "#1b1cff" },
{ fill: "#1500ff" }
]
};
// isobands没有经过编辑裁剪 是正方形图层, 是根据网格点,取值范围和样式配置返回等压线(geojson)
let isobands = turf.isobands(
grid,
[1, 10, 20, 30, 50, 70, 80, 90 ,100],
isobands_options
);
// flatten 减少geoJson嵌套层级
guizhoulunkuo = turf.flatten(guizhoulunkuo);
isobands = turf.flatten(isobands);
// console.log('isobands', isobands)
// 第四步 将等压线限制在贵州范围内并生成最终等压线
// 通过intersect判断是否存在交集 来判断是否在贵州范围内
// features存放有交集的点位
let features = [];
isobands.features.forEach(function (layer1) {
guizhoulunkuo.features.forEach(function (layer2) {
let intersection = null;
try {
intersection = turf.intersect(layer1, layer2);
} catch (e) {
layer1 = turf.buffer(layer1, 0);
intersection = turf.intersect(layer1, layer2);
}
if (intersection != null) {
intersection.properties = layer1.properties;
intersection.id = Math.random() * 100000;
features.push(intersection);
}
});
});
// intersection为最终完整图层
let intersection = turf.featureCollection(features);
console.log('intersection', intersection)
// 最后 将数据传入地图
// initMap(points, isobands, intersection)
initGaoDeMap(points, isobands, intersection)
}
const initGaoDeMap = (points, isobands, intersection) => {
// 可视化及交互部分
AmapLoader.load({
key:"高德地图key", // key
version:"2.0",
plugins:['AMap.DistrictSearch', 'AMap.GeoJSON'], // 需要使用的的插件列表
}).then((AMap) => {
const district = new AMap.DistrictSearch({subdistrict:2,extensions:'all',level:'province'});
district.search('贵州',function(status, result){
const bounds = result.districtList[0].boundaries
const mask = []
for (let i=0;i<bounds.length;i++){
mask.push([bounds[i]])
}
const map = new AMap.Map("map",{ // 设置地图容器id
mask: mask,
zoom:8, // 设置当前显示级别
expandZoomRange:true, // 开启显示范围设置
zooms: [7, 20], //最小显示级别为7,最大显示级别为20
center:[106.629577,26.684338], // 设置地图中心点位置
zoomEnable:true, // 是否可以缩放地图
resizeEnable:true,
});
// 添加描边
for (let i=0;i<bounds.length; i++) {
const polyline = new AMap.Polyline({
path:bounds[i], // polyline 路径,支持 lineString 和 MultiLineString
})
polyline.setMap(map);
}
loadGeoJson(AMap,map)
})
}).catch(e=>{
console.log(e);
})
const loadGeoJson = (AMap, map) => {
var geojson = new AMap.GeoJSON({
geoJSON: intersection,
getPolygon: function(geojson, lnglats) {
return new AMap.Polygon({
path: lnglats,
strokeColor: 'white',
fillColor: geojson.properties.fill,
fillOpacity: geojson.properties['fill-opacity'],
strokeWeight:0,
});
}
});
map.add(geojson)
}
}
onMounted(() => {
calculateContourLines()
})
return {
}
}
}
</script>
echarts版本
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.About{
height: 100%;
width: 100%;
position: relative;
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
}
</style>
<template>
<div class="About">
<div id='map'></div>
</div>
</template>
<script>
import * as turf from '@turf/turf'
import * as echarts from 'echarts'
import mapData from "../assets/json/guizhougexiancenter.json";
import guizhoulunkuo from "../assets/json/guizhoulunkuo.json";
import { onMounted, ref } from 'vue'
export default {
name: 'About',
components: {
},
setup () {
console.log('mapData', mapData)
const calculateContourLines = () => {
// 第一步 生成点位
// 计算贵州东南西北最远坐标
var bbox = turf.bbox(guizhoulunkuo); // 数组组合 01 03 21 23
console.log('bbox', bbox)
let coordinates = [
...(mapData.features[0].geometry.coordinates[0][0][0]),
[bbox[0], bbox[1]],
[bbox[2], bbox[1]],
[bbox[2], bbox[3]],
[bbox[0], bbox[3]],
]
// 绑定各经纬度第三个业务值
let centerPositionList = coordinates.map((item, index) => {
return {
type: "Feature",
properties: {
// 这个value就是温度;气温;光照等,除经纬度外影响划分区域的业务值
value: (Math.random() * 100).toFixed(2)
},
geometry: {
type: "Point",
coordinates: item //经纬度
}
}
})
// points为每个点数据
let points = {
type: "FeatureCollection",
features: centerPositionList
}
// 第二步 网格点
let interpolate_options = {
// 点位
gridType: "points",
// property中取那个元素
property: "value",
// 单位
units: "degrees",
// 权重
weight: 10
};
// interpolate中第一是点位数据 第二个是精细度(值越小画的点越多) 配置项
// grid网格点
let grid = turf.interpolate(points, 0.05, interpolate_options);
// value保留两位小数 经过interpolate计算后value会变得很长
grid.features.map((i) => (i.properties.value = i.properties.value.toFixed(2)));
// 第三步 等压线
// 规定样式配置
// 晴:#FEE715 多云:#B0D5FF 阴:#7B8B8E
// 小雨:#A6A6A6 中雨:#585858 大雨:#37618E 暴雨:#37618E 大暴雨:#365569 特大暴雨:#2F3640 小冻雨:#6F8FA6 中冻雨:#577189 大冻雨:#476381
// 小雪:#C6E2FF 中雪:#A2C5E0 大雪:#7C98B3 暴雪:#6284A0 大暴雪:#517394 特大暴雪:#3C6079 小雨夹雪:#6A8BAA 中雨夹雪:#4F6E8A 大雨夹雪:#37618E
let isobands_options = {
zProperty: "value",
commonProperties: {
"fill-opacity": 0.8
},
breaksProperties: [
{ fill: "#e3e3ff" },
{ fill: "#c6c6ff" },
{ fill: "#a9aaff" },
{ fill: "#8e8eff" },
{ fill: "#7171ff" },
{ fill: "#5554ff" },
{ fill: "#3939ff" },
{ fill: "#1b1cff" },
{ fill: "#1500ff" }
]
};
// isobands没有经过编辑裁剪 是正方形图层, 是根据网格点,取值范围和样式配置返回等压线(geojson)
let isobands = turf.isobands(
grid,
[1, 10, 20, 30, 50, 70, 80, 90 ,100],
isobands_options
);
// flatten 减少geoJson嵌套层级
guizhoulunkuo = turf.flatten(guizhoulunkuo);
isobands = turf.flatten(isobands);
console.log('isobands', isobands)
// 第四步 将等压线限制在贵州范围内并生成最终等压线
// 通过intersect判断是否存在交集 来判断是否在贵州范围内
// features存放有交集的点位
let features = [];
isobands.features.forEach(function (layer1) {
guizhoulunkuo.features.forEach(function (layer2) {
let intersection = null;
try {
intersection = turf.intersect(layer1, layer2);
} catch (e) {
layer1 = turf.buffer(layer1, 0);
intersection = turf.intersect(layer1, layer2);
}
if (intersection != null) {
layer1.properties.name = layer1.properties.value.split('-')[1]
intersection.properties = layer1.properties;
intersection.id = Math.random() * 100000;
features.push(intersection);
}
});
});
// intersection为最终完整图层
let intersection = turf.featureCollection(features);
console.log('intersection', intersection)
// 最后 将数据传入Echarts
initEcharts(points, isobands, intersection)
}
const initEcharts = (points, isobands, intersection) => {
let mapChart = echarts.init(document.getElementById("map"));
echarts.registerMap("guizhoulunkuo", { geoJSON: guizhoulunkuo });
echarts.registerMap('guiyangqiwen', { geoJSON: intersection });
let option = {
backgroundColor: "#091c3d",
series: [
{
type: "map",
map: 'guizhoulunkuo',
zlevel: 0,
silent:true, // 不响应鼠标事件
label: {
normal: {
show: true,
textStyle: {
color: "#fff",
fontSize: 15,
fontWeight: 500,
},
},
emphasis: {
textStyle: {
color: "rgb(183,185,14)",
},
},
},
itemStyle: {
normal: {
areaColor: "#2b93b9",
borderColor: "white",
borderWidth: 2,
shadowColor: "#2b93b9",
shadowBlur: 35,
},
},
},
{
type: 'map',
map: 'guiyangqiwen',
zlevel: 1,
emphasis: {
label: {
color: "#fff",
},
itemStyle: {
areaColor: "#1b1cff",
},
},
itemStyle: {
opacity: 0.6,
areaColor: '#c6c6ff',
borderWidth: 0
},
data: [
{
name: "10",
itemStyle: {
areaColor: '#e3e3ff'
},
},
{
name: "20",
itemStyle: {
areaColor: '#c6c6ff'
}
},
{
name: "30",
itemStyle: {
areaColor: '#a9aaff'
}
},
{
name: "40",
itemStyle: {
areaColor: '#a9aaff'
}
},
{
name: "50",
itemStyle: {
areaColor: '#8e8eff'
}
},
{
name: "60",
itemStyle: {
areaColor: '#7171ff'
}
},
{
name: "70",
itemStyle: {
areaColor: '#5554ff'
}
},
{
name: "80",
itemStyle: {
areaColor: '#3939ff'
}
},
{
name: "90",
itemStyle: {
areaColor: '#1b1cff'
}
},
{
name: "100",
itemStyle: {
areaColor: '#1500ff'
}
},
]
},
],
};
mapChart.setOption(option, true);
}
onMounted(() => {
calculateContourLines()
})
return {
}
}
}
</script>
guizhoulunkuo.json
是贵州轮廓通过我最上面获得geojson的网站获取
guizhougexiancenter.json
贵州各县中心点geojosn
// guizhougexiancenter.json
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"adcode": 520000,
"name": "贵州省",
"center": [
106.713478,
26.578343
],
"centroid": [
106.880455,
26.826368
],
"childrenNum": 9,
"level": "province",
"acroutes": [
100000
],
"parent": {
"adcode": 100000
}
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
[
[
[
106.943784,
27.694395
],
[
106.937265,
27.706626
],
[
106.831668,
27.535288
],
[
106.826591,
28.131559
],
[
107.191024,
27.951342
],
[
107.441872,
28.550337
],
[
107.605342,
28.880088
],
[
107.887857,
28.521567
],
[
107.722021,
27.960858
],
[
107.485723,
27.765839
],
[
107.892566,
27.221552
],
[
106.200954,
28.327826
],
[
105.698116,
28.587057
],
[
106.412476,
27.803377
],
[
109.192117,
27.718745
],
[
109.21199,
27.51903
],
[
108.848427,
27.691904
],
[
108.917882,
27.238024
],
[
108.229854,
27.519386
],
[
108.255827,
27.941331
],
[
108.405517,
27.997976
],
[
108.117317,
28.26094
],
[
108.495746,
28.560487
],
[
109.202627,
28.165419
],
[
107.977541,
26.582964
],
[
107.901337,
26.896973
],
[
108.12678,
27.034657
],
[
108.681121,
26.959884
],
[
108.423656,
27.050233
],
[
108.816459,
27.173244
],
[
109.212798,
26.909684
],
[
109.20252,
26.680625
],
[
108.440499,
26.727349
],
[
108.314637,
26.669138
],
[
109.136504,
26.230636
],
[
108.521026,
25.931085
],
[
108.912648,
25.747058
],
[
108.079613,
26.381027
],
[
107.593172,
26.494803
],
[
107.794808,
26.199497
],
[
107.517021,
26.258205
],
[
107.513508,
26.702508
],
[
107.8838,
25.412239
],
[
107.233588,
26.580807
],
[
107.478417,
27.066339
],
[
107.542757,
25.826283
],
[
107.32405,
25.831803
],
[
106.750006,
25.429894
],
[
106.447376,
26.022116
],
[
106.977733,
26.448809
],
[
106.657848,
26.128637
],
[
107.87747,
25.985183
],
[
106.715963,
26.573743
],
[
106.713397,
26.58301
],
[
106.670791,
26.410464
],
[
106.762123,
26.630928
],
[
106.633037,
26.676849
],
[
106.626323,
26.646358
],
[
106.969438,
27.056793
],
[
106.737693,
27.092665
],
[
106.599218,
26.840672
],
[
106.470278,
26.551289
],
[
105.946169,
26.248323
],
[
106.259942,
26.40608
],
[
105.745609,
26.305794
],
[
105.768656,
26.056096
],
[
105.618454,
25.944248
],
[
106.084515,
25.751567
],
[
104.897982,
25.088599
],
[
105.192778,
25.431378
],
[
104.955347,
25.786404
],
[
105.218773,
25.832881
],
[
105.650133,
25.385752
],
[
106.091563,
25.166667
],
[
105.81241,
24.983338
],
[
105.471498,
25.108959
],
[
104.846244,
26.584805
],
[
105.474235,
26.210662
],
[
104.95685,
26.540478
],
[
104.468367,
25.706966
],
[
105.284852,
27.302085
],
[
105.609254,
27.143521
],
[
106.038299,
27.024923
],
[
106.222103,
27.459693
],
[
105.768997,
26.668497
],
[
105.375322,
26.769875
],
[
104.286523,
26.859099
],
[
104.726438,
27.119243
]
]
]
]
]
}
}
]
}