讲讲项目背景,大屏专题图要绘制一个地区区域环境扩散效果,初步一开始感觉是一个热力图,后面经过描述确认不是,而是一个根据点位进行区域绘制的等值面
我以为的:
最后实际上的
第一张图是ui效果图,第二张图是确定功能需求后绘制的,说实话,看到ui效果图时我第一反应是热力图,因为这个扩散效果太像了,当时自己想的是这个图有河道,那就说明是地图,是地图那就说明可能需要缩放和拖拽,一开始项目中因为是大屏数据可视化,已经引入了echarst包,所以根据echarst绘制了一个地区区域面
,如下:
echarts + canvas
主要还是echarts社区给力,各种可视化图形基本都有
社区地址
社区查找示例筛选热力图,找到下面两个示例,跟我想要的效果很相似
最后结论是这种热力效果有缺陷,那就是echarts绘制区域断面是根据registerMap函数绘制的,根据断面地理坐标geojson文件绘制出来一个图层
echarts.registerMap(‘fenyang’, geoJson);
而热力图图层无法融入registerMap创建的图层中去,当图形缩小到一定程度时,热力图层将变成一个矩形方块,看起来很不友好,所以淘汰
高德地图
使用高德绘制上述图形还是可以轻轻松松的,网上示例文档很多,这里就不介绍了,如有需要,留言,根据需要我会在写一篇博客,帮助有需要的朋友。
这里淘汰原因,项目中只有这一块用到了地图,引入高德显得过于臃肿。
项目领导反映这一块内容别用地图,且这不是一个热力图,不需要地图缩放,拖拽功能,可以用canvas绘制,冥思苦想了一会,不是热力图那看起来就有点类似等值面效果了,用canvas画这个断面不是啥问题,可是这个颜色渲染还没弄过,恰逢这时,领导给出回应,可以试试克里金插值算法试试,有这方面的插件。
kriging + canvas
克里金插值算法这是个啥,听都没听过,抱着学习心态去找度娘,翻了两个小时的博客文档最后决定自己造轮子,没有找到我可以用的示例,这里分享插件地址和两篇博客
插件地址
思路引用一
思路引用二
代码分享
其实我不怎么想贴的,因为文件结构有点多,算了还是分享出来,以免网友恶意揣测狗博主——问题没解决还瞎引导思路。
<!DOCTYPE html>
<html lang='En'>
<hEad>
<mEta charsEt='UTF-8'>
<titlE>leaflet克里金空间插值</titlE>
<stylE>
html, Body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#canvasMap{
/* width: 440px;
height: 295px; */
width: 300px;
height: 300px;
}
#map{
width: 100%;
height: 0;
margin: 0;
padding: 0;
ovErFlow: hiddEn;
cursor: dEFault;
}
</stylE>
<script src='world.js'></script>
<script src='point.js'></script>
<script src='kriging.js'></script>
</hEad>
<Body>
<canvas id='canvasMap'></canvas>
<div id='map'></div>
</Body>
<script>
//world.js,是插值之后需要裁切的图形边界信息
//point.js,是要插值的离散的点
//遍历world边界数据,生成scope边界线
let positions = [];
world[0].forEach(function (point) {
positions.push([point[1], point[0]]);
});
// 边界经度值极大值极小值,纬度极大值极小值
let miny = Math.min(...world[0].map((v) => v[1]));
let maxy = Math.max(...world[0].map((v) => v[1]));
let minx = Math.min(...world[0].map((v) => v[0]));
let maxx = Math.max(...world[0].map((v) => v[0]));
let xlim = [minx, maxx];
let ylim = [miny, maxy];
//进行克里金插值
function loadkriging()
{
var canvas = document.getElementById('canvasMap');
canvas.width = 250;
canvas.height = 250;
var n = points.length;
var t = [];//数值
var x = [];//经度
var y = [];//纬度
for (var i = 0; i < n; i++)
{
t.push(points[i].attributes.TN_);
x.push(points[i].geometry.x);
y.push(points[i].geometry.y);
}
// 对数据集进行训练
var variogram = kriging.train(t, x, y, 'exponential', 0, 100);
// 改值越大,边界线越圆滑,反之锯齿越严重
var tole = 300;
//使用variogram对象使polygons描述的地理位置内的格网元素具备不一样的预测值,最后一个参数,是插值格点精度大小
var grid = kriging.grid(world, variogram, (ylim[1]-ylim[0])/tole);
var color = [
'#7e0123',
'#7f0124',
'#7f0124',
'#7f0125',
'#7f0125',
'#800125',
'#800126',
'#800126',
'#800127',
'#810127',
'#810127',
'#810128',
'#810128',
'#820129',
'#820129',
'#820129',
'#82012a',
'#83012a',
'#83012b',
'#83012b',
'#84012b',
'#84012c',
'#84012c',
'#84012d',
'#85012d',
'#85012e',
'#85012e',
'#86012f',
'#86012f',
'#860130',
'#860130',
'#870130',
'#870131',
'#870131',
'#870132',
'#880132',
'#880132',
'#880133',
'#890133',
'#890134',
'#890134',
'#890134',
'#8a0135',
'#8a0135',
'#8a0136',
'#8a0136',
'#8b0136',
'#8b0137',
'#8b0037',
'#8b0038',
'#8c0038',
'#8c0038',
'#8c0039',
'#8c0039',
'#8d003a',
'#8d003a',
'#8d003a',
'#8d003b',
'#8e003b',
'#8e003c',
'#8e003c',
'#8f003c',
'#8f003d',
'#8f003d',
'#8f003e',
'#90003e',
'#90003e',
'#90003f',
'#90003f',
'#910040',
'#910040',
'#910040',
'#910041',
'#920041',
'#920042',
'#920042',
'#920043',
'#930043',
'#930043',
'#930044',
'#940044',
'#940045',
'#940045',
'#940045',
'#950046',
'#950046',
'#950047',
'#950047',
'#960047',
'#960048',
'#960048',
'#960049',
'#970049',
'#970049',
'#97004a',
'#97004a',
'#98004b',
'#98004b',
'#99004a',
'#9a0049',
'#9b0049',
'#9c0048',
'#9d0047',
'#9e0046',
'#9f0046',
'#a00045',
'#a10044',
'#a20043',
'#a30043',
'#a40042',
'#a50041',
'#a60040',
'#a70040',
'#a8003f',
'#aa003e',
'#ab003d',
'#ac003d',
'#ad003c',
'#ae003b',
'#af003a',
'#b0003a',
'#b10039',
'#b20038',
'#b30037',
'#b40037',
'#b50036',
'#b60035',
'#b70034',
'#b80034',
'#b90033',
'#ba0032',
'#bb0031',
'#bc0030',
'#bd0030',
'#be002f',
'#bf002e',
'#c0002d',
'#c1002d',
'#c2002c',
'#c3002b',
'#c4002a',
'#c5002a',
'#c60029',
'#c70028',
'#c80027',
'#c90027',
'#ca0026',
'#cc0025',
'#cd0024',
'#ce0024',
'#cf0023',
'#d00022',
'#d10021',
'#d20021',
'#d30020',
'#d4001f',
'#d5001e',
'#d6001e',
'#d7001d',
'#d8001c',
'#d9001b',
'#da001b',
'#db001a',
'#dc0019',
'#dd0018',
'#de0017',
'#df0017',
'#e00016',
'#e10015',
'#e20014',
'#e30014',
'#e40013',
'#e50012',
'#e60011',
'#e70011',
'#e80010',
'#e9000f',
'#ea000e',
'#eb000e',
'#ec000d',
'#ee000c',
'#ef000b',
'#f0000b',
'#f1000a',
'#f20009',
'#f30008',
'#f40008',
'#f50007',
'#f60006',
'#f70005',
'#f80005',
'#f90004',
'#fa0003',
'#fb0002',
'#fc0002',
'#fd0001',
'#fe0000',
'#fe0100',
'#fe0300',
'#fe0400',
'#fe0500',
'#fe0600',
'#fe0800',
'#fe0900',
'#fe0a00',
'#fe0b00',
'#fe0d00',
'#fe0e00',
'#fe0f00',
'#fe1100',
'#fe1200',
'#fe1300',
'#fe1400',
'#fe1600',
'#fe1700',
'#fe1800',
'#fe1900',
'#fe1b00',
'#fe1c00',
'#fe1d00',
'#fe1f00',
'#fe2000',
'#fe2100',
'#fe2200',
'#fe2400',
'#fe2500',
'#fe2600',
'#fe2700',
'#fe2900',
'#fe2a00',
'#fe2b00',
'#fe2d00',
'#fe2e00',
'#fe2f00',
'#fe3000',
'#fe3200',
'#fe3300',
'#fe3400',
'#fe3500',
'#fe3700',
'#fe3800',
'#fe3900',
'#fe3b00',
'#fe3c00',
'#fe3d00',
'#fe3e00',
'#ff4000',
'#ff4100',
'#ff4200',
'#ff4300',
'#ff4500',
'#ff4600',
'#ff4700',
'#ff4900',
'#ff4a00',
'#ff4b00',
'#ff4c00',
'#ff4e00',
'#ff4f00',
'#ff5000',
'#ff5100',
'#ff5300',
'#ff5400',
'#ff5500',
'#ff5700',
'#ff5800',
'#ff5900',
'#ff5a00',
'#ff5c00',
'#ff5d00',
'#ff5e00',
'#ff5f00',
'#ff6100',
'#ff6200',
'#ff6300',
'#ff6500',
'#ff6600',
'#ff6700',
'#ff6800',
'#ff6a00',
'#ff6b00',
'#ff6c00',
'#ff6d00',
'#ff6f00',
'#ff7000',
'#ff7100',
'#ff7300',
'#ff7400',
'#ff7500',
'#ff7600',
'#ff7800',
'#ff7900',
'#ff7a00',
'#ff7b00',
'#ff7d00',
'#ff7e00',
'#ff7f00',
'#ff8100',
'#ff8200',
'#ff8300',
'#ff8500',
'#ff8600',
'#ff8700',
'#ff8800',
'#ff8a00',
'#ff8b00',
'#ff8c00',
'#ff8e00',
'#ff8f00',
'#ff9000',
'#ff9200',
'#ff9300',
'#ff9400',
'#ff9500',
'#ff9700',
'#ff9800',
'#ff9900',
'#ff9b00',
'#ff9c00',
'#ff9d00',
'#ff9f00',
'#ffa000',
'#ffa100',
'#ffa200',
'#ffa400',
'#ffa500',
'#ffa600',
'#ffa800',
'#ffa900',
'#ffaa00',
'#ffac00',
'#ffad00',
'#ffae00',
'#ffb000',
'#ffb100',
'#ffb200',
'#ffb300',
'#ffb500',
'#ffb600',
'#ffb700',
'#ffb900',
'#ffba00',
'#ffbb00',
'#ffbd00',
'#ffbe00',
'#ffbf01',
'#ffc001',
'#ffc201',
'#ffc301',
'#ffc401',
'#ffc601',
'#ffc701',
'#ffc801',
'#ffca01',
'#ffcb01',
'#ffcc01',
'#ffcd01',
'#ffcf01',
'#ffd001',
'#ffd101',
'#ffd301',
'#ffd401',
'#ffd501',
'#ffd701',
'#ffd801',
'#ffd901',
'#ffdb01',
'#ffdc01',
'#ffdd01',
'#ffde01',
'#ffe001',
'#ffe101',
'#ffe201',
'#ffe401',
'#ffe501',
'#ffe601',
'#ffe801',
'#ffe901',
'#ffea01',
'#ffeb01',
'#ffed01',
'#ffee01',
'#ffef01',
'#fff101',
'#fff201',
'#fff301',
'#fff501',
'#fff601',
'#fff701',
'#fff801',
'#fffa01',
'#fffb01',
'#fffc01',
'#fffe01',
'#ffff01',
'#fcff01',
'#fafe01',
'#f7fe01',
'#f5fe01',
'#f2fe01',
'#f0fd01',
'#edfd01',
'#eafd01',
'#e8fd01',
'#e5fc01',
'#e3fc01',
'#e0fc01',
'#defb01',
'#dbfb01',
'#d9fb01',
'#d6fb01',
'#d3fa01',
'#d1fa01',
'#cefa01',
'#ccfa01',
'#c9f901',
'#c7f901',
'#c4f901',
'#c1f801',
'#bff801',
'#bcf801',
'#baf801',
'#b7f701',
'#b5f701',
'#b2f701',
'#aff701',
'#adf601',
'#aaf601',
'#a8f601',
'#a5f501',
'#a3f501',
'#a0f501',
'#9ef501',
'#9bf401',
'#98f401',
'#96f401',
'#93f401',
'#91f301',
'#8ef301',
'#8cf301',
'#89f201',
'#86f201',
'#84f201',
'#81f201',
'#7ff101',
'#7cf101',
'#7af101',
'#77f101',
'#74f001',
'#72f001',
'#6ff001',
'#6def01',
'#6aef01',
'#68ef01',
'#65ef01',
'#62ee01',
'#60ee01',
'#5dee01',
'#5bee01',
'#58ed01',
'#56ed01',
'#53ed01',
'#51ec01',
'#4eec01',
'#4bec01',
'#49ec01',
'#46eb01',
'#44eb01',
'#41eb01',
'#3feb01',
'#3cea01',
'#39ea01',
'#37ea01',
'#34e901',
'#32e901',
'#2fe901',
'#2de901',
'#2ae801',
'#27e801',
'#25e801',
'#22e801',
'#20e701',
'#1de701',
'#1be701',
'#18e601',
'#16e601',
'#13e601',
'#10e601',
'#0ee501',
'#0be501',
'#09e501',
'#06e501',
'#04e401',
'#01e401',
]
//将得到的格网grid渲染至canvas上
kriging.plot(canvas, grid, [xlim[0], xlim[1]], [ylim[0], ylim[1]], color.reverse());
// 绿,黄绿,橙黄绿,红橙黄绿,紫红橙黄绿,洋红紫红橙黄绿
// #01e401,#ffff01,#ff7e00,#fe0000,#98004b,#7e0123,
// 黄绿 #ffff01 #01e401
// 橙黄绿 #01e401 #ff7e00 #ffff01 #01e401
// 红橙黄绿 #01e401 #fe0000 #ff7e00 #ffff01 #01e401
// 紫红橙黄绿 #01e401 #98004b #fe0000 #ff7e00 #ffff01 #01e401
// 洋红紫红橙黄绿 #01e401 #7e0123 #98004b #fe0000 #ff7e00 #ffff01 #01e401
//
}
loadkriging();
</script>
</html>
这里可以看到我声明的色值数组很长,因为建立的色系过渡数组太短的话,颜色过渡效果看起来非常差,说起来找色系过渡的编程处理方式还找了半天。