vue3+高德地图(或echarts)+turfjs实现等压线,色斑图(用于显示气象,环境等地图场景)

首先是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
                ]
              ]
            ]
          ]
        ]
      }
    }
  ]
}
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值