开发 AMapUI 组件库 参考手册 海量数据 海量点展示

海量点展示 最后更新时间: 2023年08月08日

PointSimplifier是一个针对海量点展示场景的组件,能够支持较大规模的经纬度数据,以及配置丰富的展示效果。

上方是全国范围内100万规模的点的一些效果截图。可以看出,PointSimplifier在低级别下并没有绘制出全部的点,而是选取了其中的一部分,选取的策略(可配置)简单来说分如下两步:

  1. TopN选取:在高密度区域(上图的东南部,带背景色),排序选出高优先级的N个点,其余点抛弃。
  2. 占位检测:绘制之前,如果发现某个点需要占用的矩形空间已经有其他点存在了,则不绘制该点,直接跳过。

通过以上两步,最终显示的点的规模可以被控制在浏览器允许的合理范围以内,效果上也保留了点的分布特征,能够直观的分辨密集区域和稀疏区域。

浏览器支持:

PointSimplifier目前依赖Canvas进行绘制,因此不支持IE9及以下浏览器。

名词释义

名称

说明

数据源(data)

一个数组,每个元素即点的相关信息(dataItem)   

数据项(dataItem)  

数据源数组的元素,通常就是点的相关信息。数据项自身的格式没有强制要求,只要能索引或者包含点的信息即可。

数据项索引(dataIndex)  

数据项在数据源数组中的的索引位置,即 0,1,2....   

四叉树

一种空间索引结构。简单来说,点的范围构成一个矩形,如果这个矩形中包含的点的数量大于某个阈值,则宽高等分,切出4个面积相等的小矩形(称为四叉树节点),然后对这4个小矩形继续同样的步骤。

下方左侧为四叉树的示意图,右侧为 PointSimplifier  开启 drawQuadTree 参数的效果。

TopN区域

四叉树节点代表的区域,如果该区域的视图面积小于一定阈值(比如10*10像素),则仅仅选出区域内高优先级的N个点进行绘制,该区域就是一个TopN区域。通常来说,地图的zoom值越小,节点的视图面积越小,越有可能成为TopN区域。

下图中红色黑边的小矩形即为TopN区域,可以看出,它们都是小面积的四叉树节点。

Point Hardcore

点的“硬核”区域(矩形),该区域为该点独占,会起到“占位”的作用。

直观效果可以访问这里(调整 pointHardcoreStyle 中的width 和 height)。 

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;
}

示例中心

接口文档

构造参数

参数名称

类型

说明

map

AMap.Map

地图对象实例,用于显示相关的Marker

zIndex

Number

绘制用图层的叠加顺序值 。如果需要叠加在地图的最上层,可以设置一个较大的值,比如300

data

Array

数据源数组,每个元素即为点相关的信息

getPosition

Function

返回数据项中的经纬度信息

@param  {*} dataItem 数据项

@param  {number} dataIndex 数据项索引 

@return {AMap.LngLat|Array.<number>} 返回经纬度实例(AMap.LngLat)或者经纬度数字组成的数组([lng, lat])

比如:

function(dataIte, dataIndex) {
  return [dataItem.lng, dataItem.lat];
}

getHoverTitle

Function

返回鼠标Hover时显示的Title内容

@param {*} dataItem 数据项

@param {number} dataIndex 数据项索引

@return {String} 返回Title内容

比如:

function(dataItem, dataIndex) {
  return dataItem.name;
}

compareDataItem

Function

数据项的优先级比较函数,用于Array.sort(compare);排序后的数组,靠前的优先绘制。

@params {*} dataItemA 数据项A

@params {*} dataItemB 数据项B

@params {number} dataIndexA 数据项A的索引位置

@params {number} dataIndexB 数据项B的索引位置

@return {number} -1, 0, 1

比如:

function(a, b, aIndex, bIndex) {
  //数据源中靠后的元素优先,index大的排到前面去
  return aIndex > bIndex ? -1 : 1;
}

autoSetFitView

Boolean

是否在绘制后自动调整地图视野以适合全部点,默认true

renderConstructor

Constructor

绘制引擎的构造类(Function,详见下方 绘制引擎部分),可选值有:

PointSimplifier.Render.Canvas (默认)

PointSimplifier.Render.Canvas.GroupStyleRender (支持样式分组,示例

如果有特殊需求,也可以参考GroupStyleRender的源码自主实现,示例

renderOptions

Object

绘制引擎的构造参数,请参见下方 绘制引擎部分

maxChildrenOfQuadNode

Number

四叉树叶子节点中包含的点的最大数量,超过该数量则进行宽高等分,一分为四。默认100。

通常来说,值越小,分叉的可能性越大,一方面,这有助于精细的划分高密度区域,另外一面,也增加了四叉树的节点数量(指数增长),从而有损性能。

maxDepthOfQuadTree

Number

四叉树的最大高度。默认16. 超过该高度,即使数量超过 maxChildrenOfQuadNode 的限制,也不再分叉。

badBoundsAspectRatio

Number

点的范围矩形的最坏宽高比( 取值小于1,大于 1 时会自动取倒数)。

四叉树的根节点是根据点的分布范围构建的,分叉之后的宽高比也与根节点一致,过宽或者过高的矩形可能会影响TopN区域的视觉观感(比如出现 100*1 的矩形)。默认值为0.6,宽高比小于该阈值时会对范围矩形做一定的扩充,缩小宽和高的差距,使其更加“周正”。

方法

方法名称

返回值

说明

render()

立即重新绘制

renderLater([delay:number])

延时设定的毫秒(默认10)后绘制;该时间段内重复调用只会触发一次。该函数适合短时间内多次触发绘制的场景。

setData(data:Array)

设定数据源数组,并触发重新绘制。data为空时将清除显示内容。

on(eventName:String, handler:Function)

监听 eventName 事件,多个事件用空格分隔  

off(eventname:String, handler:Function)

注销 eventName 事件,多个事件用空格分隔 

hide()

隐藏

show()

显示

isHidden()

Boolean

返回是否处于隐藏状态

getRender()

Render

返回内部使用的绘制引擎的实例

getRenderOptions()

Object

返回内部绘制引擎的参数选项的引用。更改后,调用renderLater()方法重新绘制即可生效。(示例

事件

事件名称

参数

说明

pointClick

event:{type:String}  事件

point:{ data:dataItem, index:number} 数据项信息

鼠标点击点的矩形区域时触发  

pointMouseover

event:{type:String}  事件

point:{ data:dataItem, index:number} 数据项信息

鼠标移入到点的矩形区域时触发

pointMouseout

event:{type:String}  事件

point:{ data:dataItem, index:number} 数据项信息

鼠标移出到点的矩形区域时触发   

绘制引擎 

PointSimplifier.Render.Canvas(默认)

构造参数

参数名称

类型

说明

eventSupport 

Boolean 

是否支持事件(click,mouseover,mouseout),默认为True。事件监听本身对性能有一定的损耗,如果不需要,可以关闭。

drawQuadTree

Boolean

是否绘制四叉树,通常在开发调试阶段开启,默认关闭。开启后可以通过 quadTreeStyle 来调整样式

drawPositionPoint

Boolean

是否绘制位置点,通常在开发调试阶段开启,辅助设定点的绘制区域的偏移(比如圆形的定位点在中心,而水滴形状的定位点在底部中心位置),默认关闭。 开启后可以通过  pointPositionStyle  来调整样式 

drawShadowPoint

Boolean

是否绘制 Shadow Point ,默认关闭。 开启后可以通过  shadowPointStyle  来调整样式  。

该功能有助于直观的分辨哪些点的空间被挤占了。但是,绘制的点的数量将大幅增加(相当于规避了占位检测的过滤功能),建议谨慎开启。

pointStyle

Object

点的样式 (调整样式Demo),属性取值为:

{
  content: {string|function} 
           点的绘制内容,详见下
  offset: { [number, number] } 
           绘制区域相对于定位点的偏移,可以使用绝对数值,也可以使用百分比['-50%', '-100%']
           百分比分别相对于width和height
  width: {number}
          绘制区域矩形的宽度
  height: {number}
          绘制区域矩形的高度
  fillStyle: {string}
          填充色,比如 red, rgb(255,0,0), rgba(0,0,0,1)等
  lineWidth:  {number}
          描边宽度
  strokeStyle: {string}
          描边色,比如 red, rgb(255,0,0), rgba(0,0,0,1)等
}

content的取值有两类:

  1. {string}, 可以是 rect(矩形), circle(圆形),none(空)

  1. {function},  根据矩形范围,描绘出点的形状路径或者绘制图片

@param {Canvas.Context}  Canvas的2d Context对象

@param {number} x 绘制区域左上角横坐标(相对于map容器)

@param {number} y 绘制区域左上角纵坐标(相对于map容器)

@param {number} width 绘制区域的宽度

@param {number} height 绘制区域的高度

注意:

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。因此,不要在该函数中使用固定数值。

示例:

function(ctx, x, y, width, height) {
  //绘制一个矩形
 ctx.moveTo(x, y); //移动到左上角
 ctx.lineTo(x + width, y);  //连接到右上角
 ctx.lineTo(x + width, y + height);//连接到右下角
 ctx.lineTo(x, y + height); //连接到左下角
 ctx.lineTo(x, y);//连接到左上角
}

PointSimplifier同时提供了一个快捷方法用于创建图片内容的content(function):

PointSimplifier.Render.Canvas.getImageContent ,该函数的返回值直接赋给content即可。

示例:

content = PointSimplifier.Render.Canvas.getImageContent( '图片地址',   
function onload() {
    //图片加载成功,重新绘制一次
    pointSimplifierIns.renderLater();
},
function onerror(e) {
    alert('图片加载失败!');
});

图片的绘制性能相对较差,建议优先考虑形状。

pointHardcoreStyle

Object

点的”硬核空间“的样式,取值参见 pointStyle 。默认 fillStylestrokeStyle 以及content属性为空,即不显示。

pointHardcoreStyle的 widthheight会起到空间占位的效果,默认情况下与pointStyle相同。如果 pointHardcoreStyle中的width/height 小于 pointStyle中的width/height, 点之间就会产生重叠(下图左侧),反之,点之间会有空隙(下图右侧)。

红色圈为pointHardcoreStyle,篮色圈为pointStyle。

pointPositionStyle

Object

定位点的样式, drawPositionPoint 开启时有效,取值参见pointStyle

定位点有助于辅助设定pointStyle中的offset。比如下图左侧,圆形的定位点在中心,offset应该为['-50%', '-50%'];而右侧锥形的定位点在底部中点,此时offset应该为['-50%', '-100%']

pointHoverStyle

Object

鼠标Hover时绘制的覆盖点的样式,取值参见 pointStyle 。默认为黄色描边的圆圈,见下图。

shadowPointStyle

Object

Shadow Point(空间被挤占的点)的样式, drawShadowPoint 开启时有效,取值参见pointStyle

topNAreaStyle

Object

TopN区域的样式, 取值参见pointStyle ,但有以下不同之处:

1、widthheight无效,由四叉树节点自身决定

2 、content为circle时,circle的直径为width和height中的较小值

3、增加属性 autoGlobalAlphaAlpha ,标识不透明度的范围([min, max]),默认为 [ 0.1, 1 ]。具体数值由 getAreaScore 计算,按10段等分,分数高的不透明度也高。如不需要该效果,可以设置为false

getAreaScore

Function

根据密度计算TopN区域的分数,范围为1-10,就近取整。

@param {number} minScore 最小取值,默认为1

@param {number} maxScore 最大取值,默认为10

@param {x:number, y:number, width:number, height:number} bounds 区域的边界信息 

@param {number} descendantsNum 该区域包含的点的总数

@param {width:number, height:number} pointSize 点的尺寸,源自参数pointStyle

@return {number}  

默认的实现,简单来说就是: Log2(区域内所有点的平铺面积 / 区域面积)

function(minScore, maxScore, bounds, descendantsNum, pointSize) {
  var ratio = descendantsNum * pointSize.width * pointSize.height / bounds.width / bounds.height;
  return Math.round(Math.log(ratio) / Math.log(2));
}

quadTreeStyle

 Object 

四叉树的样式,  drawQuadTree 开启时有效,取值(仅包括属性fillStyle,lineWidth,strokeStyle)参见pointStyle。 

hoverTitleStyle

Object

鼠标Hover时显示的Title(如下图红框部分)的样式,属性取值:

{
  position: {string}  title的位置,left 或者 top
  classNames: {string} title所用的dom节点上的classNames,多个用空格分开,可借此调整dom节点的样式
  offset: { [number, number] } title的dom节点相对于定位点的偏移
}

 getAreaSizeForTopSelect 

Function

返回一个面积阈值,当四叉树的节点区域小于该阈值时,会进行TopN选取。推荐使用一个视觉上可分辨的较小面积,默认10*10。

@param  {number} zoom map当前的zoom值

@param  {width:number, height:number} pointSize 点的尺寸,源自参数pointStyle

@return {number} 面积阈值

比如:

function(zoom, pointSize) {
  return Math.min(100, pointSize.width * pointSize.height * 1.5);
}

 getNumForTopSelect 

 Function 

返回某个区域内按优先级(由 compareDataItem 确定)选取的点的数量

@param {number} zoom map当前的zoom值 

@param {x:number, y:number, width:number, height:number} bounds 区域的边界信息

@param {number} descendantsNum 该区域包含的点的总数

@param {width:number, height:number} pointSize 点的尺寸,源自参数pointStyle

@return {number} 选取的数量 

比如:

function(zoom, bounds, descendantsNum, pointSize) {
  var idealNum = (bounds.width * bounds.height) / (pointSize.width * pointSize.height);
  return Math.max(3, Math.ceil(idealNum * 1.5));
}

PointSimplifier.Render.Canvas.GroupStyleRender(样式分组引擎)

继承自 PointSimplifier.Render.Canvas,额外增加如下构造参数以支持定义样式分组(示例

构造参数

参数名称

类型

说明

getGroupId

Function

返回某个数据项的分组Id,函数类型如下:

 

@param  {*} dataItem 数据项

@param  {number} dataIndex 数据项索引 

@return {String} 返回该数据项对应的分组Id

groupStyleOptions

Object|Function

如果是Object,则取值为:

{
  id1:样式配置,
  id2:样式配置,
  ....
}

如果是Function,则类型为:

@param  {String} 分组Id 

@return {String} 返回分组Id对应的样式配置

样式配置的属性取值如下:

{
  pointStyle:<同上述pointStyle>,
  pointHardcoreStyle:<同上述pointStyle>,
  pointPositionStyle:<同上述pointPositionStyle>
}

返回顶部 示例中心 常见问题 智能客服 公众号
二维码