首先是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 23console.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", // keyversion:"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].boundariesconst mask = []for (let i=0;i<bounds.length;i++){mask.push([bounds[i]])}const map = new AMap.Map("map",{ // 设置地图容器idmask: mask, zoom:8, // 设置当前显示级别expandZoomRange:true, // 开启显示范围设置zooms: [7, 20], //最小显示级别为7,最大显示级别为20center:[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 23console.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 大雨夹雪:#37618Elet 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)// 最后 将数据传入EchartsinitEcharts(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]]]]]}}]
}