美文网首页
leaflet地图分级设色

leaflet地图分级设色

作者: 嘀灬学生卡 | 来源:发表于2021-05-27 19:49 被阅读0次

    关键词:leaflet; geojson; wkt; 分级设色; 地图渲染;颜色映射;颜色转换;图例

    案例需求:各省级专题数据分级设色
    数据准备:1.地图数据geojson格式(https://geo.datav.aliyun.com/areas_v2/bound/100000_full.json
    2.专题数据,通过随机数生成

    示例
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>leaflet分层渲染</title>
      <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
      <link href="https://cdn.bootcdn.net/ajax/libs/leaflet/1.7.1/leaflet.min.css" rel="stylesheet">
      <script src="https://cdn.bootcdn.net/ajax/libs/leaflet/1.7.1/leaflet.min.js"></script>
    
      <style>
        body{
          width: calc(100vw);
          height: calc(100vh);
          padding: 0;
          margin: 0;
        }
        .map{
          width: 100%;
          height: 100%;
          background-color: #fff;
        }
        .legend{
          position: absolute;
          right: 20px;
          bottom: 20px;
          z-index: 999;
        }
        .legend ul li{
          padding:0;
          margin:0;
          list-style:none;
          display: flex;
          align-items: center;
          margin-bottom: 5px;
        }
        .legend ul li i{
          display: inline-block;
          width: 20px;
          height: 20px;
          border-radius: 50%;
          margin-right: 5px;
        }
      </style>
    </head>
    <body onload="init()">
      <div id="map" class="map"></div>
      <div class="legend"></div>
    </body>
    <script>
      let map;
      let separatedColors = ['#DAF7A6', '#FFC300', '#FF5733', '#C70039', '#900C3F', '#581845'];//离散颜色
      let minVal = 1;
      let maxVal = 100;
      function init(){
        initMap();
        initLegend();
      }
      function initMap(){
        map = L.map('map', {
          crs: L.CRS.EPSG4326,
          center: [40.83, 113.31],
          zoom: 3,
          zoomControl: true
        });
        let vecUrl = 'http://t0.tianditu.gov.cn/DataServer?T=vec_c&X={x}&Y={y}&L={z}&tk=c04e7575a1f250c6f22ba42fa9c8aa63';
        let baseLayer = L.tileLayer(vecUrl, {zoomOffset: 1});
        map.addLayer(baseLayer)
        let url = 'https://geo.datav.aliyun.com/areas_v2/bound/100000_full.json';
        axios.get(url).then(res => {
          let geojson = res.data;
          L.geoJSON(geojson, {
            onEachFeature: function(feature, layer){
              //生成1-100的随机整数,作为每个要素的某一专题属性值
              feature.properties.value = random(1, 100);
              feature.properties.color = getSeparatedColorByVal(minVal, maxVal, separatedColors, feature.properties.value);
              layer.setStyle({
                stroke: false,//取消边框
                color: feature.properties.color,
                fillOpacity: 0.6//默认0.2
              });
            }
          }).addTo(map);
        });
      }
    
      //初始化图例
      function initLegend(){
        let legend = getLegend(minVal, maxVal, separatedColors);
        let legendDom = document.getElementsByClassName('legend')[0];
        let insertDom = document.createElement('ul');
        let str = ``;
        for(let i = 0; i < legend.length; i++){
          str += `<li><i style="background: ${legend[i].color}"></i>${legend[i].region.join('-')}</li>`;
        }
        insertDom.innerHTML = str;
        legendDom.appendChild(insertDom);
      }
    
      //生成指定范围的随机整数
      function random(min, max) {
        return Math.floor(Math.random() * (max - min)) + min;
      }
      //根据离散颜色及数据范围生成对应值的颜色
      function getSeparatedColorByVal(minVal, maxVal, colors, val){
        let length = colors.length;
        let avg = ((maxVal - minVal)/length).toFixed(4);
        //生成等分区间
        let regions = [];
        for(let i = 0; i < length; i++){
          if(i === length -1){
            regions.push([(minVal + avg * i), maxVal]);
          }else{
            regions.push([(minVal + avg * i), (minVal + avg * (i + 1))]);
          }
        }
        //返回对应值颜色
        for(let i = 0; i < regions.length; i++){
          if(val >= regions[i][0] && val <= regions[i][1]){
            return colors[i];
          }
        }
      }
      
      //生成图例
      function getLegend(minVal, maxVal, colors){
        let length = colors.length;
        let avg = ((maxVal - minVal)/length).toFixed(4);
        //生成等分区间
        let regions = [];
        for(let i = 0; i < length; i++){
          if(i === length -1){
            regions.push([(minVal + avg * i).toFixed(2), maxVal.toFixed(2)]);
          }else{
            regions.push([(minVal + avg * i).toFixed(2), (minVal + avg * (i + 1)).toFixed(2)]);
          }
        }
        let legend = [];
        for(let i = 0; i< length; i++){
          legend.push({
            color: colors[i],
            region: regions[i]
          });
        }
        return legend;
      }
    </script>
    </html>
    
    效果
    渲染效果
    以上使用的离散颜色数组渲染,生成连续颜色可使用如下方法
      //根据数值范围、颜色范围(16进制类型),获取数值范围中某一数值对应颜色范围中的颜色
      //颜色要求:选择相邻色系
      function getContinuationColorByVal(minVal, maxVal, firstColor, secondColor, val){
        let ratio = (val-minVal)/(maxVal - minVal);
        let fArr = hex2RgbArr(firstColor);
        let sArr = hex2RgbArr(secondColor);
        let color = [];
        for(let i = 0; i < fArr.length; i++){
          let c = (fArr[i]<sArr[i]?fArr[i]:sArr[i]) + Math.abs(((sArr[i]-fArr[i])*ratio).toFixed(0));
          color.push(c);
        }
        return rgbArr2Hex(color);
      }
      //16进制颜色转rgb颜色数组
      function hex2RgbArr(hex){
        // 16进制颜色值的正则
        var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
        // 把颜色值变成小写
        var color = hex.toLowerCase();
        if (reg.test(color)) {
          // 如果只有三位的值,需变成六位,如:#fff => #ffffff
          if (color.length === 4) {
            var colorNew = '#';
            for (var i = 1; i < 4; i += 1) {
              colorNew += color.slice(i, i + 1).concat(color.slice(i, i + 1));
            }
            color = colorNew;
          }
          // 处理六位的颜色值,转为RGB
          var colorChange = [];
          for (var i = 1; i < 7; i += 2) {
            colorChange.push(parseInt('0x' + color.slice(i, i + 2)));
          }
          return colorChange;
        }
      }
      //rgb颜色数组[255, 255, 255]转16进制颜色#ffffff
      function rgbArr2Hex(rgbArr){
        let strHex = '#';
        // 转成16进制
        for (var i = 0; i < rgbArr.length; i++) {
          let hex = Number(rgbArr[i]).toString(16);
          hex = hex.length == 1 ? '0' + hex : hex;
          strHex += hex;
        }
        return strHex;
      }
    
    实际开发,地图要素范围数据可能后端返回wkt类型数据,wkt数据转换layer图层,需用leaflet插件leaflet-omnivore
    //wkt转leaflet layer
    wkt2Layer(wktShape) {
      if(!!wktShape){
        var geoJson = omnivore.wkt.parse(wktShape);
        let feature = geoJson.getLayers()[0].feature;
        return L.GeoJSON.geometryToLayer(feature);
       }
    }
    

    参考资料:
    https://blog.csdn.net/mossbaoo/article/details/93484635
    https://htmlcolorcodes.com/zh/yanse-xuanze-qi/
    http://datav.aliyun.com/tools/atlas/#&lat=30.37018632615852&lng=106.68898666525287&zoom=3.5
    https://www.jianshu.com/p/1cbfa0ed2051

    相关文章

      网友评论

          本文标题:leaflet地图分级设色

          本文链接:https://www.haomeiwen.com/subject/ccjdsltx.html