海量点展示 最后更新时间: 2021年01月22日
PointSimplifier是一个针对海量点展示场景的组件,能够支持较大规模的经纬度数据,以及配置丰富的展示效果。

上方是全国范围内100万规模的点的一些效果截图。可以看出,PointSimplifier在低级别下并没有绘制出全部的点,而是选取了其中的一部分,选取的策略(可配置)简单来说分如下两步:
- TopN选取:在高密度区域(上图的东南部,带背景色),排序选出高优先级的N个点,其余点抛弃。
- 占位检测:绘制之前,如果发现某个点需要占用的矩形空间已经有其他点存在了,则不绘制该点,直接跳过。
通过以上两步,最终显示的点的规模可以被控制在浏览器允许的合理范围以内,效果上也保留了点的分布特征,能够直观的分辨密集区域和稀疏区域。
浏览器支持:
PointSimplifier目前依赖Canvas进行绘制,因此不支持IE9及以下浏览器。
名词释义
名称 | 说明 |
---|---|
数据源(data) | 一个数组,每个元素即点的相关信息(dataItem) |
数据项(dataItem) | 数据源数组的元素,通常就是点的相关信息。数据项自身的格式没有强制要求,只要能索引或者包含点的信息即可。 |
数据项索引(dataIndex) | 数据项在数据源数组中的的索引位置,即 0,1,2.... |
四叉树 | 一种空间索引结构。简单来说,点的范围构成一个矩形,如果这个矩形中包含的点的数量大于某个阈值,则宽高等分,切出4个面积相等的小矩形(称为四叉树节点),然后对这4个小矩形继续同样的步骤。 下方左侧为四叉树的示意图,右侧为 PointSimplifier 开启 ![]() |
TopN区域 | 四叉树节点代表的区域,如果该区域的视图面积小于一定阈值(比如10*10像素),则仅仅选出区域内高优先级的N个点进行绘制,该区域就是一个TopN区域。通常来说,地图的 下图中红色黑边的小矩形即为TopN区域,可以看出,它们都是小面积的四叉树节点。 ![]() |
Point Hardcore | 点的“硬核”区域(矩形),该区域为该点独占,会起到“占位”的作用。 直观效果可以访问这里(调整 pointHardcoreStyle 中的 |
Shadow Point | 硬核区域已经被其他点占用,从而无法绘制的点。出于调试目的,通过参数配置也可以绘制这些点,以便直观的分辨哪些点被“挤占”了,但是该类型的点仅仅显示,没有功能,不响应事件 |
如何使用
1、引入UI组件库
2、加载PointSimplifier(模块名:ui/misc/PointSimplifier
)
//加载PointSimplifier,loadUI的路径参数为模块名中 'ui/' 之后的部分
AMapUI.loadUI(['misc/PointSimplifier'], function(PointSimplifier) {
if (!PointSimplifier.supportCanvas) {
alert('当前环境不支持 Canvas!');
return;
}
//启动页面
initPage(PointSimplifier);
});
function initPage(PointSimplifier) {
//创建组件实例
var pointSimplifierIns = new PointSimplifier({
map: map, //关联的map
compareDataItem: function(a, b, aIndex, bIndex) {
//数据源中靠后的元素优先,index大的排到前面去
return aIndex > bIndex ? -1 : 1;
},
getPosition: function(dataItem) {
//返回数据项的经纬度,AMap.LngLat实例或者经纬度数组
return dataItem.position;
},
getHoverTitle: function(dataItem, idx) {
//返回数据项的Title信息,鼠标hover时显示
return '序号: ' + idx;
},
renderOptions: {
//点的样式
pointStyle: {
fillStyle: 'blue' //蓝色填充
}
}
});
//随机创建一批点,仅作示意
var data = createPoints(map.getCenter(), 100000);
//设置数据源,data需要是一个数组
pointSimplifierIns.setData(data);
//监听事件
pointSimplifierIns.on('pointClick pointMouseover pointMouseout', function(e, record) {
console.log(e.type, record);
});
}
//仅作示意
function createPoints(center, num) {
var data = [];
for (var i = 0, len = num; i < len; i++) {
data.push({
position: [
center.getLng() + (Math.random() > 0.5 ? 1 : -1) * Math.random(),
center.getLat() + (Math.random() > 0.5 ? 1 : -1) * Math.random()
]
});
}
return data;
}
接口文档
构造参数
参数名称 | 类型 | 说明 |
---|---|---|
| 地图对象实例,用于显示相关的Marker | |
|
| 绘制用图层的叠加顺序值 。如果需要叠加在地图的最上层,可以设置一个较大的值,比如300 |
|
| 数据源数组,每个元素即为点相关的信息 |
|
| 返回数据项中的经纬度信息
比如:
|
|
| 返回鼠标Hover时显示的Title内容
比如:
|
|
| 数据项的优先级比较函数,用于Array.sort(compare);排序后的数组,靠前的优先绘制。
比如:
|
|
| 是否在绘制后自动调整地图视野以适合全部点,默认 |
|
| 绘制引擎的构造类(Function,详见下方 绘制引擎 部分),可选值有:
|
|
| 绘制引擎的构造参数,请参见下方 绘制引擎 部分 |
|
| 四叉树叶子节点中包含的点的最大数量,超过该数量则进行宽高等分,一分为四。默认100。 通常来说,值越小,分叉的可能性越大,一方面,这有助于精细的划分高密度区域,另外一面,也增加了四叉树的节点数量(指数增长),从而有损性能。 |
|
| 四叉树的最大高度。默认16. 超过该高度,即使数量超过 |
|
| 点的范围矩形的最坏宽高比( 取值小于1,大于 1 时会自动取倒数)。 四叉树的根节点是根据点的分布范围构建的,分叉之后的宽高比也与根节点一致,过宽或者过高的矩形可能会影响TopN区域的视觉观感(比如出现 100*1 的矩形)。默认值为0.6,宽高比小于该阈值时会对范围矩形做一定的扩充,缩小宽和高的差距,使其更加“周正”。 |
方法
方法名称 | 返回值 | 说明 |
---|---|---|
| 立即重新绘制 | |
| 延时设定的毫秒(默认10)后绘制;该时间段内重复调用只会触发一次。该函数适合短时间内多次触发绘制的场景。 | |
| 设定数据源数组,并触发重新绘制。data为空时将清除显示内容。 | |
| 监听 eventName 事件,多个事件用空格分隔 | |
| 注销 eventName 事件,多个事件用空格分隔 | |
| 隐藏 | |
| 显示 | |
|
| 返回是否处于隐藏状态 |
|
| 返回内部使用的绘制引擎的实例 |
|
| 返回内部绘制引擎的参数选项的引用。更改后,调用renderLater()方法重新绘制即可生效。(示例) |
事件
事件名称 | 参数 | 说明 |
---|---|---|
|
| 鼠标点击点的矩形区域时触发 |
|
| 鼠标移入到点的矩形区域时触发 |
|
| 鼠标移出到点的矩形区域时触发 |
绘制引擎
PointSimplifier.Render.Canvas(默认)
构造参数
参数名称 | 类型 | 说明 |
---|---|---|
|
| 是否支持事件(click,mouseover,mouseout),默认为True。事件监听本身对性能有一定的损耗,如果不需要,可以关闭。 |
|
| 是否绘制四叉树,通常在开发调试阶段开启,默认关闭。开启后可以通过 |
|
| 是否绘制位置点,通常在开发调试阶段开启,辅助设定点的绘制区域的偏移(比如圆形的定位点在中心,而水滴形状的定位点在底部中心位置),默认关闭。 开启后可以通过 |
|
| 是否绘制 Shadow Point ,默认关闭。 开启后可以通过 该功能有助于直观的分辨哪些点的空间被挤占了。但是,绘制的点的数量将大幅增加(相当于规避了占位检测的过滤功能),建议谨慎开启。 |
|
| 点的样式 (调整样式Demo),属性取值为:
注意: 1)该函数通常只是描绘路径(使用 moveTo,lineTo, arc, arcTo等),尽量不要fill或者stroke,所有点的路径描绘完成后,引擎自己会在尾部调用fill以及stroke,一次性绘出所有路径。 2)x, y, width, height 的数值与视觉上的数值在高清屏幕时(window.devicePixelRatio>1)会有差异,比如pointStyle.width = 4, 如果屏幕的devicePixelRatio=2,那么content函数接收的width参数就会是8。因此,不要在该函数中使用固定数值。 示例:
PointSimplifier同时提供了一个快捷方法用于创建图片内容的content(function):
示例:
图片的绘制性能相对较差,建议优先考虑形状。 |
|
| 点的”硬核空间“的样式,取值参见 pointHardcoreStyle的 红色圈为pointHardcoreStyle,篮色圈为pointStyle。 ![]() |
|
| 定位点的样式, 定位点有助于辅助设定 ![]() |
|
| 鼠标Hover时绘制的覆盖点的样式,取值参见 ![]() |
|
| Shadow Point(空间被挤占的点)的样式, |
|
| TopN区域的样式, 取值参见 1、 2 、 3、增加属性 |
|
| 根据密度计算TopN区域的分数,范围为1-10,就近取整。
默认的实现,简单来说就是: Log2(区域内所有点的平铺面积 / 区域面积)
|
| | 四叉树的样式, |
|
| 鼠标Hover时显示的Title(如下图红框部分)的样式,属性取值:
![]() |
|
| 返回一个面积阈值,当四叉树的节点区域小于该阈值时,会进行TopN选取。推荐使用一个视觉上可分辨的较小面积,默认10*10。
|
| | 返回某个区域内按优先级(由 compareDataItem 确定)选取的点的数量
|
PointSimplifier.Render.Canvas.GroupStyleRender(样式分组引擎)
继承自 PointSimplifier.Render.Canvas,额外增加如下构造参数以支持定义样式分组(示例)
构造参数
参数名称 | 类型 | 说明 |
---|---|---|
|
| 返回某个数据项的分组Id,函数类型如下:
|
|
| 如果是Object,则取值为:
如果是Function,则类型为:
样式配置的属性取值如下:
|