文章目录
- 1、概念
- 2、leaflet-idw插件
- 3、使用方法
- 4、示例代码
- 5、后续
- 1)自定义色带-gradient
- 2)效率问题
1、概念
反距离权重 (IDW) 插值显式假设:彼此距离较近的事物要比彼此距离较远的事物更相似。当为任何未测量的位置预测值时,反距离权重法会采用预测位置周围的测量值。与距离预测位置较远的测量值相比,距离预测位置最近的测量值对预测值的影响更大。反距离权重法假定每个测量点都有一种局部影响,而这种影响会随着距离的增大而减小。由于这种方法为距离预测位置最近的点分配的权重较大,而权重却作为距离的函数而减小,因此称之为反距离权重法。
以上来自(arcgis帮助文档)
简单理解就是事物之间的相互影响,随着距离的增大而越来越小。
2、leaflet-idw插件
在github上偶然发现了一个基于leaflet的反距离权重插值的插件,插件地址:
https://github.com/JoranBeaufort/Leaflet.idw
3、使用方法
下载插件后,所有的算法都在leaflet.js文件中。在文件末尾,定义了一个方法:
L.idwLayer = function (latlngs, options) {
return new L.IdwLayer(latlngs, options);
};
它返回了一个插值结果图层,可以直接addTo到leaflet的L.map对象中。两个参数:
latlngs: 是一个二维数组对象,里面每个元素包含三个值:经度、纬度以及该点的采样值。
options: 是一个对象,来的142-151行可以看到定义如下:
options: {
opacity: 0.5,
maxZoom: 18,
cellSize: 1,
exp: 2,
max: 100
},
其中:
opacity: 图层的透明度,
maxZoom: 图层最大缩放级别,
cellSIze: 用于插值计算时的单元格大小,越小越精细,越耗资源,
exp: 幂函数中的幂值,(幂函数可以在上面链接中了解下)
max: 最大样点值。
4、示例代码
(function(){
var map = L.map('map').setView([35.87, 105.475], 5);
var tiles = L.tileLayer('https://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetGray/MapServer/tile/{z}/{y}/{x}', {
}).addTo(map);
$.getJSON('/data/city_air.geojson',function(data){
var features = data.features;
showidwLayer(features)
showMark(features);
})
/**
* 显示插值图层
* @param {Array(point)} data
*/
function showidwLayer(data){
var points = [];
data.forEach(element => {
var lng = element.geometry.coordinates[0];
var lat = element.geometry.coordinates[1];
var aqi = parseInt(element.properties.AQI);
if(aqi){
points.push([lat,lng,aqi]);
}
});
var idw = L.idwLayer(points,{
opacity: 0.3,
maxZoom: 18,
cellSize: 10,
exp: 5,
max: 300
});
idw.addTo(map);
}
/**
* 显示采样点
* @param {*} data
*/
function showMark(data){
data.forEach(element => {
var lng = element.geometry.coordinates[0];
var lat = element.geometry.coordinates[1];
L.marker([lat, lng]).addTo(map) //这里纬度在前
});
}
})()
为了查看方便,我把采样点也显示在地图上。
完整代码下载:Demo 插值结果
5、后续
1)自定义色带-gradient
上面的插值结果,在值高的地方,颜色偏黄、红,在值低的地方,颜色片绿、蓝,色带颜色值在源码中的定义如下:
defaultGradient: {
0.0: '#000066',
0.1: 'blue',
0.2: 'cyan',
0.3: 'lime',
0.4: 'yellow',
0.5: 'orange',
0.6: 'red',
0.7: 'Maroon',
0.8: '#660066',
0.9: '#990099',
1.0: '#ff66ff'
},
有时候,我们并不满足与上面这种颜色搭配,就需要自定义颜色色带。怎么自定义?
options.gradient参数
即在options中增加一个gradient属性,按上面的方式定义色带即可。如
var colors = {
0:'#fff',
0.3: '#A5CC82',
0.6: '#00467F',
0.9: '#292E49',
1: '#000'
},
var options = {
opacity: 0.5,
maxZoom: 18,
cellSize: 10,
exp: 5,
max: 300,
gradient: colors
}
idw = L.idwLayer(points,options);
渲染后的结果如下:
2)效率问题
这种方法,是在前端来直接进行插值、渲染,插值算法可能会导致页面卡顿,另外,每次放大缩小操作时,都会重新进行计算插值,需要注意。
因此,在资源有限的情况下,建议将optison参数中的cellSize,尽量设置为较高数值。