废了九牛二虎之力,总算摸清楚如何将一个黑白的地形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&¬ClockwisePartNum==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:'© <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
最后编辑:秦晓川 更新时间:2024-11-18 15:41