作者:yangjunlin
在上一篇文章中我们已经使用了像素法实现克里金插值的方式,但是问题也就随之抛了出来。1.第一点,在反距离权重插值的时候,因为处理的数据量大会直接导致主线程卡,导致用户体验不好,2.第二点,分析过程中 zoom级别改变,坐标转像素的值的计算方式也会发生变化,这样就会导致(坐标转像素坐标,像素坐标转坐标)会出现错误结果。
我们先分析一下第一个问题,主线程卡顿的问题其实很好解决, Web Worker 可以创建一个独立于主线程运行的子线程。可以将一些【可能会阻塞主线程的操作】,丢在 Worker 里去单独执行。因此我们可以直接将卡住进程的反距离权重插值分析方法直接抛到webworker里面即可
再看下第二个问题,既然像素没法用,那么我们就自己搞‘像素’ 也就是自己画格子。其实坐标到像素仔细来看可以认为是一种投影,那么我们是不是也能自己搞一套投影了。从当前我的数据的坐标系来看,我用的mapboxgl3857的web墨卡托投影的坐标,全球的比例级别可直接认为是1:1,中国地区是没有被压扁的。我的思路是这样的我们也可以画一个1:1的范围是正方形的图形,然后对里面的区域再进行[m,m]的小网格划分。3857web墨卡托与该正方形的范围基本上就是成一个k比例的,也就是说,我们不用复杂的投影计算,只需要简单的算出每个单位的经纬度所占的小格子数就可以,这样就大大降低了难度。
let width=bbox[2]-bbox[0];
let height=bbox[3]-bbox[1];
length=width-height>0?width:height
return length;
//形成1000*1000的网格。
let cw=1000,ch=1000;
let k=cw/lenght;
//将几何范围放到左下为原点的位置上
let x=data[i].x-xoffset;
let y=data[i].y-yoffset;
//进行投影,将局部
let posx=x*k;
let posy=y*k;
let x= coordinates[i][j][m][0]*1/k+box[0]
let y=coordinates[i][j][m][1]*1/k+box[1]
coordinates[i][j][m] = [x, y]



//Worker.js
self.onmessage = function ({data}) {
const resdata=IDW(data['data'],data['cw'],data['ch'])
self.postMessage({ resdata })
}
self.onerror = function (err) {
throw new Error(err)
}
//主进程:
//webworker
const worker = new Worker('./worker.js', {
name: 'my-worker'
})
//主线程向子线程发数据
worker.postMessage({
data: pxdata.data,
cw: cw,
ch: ch,
contours
})
// 监听到子线程返回的数据
worker.onmessage = ({
data
}) => {
const idwdata = data['resdata'];}
然后将拿到结果在进行d3分析,解析渲染即可,这样就解决因为反距离权重分析的时间长导致主进程卡在而导致无法正常使用地图的问题。
当然这个只是我的一个demo,代码肯定还有很多不完善的地方,这两篇文章只是提供给大家做前端插值分析的一个小方向,如果大家有更多的更优的解决方案,欢迎大家在评论里讨论