废了九牛二虎之力,总算摸清楚如何将一个黑白的地形tif文件转换为mapbox terrainRGB(地形瓦片)

我编译后放在网盘

地图倾斜

https://zhuanlan.zhihu.com/p/362310397

等高线?

https://codepen.io/shevawen/pen/abOPdJy?editors=1111
Leaflet加turf生成等值线图(或色斑图)并单击显示值
https://blog.csdn.net/cwr888/article/details/124717178
cwr888
已于 2022-08-16 11:41:47 修改
Leaflet加turf生成等值线图(或色斑图)并单击显示值,效果如下图所示:

参考代码如下:

index.html

<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>CodePen - turfjs-interpolate-isoband</title>
  <link rel='stylesheet' href='../leaflet1.2.css'>
  <link rel="stylesheet" href="style.css">

</head>
<body>
<!-- partial:index.partial.html -->
<div id='menu-ui' class='menu-ui'></div>
<div id='map'></div>
<!-- partial -->
  <script src='../turf5.1.6.min.js'></script>
<script src='../leaflet1.2.js'></script>
<script  src="script.js"></script>

</body>
</html>

script.js

let boundaries = {
  type: "FeatureCollection",
  name: "boundaries",
  crs: { type: "name", properties: { name: "urn:ogc:def:crs:OGC:1.3:CRS84" } },
  features: [
    {
      type: "Feature",
      properties: {},
      geometry: {
        type: "MultiPolygon",
        coordinates: [ [ [ [ 110.763, 41.376 ], [ 110.823, 41.381 ], [ 110.815, 41.357 ], [ 110.944, 41.317 ], [ 110.978, 41.346 ], [ 111.026, 41.299 ], [ 111.085, 41.285 ], [ 111.096, 41.306 ], [ 111.232, 41.238 ], [ 111.273, 41.289 ], [ 111.439, 41.327 ], [ 111.724, 41.309 ], [ 111.833, 41.252 ], [ 111.822, 41.216 ], [ 111.862, 41.204 ], [ 111.874, 41.129 ], [ 112.027, 41.046 ], [ 112.011, 41.003 ], [ 112.035, 40.968 ], [ 112.138, 40.938 ], [ 112.178, 40.818 ], [ 112.144, 40.761 ], [ 112.086, 40.738 ], [ 112.124, 40.697 ], [ 112.108, 40.657 ], [ 112.038, 40.654 ], [ 112.092, 40.587 ], [ 112.046, 40.559 ], [ 112.218, 40.448 ], [ 112.259, 40.391 ], [ 112.229, 40.354 ], [ 112.264, 40.356 ], [ 112.305, 40.253 ], [ 111.964, 39.795 ], [ 111.925, 39.611 ], [ 111.829, 39.619 ], [ 111.777, 39.588 ], [ 111.64, 39.643 ], [ 111.511, 39.663 ], [ 111.43, 39.642 ], [ 111.435, 39.67 ], [ 111.358, 39.721 ], [ 111.366, 39.789 ], [ 111.439, 39.896 ], [ 111.405, 40.044 ], [ 111.308, 40.151 ], [ 111.039, 40.27 ], [ 111.024, 40.31 ], [ 111.108, 40.33 ], [ 111.121, 40.382 ], [ 110.953, 40.495 ], [ 110.895, 40.483 ], [ 110.837, 40.534 ], [ 110.874, 40.585 ], [ 110.796, 40.611 ], [ 110.78, 40.79 ], [ 110.705, 40.805 ], [ 110.739, 40.917 ], [ 110.623, 40.941 ], [ 110.672, 41.053 ], [ 110.639, 41.1 ], [ 110.65, 41.164 ], [ 110.554, 41.224 ], [ 110.559, 41.261 ], [ 110.512, 41.291 ], [ 110.547, 41.288 ], [ 110.569, 41.331 ], [ 110.629, 41.31 ], [ 110.719, 41.385 ], [ 110.763, 41.376 ] ] ] ] } }
  ]
};

let points = turf.randomPoint(30, { bbox: turf.bbox(boundaries) });

turf.featureEach(points, function (currentFeature, featureIndex) {
  currentFeature.properties = { value: (Math.random() * 100).toFixed(2) };
});
//console.log(JSON.stringify(points));

var interpolate_options = {
  gridType: "points",
  property: "value",
  units: "degrees",
  weight: 10
};
let grid = turf.interpolate(points, 0.05, interpolate_options);
// 适当降低插值结果的精度便于显示
grid.features.map((i) => (i.properties.value = i.properties.value.toFixed(2)));

var 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"}
  // ]
  breaksProperties: [
    {fill: "rgb(234,234,234)"},
    {fill: "rgb(140,246,130)"},
    {fill: "rgb(0,191,27)"},
    {fill: "rgb(62,185,255)"},
    {fill: "rgb(25,0,235)"},
    {fill: "rgb(255,0,255)"},
    {fill: "rgb(140,0,65)"}
  ]
};
let levelV = [1, 10, 20, 30, 50, 70, 100];
let isobands = turf.isobands(
  grid,
  levelV,
  isobands_options
);
function sortArea(a,b)
{
    return turf.area(b)-turf.area(a);
}
//按照面积对图层进行排序,规避turf的一个bug
isobands.features.sort(sortArea)
//后面使用要求输入的参数为Feature<Polygon> ,而turf.isobands的是 MultiPolygon,需要先 flatten() 处理一下,同时去掉图形为空的记录
boundaries = turf.flatten(boundaries); //行政边界
isobands = turf.flatten(isobands);//等值面边界
//console.log('isobands:'+JSON.stringify(isobands));

//统计图形坐标为顺序针和逆时针的数量
let clockwiseNum = 0; //顺时针图形数量
let notClockwiseNum = 0; //逆时针图形数量
let notClockwisePartNum = 0; //逆时针图形部件数量
let notClockwiseIndex = 0; //逆时针图形序号
isobands.features.forEach(function (feature, index) {
  let partNum = 0; //记录图形部件数
  let haveNotClockwise = false; //记录图形是否带逆时针部件
  feature.geometry.coordinates.forEach(function (coords) {
      let booleanClockwise = turf.booleanClockwise(coords);
      if(booleanClockwise)
        clockwiseNum++;
      else{
        notClockwiseNum++;
      haveNotClockwise = true;
      }
      partNum++;
      console.log('a'+partNum+':'+booleanClockwise);
      //console.log(coords);
  });
  //有逆时针图形时记录逆时针图形部件数量和逆时针图形序号
  if(haveNotClockwise){
    notClockwisePartNum = partNum;
    notClockwiseIndex = index;
  }
  //turf.isobands有点不符合业务预期,只有一个逆时针图形是镂空图形缺少外环的错误问题,写点程序补救下
  if(partNum==1&&haveNotClockwise){
    let coords=[];
      let gridBox = turf.bbox(grid);
      let gridBoxPolygon = [[gridBox[0],gridBox[1]],[gridBox[0],gridBox[3]],[gridBox[2],gridBox[3]],[gridBox[2],gridBox[1]],[gridBox[0],gridBox[1]]];
      coords.push(gridBoxPolygon);
      isobands.features.forEach(function (feature, index) {
        if(index!=notClockwiseIndex){
            feature.geometry.coordinates.forEach(function (item) {
          if(turf.booleanClockwise(coords))
            coords.push(item.reverse());
          else
            coords.push(item);
            });
        }
      });
      isobands.features[notClockwiseIndex].geometry.coordinates=coords;
    if(isobands.features.length==1){ //图层只有一个镂空图形时属性可能不对需要重新赋值
      let maxAttribute = getMaxAttribute(levelV,grid,isobands_options.breaksProperties);
      let value = maxAttribute[0];
      let fill = maxAttribute[1];
      if(value!=''&&fill!=''){
        isobands.features[notClockwiseIndex].properties.value = value;
        isobands.features[notClockwiseIndex].properties.fill = fill;
      }
    }
  }
});

//turf.isobands有点不符合业务预期
// //if(isobands.features.length==2){//只有两个图形的情况下,一个图形包含另一个图形时,大图形缺少外环显示错误,写点程序补救下
// //  if(isobands.features[0].geometry.coordinates.length==1&&isobands.features[1].geometry.coordinates.length==1){
// //    if(turf.booleanClockwise(isobands.features[0].geometry.coordinates[0])){
// //      if(!turf.booleanClockwise(isobands.features[1].geometry.coordinates[0])){
// //          let gridBox = turf.bbox(grid);
// //          let gridBoxPolygon = [[gridBox[0],gridBox[1]],[gridBox[0],gridBox[3]],[gridBox[2],gridBox[3]],[gridBox[2],gridBox[1]],[gridBox[0],gridBox[1]]];
// //          isobands.features[1].geometry.coordinates.unshift(gridBoxPolygon);
// //        }
// //    }
// //    else{
// //        if(turf.booleanClockwise(isobands.features[1].geometry.coordinates[0])){
// //          let gridBox = turf.bbox(grid);
// //          let gridBoxPolygon = [[gridBox[0],gridBox[1]],[gridBox[0],gridBox[3]],[gridBox[2],gridBox[3]],[gridBox[2],gridBox[1]],[gridBox[0],gridBox[1]]];
// //          isobands.features[0].geometry.coordinates.unshift(gridBoxPolygon);
// //      }
// //    }
// //  }
// //}
// //else{
//   if(notClockwiseNum==1&&notClockwisePartNum==1){//有些镂空图形缺少外环显示错误,写点程序补救下
//       let coords=[];
//       let gridBox = turf.bbox(grid);
//       let gridBoxPolygon = [[gridBox[0],gridBox[1]],[gridBox[0],gridBox[3]],[gridBox[2],gridBox[3]],[gridBox[2],gridBox[1]],[gridBox[0],gridBox[1]]];
//       coords.push(gridBoxPolygon);
//       isobands.features.forEach(function (feature, index) {
//         if(index!=notClockwiseIndex){
//           feature.geometry.coordinates.forEach(function (item) {
//             coords.push(item.reverse());
//           });
//         }
//       });
//       isobands.features[notClockwiseIndex].geometry.coordinates=coords;
//     if(isobands.features.length==1){ //图层只有一个镂空图形时属性可能不对需要重新赋值
//      let maxAttribute = getMaxAttribute(levelV,grid,isobands_options.breaksProperties);
//      let value = maxAttribute[0];
//      let fill = maxAttribute[1];
//      if(value!=''&&fill!=''){
//        isobands.features[notClockwiseIndex].properties.value = value;
//        isobands.features[notClockwiseIndex].properties.fill = fill;
//      }
//     }
//   }
// //}

//根据行政边界裁剪图形
let features = [];//裁剪后的结果集
isobands.features.forEach(function (feature1) {
  boundaries.features.forEach(function (feature2) {
    let intersection = null;
    try {
      intersection = turf.intersect(feature1, feature2);
    } catch (e) {
      try{
          //色斑图绘制之后,可能会生成一些非法 Polygon ,例如 在 hole 里存在一些形状(听不懂?去查一下 GeoJSON 的规范),
          //我遇到的一个意外情况大概是这样,这种 Polygon 在做 intersect() 操作的时候会报错,所以在代码中做了个容错操作。
          //解决的方法通常就是做一次 turf.buffer() 操作,这样可以把一些小的碎片 Polygon 清理掉。
        feature1 = turf.buffer(feature1, 0);
        intersection = turf.intersect(feature1, feature2);
      } catch (e) {
          intersection = feature1;//实在裁剪不了就不裁剪了,根据业务需求自行决定
      }
    }
    if (intersection != null) {
      intersection.properties = feature1.properties;
      intersection.id = (Math.random() * 100000).toFixed(0);
      features.push(intersection);
    }
  });
});

//turf.isobands有点不符合业务预期,只有一个等级时,结果集可能为空,无图形显示,写点程序(找出那一个等级,并添加进结果集)补救下
if(features.length == 0){
  let maxAttribute = getMaxAttribute(levelV,grid,isobands_options.breaksProperties);
    let value = maxAttribute[0];
    let fill = maxAttribute[1];
  if(value!=''&&fill!=''){
    //获取网格点Box
    let gridBox = turf.bbox(grid);
    //生成网格点范围的面
    let gridBoxPolygon = [[[gridBox[0],gridBox[1]],[gridBox[0],gridBox[3]],[gridBox[2],gridBox[3]],[gridBox[2],gridBox[1]],[gridBox[0],gridBox[1]]]];
    //获取网格范围的面与行政边界的交集 Polygon
    let intersectPolygon = null;
    let gridoxFeature = {"type":"Feature","properties":{"fill-opacity":0.8},"geometry":{"type":"Polygon","coordinates":gridBoxPolygon},"id":10};
    try {
      intersectPolygon = turf.intersect(gridoxFeature, boundaries.features[0]);
    } catch (e) {
      try{
          //色斑图绘制之后,可能会生成一些非法 Polygon ,例如 在 hole 里存在一些形状(听不懂?去查一下 GeoJSON 的规范),
          //我遇到的一个意外情况大概是这样,这种 Polygon 在做 intersect() 操作的时候会报错,所以在代码中做了个容错操作。
          //解决的方法通常就是做一次 turf.buffer() 操作,这样可以把一些小的碎片 Polygon 清理掉。
          gridoxFeature = turf.buffer(gridoxFeature, 0);
          intersectPolygon = turf.intersect(gridoxFeature, boundaries.features[0]);
      } catch (e) {
        intersectPolygon = gridoxFeature;//实在裁剪不了就不裁剪了,根据业务需求自行决定
      }
    }
    //结果添加到结果数组
    if (intersectPolygon != null){
      features.push({"type":"Feature","properties":{"fill-opacity":0.8,"fill":fill,"value":value},"geometry":intersectPolygon.geometry,"id":0});
    }
  }
}

//console.log('features:'+JSON.stringify(features));
let intersection = turf.featureCollection(features);


// 可视化及交互部分
//图层
var baseLayer = L.tileLayer(
  'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
      attribution: '...',
      maxZoom: 18
  }
);
var map = new L.Map('map', {
    center: new L.LatLng(40.4865, 111.4085),//110.763, 41.376   39.62353145, 121.9937485
    zoom: 8, //4
    attributionControl:false, //是否去除右下角标志
    layers: [baseLayer]
});
map.bounds = turf.bbox(boundaries);


  // 逐个添加过程中的数据
  L.geoJSON(boundaries, {
    style: function (feature) {
        return {color: '#4264fb', weight:1, fillOpacity:0};
    }
  }).addTo(map);

  //由于leaflet中没有找到图层显示隐藏属性,建一个字符串记录leaflet地图中显示的图层
  let layerstr = "";
  var layerM = new Map(); //记录创建的图层列表
  //原始点图层
  var geojsonMarkerOptions = {  // geojson点的样式
    radius: 3,
    fillColor: "#ff7800",
    color: "#000",
    weight: 1,
    opacity: 1,
    fillOpacity: 0.8
  };
  var pointsLay = L.geoJSON(points, {  // 添加geojson数据
      pointToLayer: function (feature, latlng){
        return L.circleMarker(latlng, geojsonMarkerOptions);
      }
    }).addTo(map);
    var pointsTxtLay = L.geoJSON(points, {  // 添加geojson数据
        pointToLayer: function (feature, latlng){
          //marker的icon文字
          var myIcon = L.divIcon({
            html: "<div style='color:#000;margin-top:-5px'>"+feature.properties.value+"</div>",
            className: 'my-div-icon',
            iconSize: 30
          });
          return L.marker(latlng, { icon: myIcon});
        }
      }).addTo(map);
  layerstr = layerstr + "points,";
  layerM.set("points",pointsLay);
  layerM.set("pointsTxt",pointsTxtLay);
  //网格差值结果
  var gridLay = L.geoJSON(grid, {
    pointToLayer: function (feature, latlng){
      //marker的icon文字
      var myIcon = L.divIcon({
        html: "<div style='color:#FF0000'>"+feature.properties.value+"</div>",
        className: '',
        iconSize: 30
      });
      return L.marker(latlng, { icon: myIcon});
    }
  });
  //显示信息
  let identifyGrid = function (e) {
    if (e.value !== null) {
      //let v = e.value.toFixed(3);
      let v = e.layer.feature.properties.value;
      let html = `<span class="popupText">Surface currents velocity ${v} ml</span>`;
      let popup = L.popup().setLatLng(e.latlng).setContent(html).openOn(map);
    }
  };
  // Bilinear interpolation
  gridLay.interpolate = true;
  gridLay.on('click', identifyGrid);
  layerM.set("grid",gridLay);
  //差值结果分级
  var isobandsLay = L.geoJSON(isobands, {
    style: function (feature) {
        return {color: '#4264fb',fillColor:feature.properties.fill, weight:0.1, fillOpacity:0.2};
    }
  });
  layerM.set("isobands",isobandsLay);
  //差值分级后再根据行政区裁剪后的图层
  var intersectionLay = L.geoJSON(intersection, {
    style: function (feature) {
        return {color: '#ffffff',fillColor:feature.properties.fill, weight:0.1, fillOpacity:0.2};
    }
  }).addTo(map);
  //显示属性信息
  let identify = function (e) {
    if (e.value !== null) {
      //let v = e.layer.feature.properties.value;//获取的值为区间值
      let v = getPointValue(e.latlng.lat,e.latlng.lng);//获取的值为IDW差的值
      let html = `<span class="popupText">Surface currents velocity ${v} ml</span>`;
      let popup = L.popup().setLatLng(e.latlng).setContent(html).openOn(map);
    }
  };
  intersectionLay.on('click', identify);
  //定位到geojson数据上
  //map.fitBounds(intersectionLay.getBounds());
  layerstr = layerstr + "intersection,";
  layerM.set("intersection",intersectionLay);


  //根据网格点计算任意经纬度值
  function getPointValue(lat,lon){
    let latMin = 0.0, latMax = 0.0, lonMin = 0.0, lonMax = 0.0;
    let leftTopV = 0, rightTopV = 0, rightButtomV = 0, leftButtomV = 0;
    //先求任意经纬度点所在的网格坐标
    grid.features.forEach(function(item){
      if(item.geometry.coordinates[0]<=lon && item.geometry.coordinates[1]>=lat){
          //lonMin = item.geometry.coordinates[0];
          //latMax = item.geometry.coordinates[1];
          if(lonMin == 0.0){
              lonMin = item.geometry.coordinates[0];
              latMax = item.geometry.coordinates[1];
          }
          else{
              lonMin = ((lon-item.geometry.coordinates[0])<(lon-lonMin))?item.geometry.coordinates[0]:lonMin;
              latMax = ((item.geometry.coordinates[1]-lat)<(latMax-lat))?item.geometry.coordinates[1]:latMax;
          }
          //leftTopV = item.properties.value;
      }
      //if(item.geometry.coordinates[0]>=lon && item.geometry.coordinates[1]>=lat){
          //lonMax = item.geometry.coordinates[0];
          //latMax = item.geometry.coordinates[1];
          //lonMax = ((item.geometry.coordinates[0]-lon)<(lonMax-lon)?item.geometry.coordinates[0]:lonMax);
          //latMax = ((item.geometry.coordinates[1]-lat)<(latMax-lat))?item.geometry.coordinates[1]:latMax;
          //rightTopV = item.properties.value;
      //}
      if(item.geometry.coordinates[0]>=lon && item.geometry.coordinates[1]<=lat){
          //lonMax = item.geometry.coordinates[0];
          //latMin = item.geometry.coordinates[1];
          if(lonMax == 0.0){
              lonMax = item.geometry.coordinates[0];
              latMin = item.geometry.coordinates[1];
          }
          else{
              lonMax = ((item.geometry.coordinates[0]-lon)<(lonMax-lon))?item.geometry.coordinates[0]:lonMax;
              latMin = ((lat-item.geometry.coordinates[1])<(lat-latMin))?item.geometry.coordinates[1]:latMin;
          }
          //rightButtomV = item.properties.value;
      }
      //if(item.geometry.coordinates[0]<=lon && item.geometry.coordinates[1]<=lat){
          //lonMin = item.geometry.coordinates[0];
          //latMin = item.geometry.coordinates[1];
          //lonMin = ((lon-item.geometry.coordinates[0])<(lon-lonMin)?item.geometry.coordinates[0]:lonMin);
          //latMin = ((lat-item.geometry.coordinates[1])<(lat-latMin))?item.geometry.coordinates[1]:latMin;
          //leftButtomV = item.properties.value;
      //}
    });
    //再求任意经纬度点所在的网格上点的值
    grid.features.forEach(function(item){
      if(item.geometry.coordinates[0]==lonMin && item.geometry.coordinates[1]==latMax){
          leftTopV = item.properties.value;
      }
      if(item.geometry.coordinates[0]==lonMax && item.geometry.coordinates[1]==latMax){
          rightTopV = item.properties.value;
      }
      if(item.geometry.coordinates[0]==lonMax && item.geometry.coordinates[1]==latMin){
          rightButtomV = item.properties.value;
      }
      if(item.geometry.coordinates[0]==lonMin && item.geometry.coordinates[1]==latMin){
          leftButtomV = item.properties.value;
      }
    });
    //开始通过IDW算法计算网格上任意点的值
    let idwdatas = [{x:lonMin,y:latMax,v:leftTopV},{x:lonMax,y:latMax,v:rightTopV},{x:lonMax,y:latMin,v:rightButtomV},{x:lonMin,y:latMin,v:leftButtomV}];
    var idwresult = [{x:lon,y:lat,v:0}];
    idwcomputer(idwdatas,idwresult);
    //console.info(idwresult);
    //结束通过IDW算法计算网格上任意点的值
    let rValue = idwresult[0].v.toFixed(2);//获取任意经纬度点的值
    return rValue;
  }
  //idw算法
  function idwcomputer(datas,result){
    if(datas.lenght<3) return result;
    var m0=datas.length;
    var m1=result.length;
    //距离列表
    var r=[];
    for(var i=0;i<m1;i++){
      for(var j=0;j<m0;j++){
              var tmpDis = Math.sqrt(Math.pow(result[i].x - datas[j].x, 2) + Math.pow(result[i].y - datas[j].y, 2));
              r.push(tmpDis);
      }
    }

    //插值函数
    for (var i = 0; i < m1; i++)
    {
      //查找重复
      var ifFind = false;
      for (var j = m0 * i; j < m0 * i + m0; j++)
      {
          if (Math.abs(r[j]) < 0.0001)
          {
              result[i].v = datas[j - m0 * i].v;
              ifFind = true;
              break;
          }
      }

      if (ifFind) continue;

      var numerator = 0;
      var denominator = 0;

      for (var j = m0 * i; j < m0 * i + m0; j++)
      {
          numerator += datas[j - m0 * i].v / (r[j] * r[j]);
          denominator += 1 / (r[j] * r[j]);
      }
      result[i].v = numerator / denominator;
    }
    return result;
  }
  //取网格点中等级包含最多的点的等级属性
  function getMaxAttribute(inLevelV,inGrid,inBreaksProperties){
    //定义变量
    let levelArray = [];
    let levelLength = inLevelV.length;
    inLevelV.forEach(function (item, index) {
      if(index<levelLength-2)levelArray.push(0);
    });
    //统计每个等级中网格点数量
    inGrid.features.map((i) => {
      inLevelV.forEach(function (item, index) {
      if(index<levelLength-3){
        if(i.properties.value>=inLevelV[index]&&i.properties.value<inLevelV[index+1])levelArray[index]++;
      }
      if(index==levelLength-2){
        if(i.properties.value>=inLevelV[index])levelArray[index]++;
      }
      });
    });
    //取等级中网格点最多的值
    let maxIndex = -1;
    let maxV = 0;
    levelArray.forEach(function (item, index) {
      if(maxV<item){maxV = item; maxIndex = index;}
    });
    let value = '';
    let fill='';
    if(maxIndex != -1){
      value = inLevelV[maxIndex] + '-' + inLevelV[maxIndex+1];
      fill=inBreaksProperties[maxIndex].fill;
    }
    return [value,fill]
  }

  // 右上角的导航菜单
  var layers = document.getElementById("menu-ui");
  var toggleableLayerIds = ["points", "grid", "isobands", "intersection"];

  for (var i = 0; i < toggleableLayerIds.length; i++) {
    var id = toggleableLayerIds[i];

    var link = document.createElement("a");
    link.href = "#";
    link.className = layerstr.indexOf(id+",") == -1 ? "" : "active";
    link.textContent = id;

    link.onclick = function (e) {
      let clickedLayer = this.textContent;
      e.preventDefault();
      e.stopPropagation();

      let visibility = layerstr.indexOf(clickedLayer+",");

      if (visibility === -1) {
        this.className = "active";
        map.addLayer(layerM.get(clickedLayer));
        if(clickedLayer=="points"){
          map.addLayer(layerM.get(clickedLayer+"Txt"));
        }
        layerstr = layerstr + clickedLayer + ",";
      } else {
        map.removeLayer(layerM.get(clickedLayer));
        if(clickedLayer=="points"){
          map.removeLayer(layerM.get(clickedLayer+"Txt"));
        }
        this.className = "";
        layerstr = layerstr.replace(clickedLayer + ",","");
      }
     };

     layers.appendChild(link);
   }

// var hoveredStateId = null;
// map.on("mousemove", "intersection", function (e) {
//   if (e.features.length > 0) {
//     if (hoveredStateId) {
//       map.setFeatureState(
//         { source: "intersection", id: hoveredStateId },
//         { hover: false }
//       );
//     }
//     hoveredStateId = e.features[0].id;
//     map.setFeatureState(
//       { source: "intersection", id: hoveredStateId },
//       { hover: true }
//     );
//   }
// });

// var map = L.map("mapDiv").setView([36.55,117.32],13);
// L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{attribution:'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'}).addTo(map);
// L.marker([36.55,117.32]).addTo(map);
// L.polyline([[36.54,117.33],[36.55,117.33],[36.56,117.35],[36.55,117.36]]).addTo(map);
// L.polygon([[[36.53,117.32],[36.51,117.30],[36.51,117.33],[36.53,117.32]]]).addTo(map);
// L.circle([36.52,117.30],{radius:200}).addTo(map);
// L.circleMarker([36.54,117.29],{radius:20}).addTo(map);

style.css

body {
  margin: 0;
  padding: 0;
}
#map {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 100%;
}
.menu-ui {
  background: #fff;
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 999;
  border-radius: 3px;
  width: 120px;
  border: 1px solid rgba(0, 0, 0, 0.4);
}
.menu-ui a {
  font-size: 13px;
  color: #404040;
  display: block;
  margin: 0;
  padding: 0;
  padding: 10px;
  text-decoration: none;
  border-bottom: 1px solid rgba(0, 0, 0, 0.25);
  text-align: center;
}
.menu-ui a:first-child {
  border-radius: 3px 3px 0 0;
}
.menu-ui a:last-child {
  border: none;
  border-radius: 0 0 3px 3px;
}
.menu-ui a:hover {
  background: #f8f8f8;
  color: #404040;
}
.menu-ui a.active {
  background: #3887be;
  color: #fff;
}
.menu-ui a.active:hover {
  background: #3074a4;
}

本文大部分参考:
Javascript(turfjs)等值线图绘制 - SegmentFault 思否
Leaflet加turf生成色斑图并单击显示范围值或精准值-Javascript文档类资源-CSDN文库

原文链接:https://blog.csdn.net/cwr888/article/details/124717178

作者:秦晓川  创建时间:2023-07-21 15:44
最后编辑:秦晓川  更新时间:2024-11-18 15:41