Echarts GL 结合mapbox趟坑记(使用appendData)

前言

echartsGL官网示例有个很炫酷的散点图,通过服务器分批加载实现了千万条以上数据的展示:

Echarts GL 结合mapbox趟坑记(使用appendData)_第1张图片

domo可以看这里。

其实就是分批加载服务器数据然后呈现。看上去很简单,其实坑不是一般的多。

二、数据转换

通过官网下载上述demo,放到本地,打开控制台,找到数据请求地址,修改demo里的ROOTPATH,尝试在本地跑起来。一看,报错。接口不支持跨域。没办法,只能模拟一下接口返回的数据,通过Float32Array进行数据封装。demo里的核心代码如下:

myChart.appendData({
    seriesIndex: 0,
     data: data
 });

可以看到核心代码就是调用的echarts的对象方法appendData;

data的数据格式,在我摸了半天的情况下,终于弄清楚:
假设这是我的元数据(并非最终数据):

 [
   {
      lat:131.222,
	  lon:31.3333,
	  num:12
   } 
]

每一个数据可以由经度,维度,以及这个点的加权(记为num)组成。则我们需要一个Float32Array,其存储格式如下:

[131.22,31.33333,12,132.33,32.2222,24.....]

转换函数如下:

	_Scatter.prototype._transform = function(data_arr){

		const ret = new Float32Array(data_arr.length * 3);
		data_arr.map((o, i) => {
			ret[i + (i * 2)] = o.lon
			ret[i + 1 + (i * 2)] = o.lat
			ret[i + 2 + (i * 2)] = o.num || 0
		})
		return ret;
	}

此时我们就可以进行放数据了。

三、使用mapbox

echartsGL中支持了对mapbox的内置支持。将window下的mapboxgl置为mapbox根对象即可。我们库将mapbox自封装了一下。所以是:

window.mapboxgl = SE;

之后在echarts的options里配置地图。将原先使用的矢量百度地图替换为maobox加载的wmts服务。
style的配置方案可以参考mapbox官档。

	const mapbox = {
				style: g_config.styleUrl,
				boxHeight: 20,
				zoom: zoom || undefined,
          		center: center || undefined,
				light: {
					main: {
						intensity: 1,
						shadow: true,
						shadowQuality: 'high'
					},
					ambient: {
						intensity: 0.2
					}
				}
		};

地图初始化(拷贝的demo的方式,注意将coordinateSystem换为mapbox):

series: [{
        name: '弱',
        type: 'scatterGL',
        progressive: 1e6,
        coordinateSystem: 'mapbox',
        symbolSize: 1,
        zoomScale: 0.002,
        blendMode: 'lighter',
        large: true,
        itemStyle: {
            color: 'rgb(20, 15, 2)'
        },
        postEffect: {
            enable: true
        },
        silent: true,
        dimensions: ['lng', 'lat'],
        data: new Float32Array()
    }]

接入数据。发现echarts_gl报错。
Echarts GL 结合mapbox趟坑记(使用appendData)_第2张图片

此处的我一脸懵逼。反复检查输入数据就是跟demo一致时,不得不怀疑是echarts与maobox兼容性导致的。于是我翻阅官档,找到了如下一个可疑的点。
Echarts GL 结合mapbox趟坑记(使用appendData)_第3张图片
居然没有mapbox相关的配置?只有mapbox3d?于是我在源码中搜索 mapbox3D 得到了如下一句源码
Echarts GL 结合mapbox趟坑记(使用appendData)_第4张图片
原来是mapbox的配置项默认被置为了3d.也就是现在echarts内置的mapbox只能是3D的。在翻阅文档,发现有一种图表类型是scatter3D专门适用于三维场景下的散点图。以下是官网摘取的几个DEMO
Echarts GL 结合mapbox趟坑记(使用appendData)_第5张图片

Echarts GL 结合mapbox趟坑记(使用appendData)_第6张图片

试过各种scatterGL的各种配置。万念俱灰之时,随手将type改为scatter3D。神奇的事情发生了!居然一切正常。

Echarts GL 结合mapbox趟坑记(使用appendData)_第7张图片
此时只有一句话 wtf。最怕的不是改完一个bug吐槽怎么还不正常。而是改完之后莫名其妙发现居然正常了。
这个问题我后来有时间会补上原因。先说接下来的事情

四、使用appendData

按照官网demo,写了一个批量请求服务器数据的接口。然而在数据呈现的时候,发现并没有像demo一般颗粒慢慢加载,而是每次appendData都刷新了原数据。出现了类似放烟花的效果。这个比较好解,我很快找到了配置项progressiveThreshold。这个是配置散点图当数据到达这个值之前,都会刷新数据,因为我每次请求的数据是1000个点。非demo里的100000,而这个配置项默认就是100000.

const options_points = {
//--mapbox为上文配置
			mapbox,
			series: [Object.assign({},common, {
				progressiveThreshold: 1000,
				symbolSize: 2,
				itemStyle: {
					color: 'rgb(200, 15, 2)'
				}
			})]
		}

我做的应用是请求某一天的所有散点数据。这样一天的数据就可以按照这种方式加载了。然而我很快又遇到了另外一个问题。

四、清空appendData的数据,重新进行append

在我切换到另外一天时,我显然需要清空当天已经append进去的数据,再重新append进去。按照对echarts的了解,我知道并没有类似clearData这样的接口。只能通过setOptions,将series中对应的data属性置为默认值。于是我在重置时,继续调用了如下方法:

this.scatter.setOption({
        series: [
          {
            data: new Float32Array()
          }
        ]
      });

效果如我预期一样很棒(我以为)。地图上的点都被清空了。于是我连接了业务逻辑,开始第二天的数据查找。第二天的数据开始append的时候,居然又给我放起了烟花~~~

联想到echarts的options自动合并策略。我觉得我并没有让echarts意识到我需要清空数据和当前的数据模式append)。于是我联想到了其他的方式让echarts觉得是时候重新清除数据了。修改部分配置项的值,让echarts不得不清空某些状态。

在我尝试N次的时候。最终我成功了。。。

setOption({
        series: [
          {
            progressive: 1e6,
            progressiveThreshold: 1000 + Math.random(),
            data: new Float32Array()
          }
        ]
      });

没错。就是刚才的属性progressiveThreshold。我在每次需要重新append的时候,将这个属性置为和上一个不一样。对就是使用Math.random().这样echarts会觉得需要重新刷新数据的状态,于是我可以进行下一轮分批加载。

五、结语

今天先写到这。后续有坑再补。

你可能感兴趣的:(echarts,前端技术)