示例中心
功能在线体验
控制台

高德 开发 地图 JS API 参考手册 - UI组件库 其他组件 标注列表

更新时间:2018年07月02日

MarkerList,即点标注(Marker)+ 列表(List),是一类非常典型的地图应用,通常包括如下的需求片段:

  • 存在一组包含经纬度信息的数据,比如连锁店面的信息,地点的搜索结果等等,每一条数据可称为“数据项”。
  • 要在地图上用Marker标识出各个数据项的位置;Marker上支持打开一个信息窗体(infoWindow)来展示数据项的相关信息。
  • 要构建一个列表(如上方示例的右侧部分),每个列表节点(ListElement)展示数据项的相关信息,比如名称,地址,介绍等等
  • 要支持互动,比如选中,点击Marker,点击列表节点,鼠标Hover列表节点等等;还要支持联动,比如点击列表节点时,要把关联的Marker移动到地图中心等等。

借助MarkerList,开发者可以摆脱一些较复杂的逻辑(比如数据、Marker、列表、事件的管理), 将精力集中到如下层面:

  • UI展示:给定一条数据,要构造什么样的Marker,什么样的列表节点,什么样的信息窗体
  • 事件处理:给定一个事件,比如makerClick,各个关联的对象(数据项,Marker,列表节点)怎么响应这个事件

名词释义

名称

说明

数据源(data) 

一个数组,每个元素即数据项(dateItem) 

数据项(dataItem) 

数据源数组的元素,数据项自身的格式没有强制要求,但需要包含或者索引一些必要的信息,包括Id,位置信息等 

数据项Id(dataId) 

数据项的Id,该Id可以唯一标识该条数据,不能重复(确实没有的话,可以使用数据项索引替代) 

数据项索引(dataIndex) 

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

列表节点(listElement) 

列表节点是由开发者自由构建的Dom节点,最终会被append到开发者指定的Dom容器中;节点的tagName没有限制,常用的有LI,DIV等。

记录(record) 

数据项及其关联的对象并在一起构成一条记录,其内容包括:数据项,数据项Id,数据项索引,以及利用数据项构建的Marker,列表节点,信息窗体等,结构示例如下:

{
	id: dataId, //数据项Id
	index: dataIndex, //数据项索引
	data: dataItem, //数据项
	marker: marker, //点标注 
	listElement: listElement, //列表节点
	infoWindow: infoWindow //打开的信息窗体
}

通常,在事件响应时会拿到一个record参数,开发者可以借此操控相关的marker,listElement等,从而方便地实现联动。

回收资源(

recycledMarker,

recycledListElement,

recycledInfoWindow) 

在数据源会被刷新的场景下,比如Ajax式的数据翻页,可以利用“回收资源“来提升性能。如果仅需要展示一次数据,可以忽略这个内容。


以翻页为例,假定每页数据长度是10,那么首次绘制后,页面上会存在10个Marker,10个列表节点;此时翻页更新数据,再次新建10个新的Marker和列表节点是可以的,但更好的做法是:更新页面上已经存在的Marker和列表节点,与新建相比,资源更加节约,性能更好。

如何使用

1、引入UI组件库

2、MarkerList依赖jQuery或者Zepto,请参见这里确定是否需要进行DomLibrary设置。

3、加载MarkerList(模块名:ui/misc/MarkerList),示例

//加载MarkerList,loadUI的路径参数为模块名中 'ui/' 之后的部分    
AMapUI.loadUI(['misc/MarkerList'], function(MarkerList) {
    //启动页面
    initPage(MarkerList);
});

function initPage(MarkerList) {
    //创建一个实例
    var markerList = new MarkerList({
        map: map, //关联的map对象
        listContainer: 'my-list', //列表的dom容器的节点或者id, 用于放置getListElement返回的内容
        getDataId: function(dataItem, index) {
            //返回数据项的Id
            return dataItem.id;
        },
        getPosition: function(dataItem) {
            //返回数据项的经纬度,AMap.LngLat实例或者经纬度数组
            return dataItem.position;
        },
        getMarker: function(dataItem, context, recycledMarker) {
            var content = '标注: ' + (context.index + 1) + '',
                label = {
                    offset: new AMap.Pixel(16, 18),
                    content: content
                };

            if (recycledMarker) {
                //存在可回收利用的marker,直接setLabel返回
                recycledMarker.setLabel(label);
                return recycledMarker;
            }
            //返回一个新的Marker
            return new AMap.Marker({
                label: label
            });
        },
        getInfoWindow: function(dataItem, context, recycledInfoWindow) {
            var tpl = '<p><%- dataItem.id %>:<%- dataItem.desc %><p>';
            //MarkerList.utils.template支持underscore语法的模板
            var content = MarkerList.utils.template(tpl, {
                dataItem: dataItem,
                dataIndex: context.index
            });
            if (recycledInfoWindow) {
                //存在可回收利用的infoWindow, 直接setContent返回
                recycledInfoWindow.setContent(content);
                return recycledInfoWindow;
            }
            //返回一个新的InfoWindow
            return new AMap.InfoWindow({
                offset: new AMap.Pixel(0, -23),
                content: content
            });
        },
        getListElement: function(dataItem, context, recycledListElement) {
            var tpl = '<p><%- dataItem.id %>:<%- dataItem.desc %><p>';
            var content = MarkerList.utils.template(tpl, {
                dataItem: dataItem,
                dataIndex: context.index
            });
            if (recycledListElement) {
                //存在可回收利用的listElement, 直接更新内容返回
                recycledListElement.innerHTML = content;
                return recycledListElement;
            }
            //返回一段html,MarkerList将利用此html构建一个新的dom节点
            return '<li>' + content + '</li>';
        }
    });

    //监听选中改变
    markerList.on('selectedChanged', function(event, info) {});

    //监听Marker和ListElement上的点击,详见markerEvents,listElementEvents
    markerList.on('markerClick listElementClick', function(event, record) {});

    //构建数据源,数据项本身没有格式要求,但需要支持getDataId和getPosition
    var data = [{
        id: 'A',
        position: [116.020764, 39.904989],
        desc: '数据_1'
    }, {
        id: 'B',
        position: [116.405285, 39.904989],
        desc: '数据_2'
    }, {
        id: 'C',
        position: [116.789806, 39.904989],
        desc: '数据_3'
    }];

    //绘制数据源,Let's go!
    markerList.render(data);

    //清除数据
    //markerList.render([]);
}

示例中心

接口文档

构造参数

参数名称

类型

说明

map

AMap.Map

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

listContainer

String|HTMLElement

列表容器的dom节点或者Id

getPosition

Function

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


@param  {*} dataItem 数据项

@return {AMap.LngLat|Array.<number>} 

                返回经纬度实例(AMap.LngLat)或者经纬度数字组成的数组([lng, lat])


比如:

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

getDataId

Function

返回数据项Id,Id具备唯一性;实在没有的话,可以用数据项索引(dataIndex)代替。


@param {*} dataItem 数据项

@param {number} dataIndex 数据项索引

@return {String} 返回Id


比如:

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

getMarker

Function

根据数据项,返回一个Marker或者其子类(比如SimpleMarker)的实例(不需要设置map和position)


@param {*} dataItem 数据项 

@param {Object} context 数据项相关上下文,

               context.index 即数据项索引,context.id即数据项id

@param {AMap.Marker} recycledMarker 可供回收利用的Marker,

                如recycledMarker不为空,可更新其内容后直接返回

@return {AMap.Marker} 返回一个Marker的实例


推荐的做法是:recycledMarker参数为空时创建新的Marker,否则更新recycledMarker并返回,比如:

function(dataItem, context, recycledMarker) {
    var label = {
        offset: new AMap.Pixel(16, 18),
        content: 'Marker: ' + (context.index + 1) + '';
    };
    if (recycledMarker) {  //存在可回收利用的marker
        recycledMarker.setLabel(label);  //更新label内容
        return recycledMarker; //直接返回
    }
    //返回一个新的Marker
    return new AMap.Marker({
        label: label
    });
}


SimpleMarker示例 SvgMarker示例

getInfoWindow

Function 

根据数据项,返回一个InfoWindow或者其子类(比如SimpleInfoWindow)的实例( 不需要设置map和position ) 

 

@param {*} dataItem 数据项 

@param {Object} context 数据项相关上下文,

              context.index 即数据项索引,context.id即数据项id

@param {AMap.InfoWindow} recycledInfoWindow 可供回收利用的InfoWindow,

               如recycledInfoWindow不为空,可更新其内容后直接返回

@return {AMap.InfoWindow} 返回一个InfoWindow或者InfoWindow子类(比如SimpleInfoWindow)的实例


推荐的做法是: recycledInfoWindow 参数为空时创建新的InfoWindow,否则更新 recycledInfoWindow 并返回,比如:

function(dataItem, context, recycledInfoWindow) {
    var content = 'InfoWin: ' + (context.index + 1) + '';
    if (recycledInfoWindow) { //存在可回收利用的infoWindow,
        recycledInfoWindow.setContent(content);   //更新内容
        return recycledInfoWindow;     //直接返回
    }
    //返回一个新的InfoWindow
    return new AMap.InfoWindow({
        offset: new AMap.Pixel(0, -23),
        content: content
    });
}


SimpleInfoWindow示例

getListElement

Function 

根据数据项,返回一个Dom节点,或者该节点的html(outerHTML)构造 


@param {*} dataItem 数据项 

@param {Object} context 数据项相关上下文,

             context.index 即数据项索引,context.id即数据项id

@param {HTMLElement} recycledListElement 可供回收利用的ListElement,

              如recycledListElement不为空,可更新其内容后直接返回

@return {HTMLElement|String}  返回一个Dom节点或者一段闭合的Html,该节点会插入到 listContainer 中


推荐的做法是: recycledListElement 参数为空时创建新的节点或者构建html(可以借助MarkerList.utils.template(underscore模板方法),以及MarkerList.utils.$(jQuery/Zepto))返回,否则更新 recycledListElement 的内容并返回, 比如:

function(dataItem, context, recycledListElement) {
    var tpl = '<p><%- dataItem.id %>:<%- dataItem.desc %><p>';
    //利用模板构建html内容
    var content = MarkerList.utils.template(tpl, {
        dataItem: dataItem,
        dataIndex: context.index
    });
    if (recycledListElement) {   //存在可回收利用的listElement
        recycledListElement.innerHTML = content; //更新innerHTML
        return recycledListElement; // 直接返回
    }
    //返回一段闭合的html,创建一个新的LI节点
    return '<li>' + content + '</li>';
}

listElementEvents

Array

列表节点上需要被监听的全部事件名称(列表的Dom节点触发的事件),默认的取值是:['click']。如需要增加监听mouseover事件,需要设置为['click', 'mouseover']


如何监听:


监听的事件名称为listElement + 事件名首字母大写,比如:

.on('listElementClick', function(event, record)...


监听多个事件时用空格分开,比如取值包括'mouseenter','mouseleave'时:

.on('listElementMouseenter listElementMouseleave', function(event, record)...


事件监听示例

markerEvents

Array

Marker上需要被监听的全部事件(由Marker触发的事件)名称 ,默认的取值是:['click'] 。如需要增加监听mouseover事件,需要设置为['click', 'mouseover']。 

 

如何监听:


监听的事件名称为marker + 事件名首字母大写,比如:

.on('markerClick', function(event, record)...


监听多个事件时用空格分开,比如取值包括'mouseover','mouseout'时: 

.on('markerMouseover markerMouseout', function(event, record)...


事件监听示例

infoWindowEvents

Array

InfoWindow上需要被监听的事件列表(InfoWindow的Dom容器触发的事件),默认的取值是:['click'] 。 如需要增加监听dblclick事件,需要设置为['click', 'dblclick']。  


如何监听: 


监听的事件名称为infoWindow + 事件名首字母大写,比如:

.on('infoWindowClick', function(event, record)...


监听多个事件时用空格分开,比如取值包括'click','dblclick'时:  

.on('infoWindowClick infoWindowDblclick', function(event, record)...


事件监听示例

autoSetFitView

Boolean

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

selectedClassNames

String

选中状态时,列表节点和Marker的Dom容器上附带的class,多个class name可以用空格分开,默认取值:'selected'。可以借此编写css控制选中状态的UI效果。


示例

makeSelectedEvents 

Array

默认触发相关记录被“选中”(单选)的事件名称(MarkerList自身触发的事件),默认的取值是:

['markerClick', 'listElementClick'],也就是关联的Marker和ListElement被点击时。


如果需要调整选中的触发行为,可以将此值置空,并借助事件监听和selectBy系列方法控制选中,示例

onSelected

Function

可选值,定义选中后需要执行的默认行为, 包括:

  1. 置顶显示关联的Marker(marker.setTop)
  2. 地图中心移动到Marker对应的位置
  3. 在Marker上展开InfoWindow

如果要修改这些行为,请将该值置null,并监听selectedChanged 事件手动进行选中处理,示例



方法

方法名称

返回值

说明

render(data:Array)


传入数据源data,绘制图面;图面绘制后,可以通过  getAllRecords 获取所有的记录,包括Marker,列表节点等

getData()

Array

返回数据源数组(注意,这个数组不是上述render中传入的data,而是一个浅层的拷贝,即每个元素的引用没变,但数组本身是个新数组)

getAllRecords()

Array

返回所有记录,每条记录中包括数据项,数据项Id,数据项索引及其关联的Marker、ListElement。通常要等到render之后才能调用。

getAllListElements()

Array

返回有数据对应的所有的列表节点

getAllMarkers()

Array

返回有数据对应的所有的Marker

getInfoWindow()

Amap.InfoWindow

返回 InfoWindow ;因为 InfoWindow 每次只能显示一个,所以与Marker不同,所有的数据项共用唯一的一个InfoWindow

getRecordByDataId(id:String)

Record

遍历所有记录,返回其中 record.id == id 的记录。 

getRecordByDataIndex

(index:number)

Record

遍历所有记录,返回其中 record.index == index 的记录

getRecordByDataItem

(dataItem:*)

Record 

遍历所有记录,返回其中 record.data == dateItem 的记录

getRecordByMarker

(marker:Amap.Marker)

Record

遍历所有记录,返回其中 record.marker == marker 的记录

getRecordByListElement

(listElement:HTMLElement)

Record

遍历所有记录,返回其中 record.listElement == listElement 的记录

getDataIdOfInfoWindow

(infoWindow:AMap.InfoWindow)

String

返回InfoWindow关联的数据项Id

getDataIdOfListElement

(listElement:HTMLElement) 

String

返回列表节点关联的数据项Id

getDataIdOfMarker

(marker:Amap.Marker) 

String

返回Marker管理的数据项Id

getSelectedDataId()

String

返回当前选中的数据项Id

getSelectedRecord()

Record

返回当前处于选中状态的记录

isSelectedDataId(id:String)

Boolean

判断传入的数据项Id是否是当前选中的Id

clearSelected()


清除选中

selectByDataId(id:String)

Record

遍历所有记录,选中其中 record.id == id 的记录。 

selectByDataIndex(index:number)

Record

遍历所有记录,选中其中 record.index == index 的记录

selectByDataItem(dataItem:*)

Record

遍历所有记录,选中其中 record.data == dataItem 的记录 

selectByDataReverseIndex

(reverseIndex:number)

Record

遍历所有记录,选中其中 记录总数-1-record.index ==  reverseIndex (即倒叙索引)的记录 

selectByRecord

(record:Record, [sourceEvent:Event])

Record

选中传入的记录。 


sourceEvent为触发该选中的来源事件,比如 markerClick的事件处理函数中获得的event参数;sourceEvent会影响selectedChanged 事件抛出的 sourceEventInfo 信息(详见下方事件部分)

openInfoWindowOnRecord

(record:Recod)


根据record的相关信息(包括位置,内容等)展开InfoWindow

closeInfoWindow()


关闭InfoWindow 

clearData()


清空数据以及关联的UI对象,包括Marker和列表节点

clearRecycle()


清空回收站,回收站包括未被使用的Marker和列表节点。


某些场景下可能需要,比如绘制的第一份数据长度是100,后面的数据长度都是20,那么回收站中将存在规模在80左右的多余资源,此时可以考虑在render完成后调用此方法。

trigger

(eventName:String, [arg1:*,arg2:*...]) 


触发 eventName 事件


对应的监听方法为:

.on(eventName, function(event, arg1, arg2...){
})

监听方法的event参数的结构是:

@prop {String} type 即eventName

@prop {MarkerList} target MarkerList实例本身

triggerWithOriginalEvent

(eventName:String, originalEvent:Event, 

[arg1:*, arg2:*...])


触发 eventName 事件,并利用originalEvent构造监听函数的event参数


对应的监听方法为:

.on(eventName, function(event, arg1, arg2...){
})

监听方法的event参数的结构是:

@prop {String} type 即eventName

@prop {*} target 即originalEvent.target

@prop {Event} originalEvent 即originalEvent

on(eventName:String, handler:Function)


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

off(eventname:String, handler:Function) 


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

静态属性

属性名称

说明

 MarkerList .utils

utils下包含一些辅助工具,包括:


1、template

underscore的模板方法,用法示例:

 var tpl = '<p><%- dataItem.id %>:<%- dataItem.desc %><p>';
 var content = MarkerList.utils.template(tpl, {
     dataItem: dataItem,
     dataIndex: context.index
 });


underscore模板语法包括以下三种:

<%- foo %>,html编码后输出

<%= foo %>,原值输出

<% ..code.. %>,js代码,比如if, for等


2、$ 

DomLibrary (jQuery/Zepto),用法示例:

MarkerList.utils.$('<div/>').appendTo(document.body)

事件

事件名称

参数

说明

renderComplete

event:{type:String,target:MarkerList} 事件

records:Array 本次绘制相关的所有记录

数据绘制完成后触发

selectedChanged

event: {type:String,target:MarkerList}  事件

changeInfo:{

  selected:Record, 选中的记录

  unSelected:Record, 取消选中的记录

  selectAgain:Boolean,是否选中了已经处于选中状态的记录

  sourceEventInfo:{

     sourceEvent:Event, 触发该选中的原始事件,可能为空

     isMarkerEvent:Boolean, 原始事件是否由Marker触发

     isListElementEvent:Boolean,原始事件是否由列表节点触发

  }

} 改变的详细信息

选中改变时触发


selected为被选中的记录


unSelected为被取消选中的记录(因为是单选)


selectAgain 为真时表示选中了本来就是选中状态的记录;如果您希望此时取消选中,可以在事件响应中手动调用方法:

this.clearSelected()


sourceEvent为触发该选中的原始事件(通常为makeSelectedEvents 中配置的事件,比如markerClick),如果使用selectBy*系列方法直接触发,则可以为空值。


某些场景下可能需要区别对待不同来源的选中行为,比如点击Marker选中时闪动关联的列表节点,点击列表节点选中时闪动关联的Marker,此时可以依靠 isMarkerEventisListElementEvent进行判断 


示例

marker + [Marker事件首字母大写]

event:{

 type:String,

 target:Marker,

 originalEvent:MarkerEvent

}  事件

record:Record Marker所属的记录

与构造参数中的 markerEvents 对应,比如markerEvents包含:

click

mouseover

则会触发:

markerClick

markerMouseover

listElement + [DOM事件首字母大写] 

event:{

 type:String,

 target:HTMLElement,

 originalEvent:DOMEvent

} 事件 

record:Record ListElement所属的记录

与构造参数中的  listElementEvents 对应,比如listElementEvents 包含:

click

mouseenter

则会触发:

listElementClick,

listElementMouseenter

infoWindow + [DOM事件首字母大写] 

 

event:{

 type:String,

 target:HTMLElement,

 originalEvent:DOMEvent

} 事件

record:Record infoWindow所属的记录

与构造参数中的  infoWindowEvents 对应,比如infoWindowEvents包含:click

则会触发:

infoWindowClick

markerWillAddToMap

event:{type:String,target:MarkerList}  事件

record:Record Marker所属的记录

记录中的marker即将被添加到map

markerAddToMap

event:{type:String,target:MarkerList}  事件

record:Record Marker所属的记录

记录中的marker已经被添加到map

markerWillRemoveFromMap

event:{type:String,target:MarkerList} 事件

record:Record Marker所属的记录

记录中的marker即将从map上删除

markerRemoveFromMap

event:{type:String,target:MarkerList}  事件

record:Record Marker所属的记录

记录中的marker已经从map上删除

listElementWillAddToContainter

event:{type:String,target:MarkerList}  事件

record:Record ListElement所属的记录

记录中的listElement即将被添加到listContainer 

listElementAddToContainter

event:{type:String,target:MarkerList}  事件 

record:Record ListElement所属的记录

记录中的lisElement已经被添加到 listContainer  

listElementWillRemoveFromContainter

event:{type:String,target:MarkerList}  事件 

record:Record ListElement所属的记录

记录中的 lisElement 即将从 listContainer  上删除 

listElementRemoveFromContainter

event:{type:String,target:MarkerList} 事件 

record:Record ListElement所属的记录

记录中的 lisElement 已经从 listContainer  上删除 

infoWindowWillAddToMap

event:{type:String,target:MarkerList}  事件 

record:Record infoWindow所属的记录

记录中的InfoWindow即将被添加到map 

infoWindowAddToMap

event:{type:String,target:MarkerList}  事件 

record:Record infoWindow所属的记录

记录中的  InfoWindow 已经被添加到map 

infoWindowWillRemoveFromMap

event:{type:String,target:MarkerList}  事件 

record:Record infoWindow所属的记录

记录中的 InfoWindow 即将从map上删除 

infoWindowRemoveFromMap

event:{type:String,target:MarkerList}  事件 

record:Record infoWindow所属的记录

记录中的 InfoWindow 已经从map上删除 

附带其他覆盖物

开发者如果需要附带绘制多边形,圆,线段等其他类型的覆盖物,可以通过监听 markerAddToMapmarkerRemoveFromMap 事件,在Marker添加到地图上时创建相关的覆盖物,并在移除时一并移除。如果开发者不希望看到Marker,可以在Marker的构造参数中增加 visible:false 

Marker附带Circle示例






移动端
示例中心
功能
在线体验
常见问题