在页面添加 JS API 的入口脚本标签,并将其中「您申请的key值」替换为您刚刚申请的 key;
添加div标签作为地图容器,同时为该div指定id属性;
为地图容器指定高度、宽度;#container {width:300px; height: 180px; }
进行移动端开发时,请在head内添加viewport设置,以达到最佳的绘制性能;
在完成如上准备工作之后便可以开始进行开发工作了,查看快速入门。
上一节说明的是最基本的同步加载 JS API 的方式,如果您需要异步加载,比如通过appendChild
,或者通过require
等异步方式来加载,这时需要您需要先准备一个全局的回调函数作为 JS API 异步加载的回调函数,并将其函数名作为callback
参数添加在 JS API 的引用地址后面,此时要注意,回调函数应该在脚本请求发出之前进行声明。异步加载方式只有在回调之后,才能开始调用JSAPI的相关接口。比如
window.onLoad = function(){
var map = new AMap.Map('container');
}
var url = 'https://webapi.amap.com/maps?v=1.4.15&key=您申请的key值&callback=onLoad';
var jsapi = doc.createElement('script');
jsapi.charset = 'utf-8';
jsapi.src = url;
document.head.appendChild(jsapi);
JS API 支持多种加载方式,可以顺序加载也可以异步加载,同时也可以作为一般脚本资源被 RequireJS 等前端框架加载。
之前我们使用的是基本的顺序同步加载方式,这种方式下,地图初始化的代码要放在 JS API 的脚本标签之后:
<script src="https://webapi.amap.com/maps?v=1.4.15&key=您申请的key值"></script>
<script type="text/javascript">
var map = new AMap.Map('container', {
center:[117.000923,36.675807],
zoom:11
});
</script>
异步加载指的是为 JS API 指定加载的回调函数,在 JS API 的主体资源加载完毕之后,将自动调用该回调函数。回调函数应该声明在 JS API 入口文件引用之前,异步加载可以减少对其他脚本执行的阻塞,HTTPS 下我们也建议使用异步方式:
<script type="text/javascript">
window.init = function(){
var map = new AMap.Map('container', {
center:[117.000923,36.675807],
zoom:11
});
}
</script>
<script src="https://webapi.amap.com/maps?v=1.4.15&key=您申请的key值&callback=init"></script>
或者
window.onLoad = function(){
var map = new AMap.Map('container');
}
var url = 'https://webapi.amap.com/maps?v=1.4.15&key=您申请的key值&callback=onLoad';
var jsapi = document.createElement('script');
jsapi.charset = 'utf-8';
jsapi.src = url;
document.head.appendChild(jsapi);
也可以使用RequireJS 等加载,点这里了解更多,在此不一一赘述。
按照「准备」篇完成页面准备工作之后就可以真正开始地图的开发工作了。本篇带您快速了解:地图、图层、点标记、矢量图形、信息窗体、事件的最基本使用方法。
var map = new AMap.Map('container');
创建的同时可以给地图设置中心点、级别、显示模式、自定义样式等属性:
var map = new AMap.Map('container', {
zoom:11,//级别
center: [116.397428, 39.90923],//中心点坐标
viewMode:'3D'//使用3D视图
});
var map = new AMap.Map('container', {
resizeEnable: true,
center: [116.397428, 39.90923],
zoom: 13
});
//实时路况图层
var trafficLayer = new AMap.TileLayer.Traffic({
zIndex: 10
});
map.add(trafficLayer);//添加图层到地图
也可以在地图初始化的时候通过layers属性为地图设置多个图层:
var map = new AMap.Map('container', {
center: [116.397428, 39.90923],
layers: [//使用多个图层
new AMap.TileLayer.Satellite(),
new AMap.TileLayer.RoadNet()
],
zooms: [4,18],//设置地图级别范围
zoom: 13
});
地图 JS API 提供了标准、卫星、路网、路况、建筑等多个官方图层,同时也提供了加载第三方WMS、WMTS、XYZ等标准图层的接口,也提供了把一般的图片、Canvas、视频、热力等作为图层的能力,查看图层相关教程。
JS API 提供了在地图之上绘制覆盖物的能力,比如点标记 Marker、文本标记 Text、圆点标记 CircleMarker。
添加点标记的方法非常简单,比如添加一个默认样式的Marker:
var marker = new AMap.Marker({
position:[116.39, 39.9]//位置
})
map.add(marker);//添加到地图
移除的方法如下:
map.remove(marker)
查看点标记相关教程
也提供了绘制圆Circle、折线 Polyline、多边形 Polygon、椭圆 Ellipse、矩形 Rectangle、贝瑟尔曲线 BesizerCurve等矢量图形的能力,比如添加折线:
var lineArr = [
[116.368904, 39.913423],
[116.382122, 39.901176],
[116.387271, 39.912501],
[116.398258, 39.904600]
];
var polyline = new AMap.Polyline({
path: lineArr, //设置线覆盖物路径
strokeColor: "#3366FF", //线颜色
strokeWeight: 5, //线宽
strokeStyle: "solid", //线样式
});
map.add(polyline);
查看矢量图形关教程
JS API 提供的Map、点标记、矢量图形的实例均支持事件,鼠标或者触摸操作均会触发相应的事件。我们通过给点标记绑定click
事件来简单了解事件系统和信息窗体的基本使用:
var infoWindow = new AMap.InfoWindow({ //创建信息窗体
isCustom: true, //使用自定义窗体
content:'信息窗体', //信息窗体的内容可以是任意html片段
offset: new AMap.Pixel(16, -45)
});
var onMarkerClick = function(e) {
infoWindow.open(map, e.target.getPosition());//打开信息窗体
//e.target就是被点击的Marker
}
var marker = new AMap.Marker({
position: [116.481181, 39.989792]
})
map.add(marker);
marker.on('click',onMarkerClick);//绑定click事件
JS API 提供了众多的插件功能,这些功能不会主动随着 JSAPI 主体资源下发,需要引入之后才能使用这些插件的功能。这些功能包括:
异步加载指的是在 JS API 加载完成之后,在需要使用到某个插件的时候,通过AMap.plugin
方法按需引入插件,在plugin
回调之后使用插件功能。
<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=您申请的key值"></script>
<script type="text/javascript" >
var map = new AMap.Map('container',{
zoom:12,
center:[116.39,39.9]
});
AMap.plugin('AMap.ToolBar',function(){//异步加载插件
var toolbar = new AMap.ToolBar();
map.addControl(toolbar);
});
</script>
AMap.plugin
的第一个参数使用数组即可同时加载引入多个插件。
AMap.plugin(['AMap.ToolBar','AMap.Driving'],function(){//异步同时加载多个插件
var toolbar = new AMap.ToolBar();
map.addControl(toolbar);
var driving = new AMap.Driving();//驾车路线规划
driving.search(/*参数*/)
});
如果希望和 JS API 的主体同步加载某些插件,而不是异步加载,可以在 JS API 的入口地址中添加plugin
参数,将需要使用的一个或者多个插件的名称作为参数即可,这种用法在 JS API 加载完毕之后便可直接使用插件功能了。
<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=您申请的key值&plugin=AMap.ToolBar"></script>
<script type="text/javascript" >
var map = new AMap.Map('mapContainer',{
zoom:12,
center:[116.39,39.9]
});
var toolbar = new AMap.ToolBar();
map.plugin(toolbar);
</script>
需要加载多个插件时,plugin参数中的插件名称之间以逗号分割。
<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=您申请的key值&plugin=AMap.ToolBar,AMap.Driving"></script>
<script type="text/javascript" >
var map = new AMap.Map('mapContainer',{
zoom:12,
center:[116.39,39.9]
});
var toolbar = new AMap.ToolBar();
map.plugin(toolbar);
var driving = new AMap.Driving();
driving.search(/*参数*/)
</script>
即在准备阶段所创建的指定了id的div对象,这个div将作为承载所有图层、点标记、矢量图形、控件的容器。
图层是指能够在视觉上覆盖一定地图范围,用来描述全部或者部分现实世界区域内的地图要素的抽象概念,一幅地图通常由一个或者多个图层组成。如上图中处于整个地图容器最下方的二维矢量图层和实施交通图层。
高德地图 JS API 即提供了标准图层、卫星图层、路网图层、路况图层等官方标准图层接口,又提供了加载其他厂商发布的标准地图服务的图层接口,还提供了加载开发者自己的图片、Canvas、视频、热力数据的图层接口。同时也深度开放了可以自定义绘制方法的自定义图层接口。
矢量图形,一般覆盖于底图图层之上,通过矢量的方式(路径或者实际大小)来描述其形状,用几何的方式来展示真实的地图要素,会随着地图缩放而发生视觉大小的变化,但其代表的实际路径或范围不变,如上图中红框内的折线、圆、多边形等。
除了图中的折线、圆、多边形之外,JS API 还提供了矩形、椭圆、贝瑟尔曲线等常用的矢量图形。3D 视图下的 Mesh、Prism 棱柱、MeshLine 也可以看做是一些特殊的矢量图形。
点标记是用来标示某个位置点信息的一种地图要素,覆盖于图层之上。如图中蓝色方框中的两个点状要素。其在屏幕上的位置会随着地图的缩放和中心变化而发生改变,但是会与图层内的要素保持相对静止。
普通的点标记 (即 Marker ) ,支持将自定义图标和DOM元素作为展示内容。除了 Marker 之外为了满足不同的场景,JS API 另外提供了丰富的点标记类型,比如圆点标记 (CircleMarker) 、文本标记 (Text)、灵活点标记 (ElasticMarker) 。同时我们提供了海量点(MassMarks)、点聚合(MarkerCluster)来满足大量点标记的展示需求。
控件浮在所有图层和地图要素之上,用于满足一定的交互或提示功能。一般相对于地图容器静止,不随着地图缩放和中心变化而发生位置的变化。如上图中绿色方框中的比例尺和级别控件。
插件是独立于JS API 地图核心模块之外的一些功能,比如服务类、绘制工具、矢量图形编辑工具、点聚合、热力图等。这些插件不会主动随 JS API的主体资源的加载而下发,使用之前需要提前引入,详见插件的使用
级别与地图的比例尺成正比,每增大一级,地图的比例尺也增大一倍,地图显示的越详细。Web地图的最小级别通常为3级,最大级别各家略有不同,高德地图 JS API 目前最大级别为 20 级。
坐标通常指经纬度坐标,高德地图的坐标范围大致为:东西经180度(-180——180,西半球为负,东半球为正),南北纬85度(-85——85,北半球为正,南半球为负)。
严格意义上,底图指处于所有图层和图形最下方的一个图层,通常不透明。可以是单一图层,比如官方标准图层,也可以是图层组合,比图卫星图层和路网图层组合。
严格意义的地图要素指的是展示在地图上的地理要素,包括道路、区域面、建筑、POI 标注、路名等。开发者自定义的点标记、矢量图形也可以看做是一种地图要素。
我们习惯将底图上自带的标示一定信息的文字或图标称为标注,比如 POI 标注,道路名称标注等。
地图平面像素坐标指投影为平面之后的地图上的平面像素坐标,高德地图使用的Web墨卡托投影,在3级时,平面坐标范围为横纵0-256* 2的3次方 像素,每级别扩大一倍,即第n级的平面坐标范围为 0-256*2 的 n 次方 像素。
地图投影指的是将地球球面的经纬度坐标映射到地图平面坐标的变换和映射关系。高德地图使用 Web 墨卡托投影,即采用 EPSG:3857 坐标系统。
三维空间坐标是在 3D 地图模式下的世界坐标,由 x、y、z 三个纬度组成。三维空间坐标通常用于描述 Object3D 类型的几何形体。
var map = new AMap.Map('container', {
resizeEnable: true, //是否监控地图容器尺寸变化
zoom:11, //初始化地图层级
center: [116.397428, 39.90923] //初始化地图中心点
});
参见代码
实际编写过程中并没有使用这么多控件,鼠标的滚轮功能已经满足大部分需求。
参见代码
//输入提示
var autoOptions = {
input: "tipinput"
};
var auto = new AMap.Autocomplete(autoOptions);
var placeSearch = new AMap.PlaceSearch({
map: map
}); //构造地点查询类
AMap.event.addListener(auto, "select", select);//注册监听,当选中某条记录时会触发
function select(e) {
placeSearch.setCity(e.poi.adcode);
placeSearch.search(e.poi.name); //关键字查询查询
}
参见代码
AMap.service(["AMap.PlaceSearch"], function() {
// 构造地点查询类
var placeSearch = new AMap.PlaceSearch({
type: '餐饮服务', // 兴趣点类别
pageSize: 5, // 单页显示结果条数
pageIndex: 1, // 页码
city: "010", // 兴趣点城市
citylimit: true, //是否强制限制在设置的城市内搜索
map: map, // 展现结果的地图实例
panel: "panel", // 结果列表将在此容器中进行展示。
autoFitView: true // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
});
var cpoint = [116.405467, 39.907761]; //中心点坐标
placeSearch.searchNearBy('', cpoint, 200, function(status, result) {
});
});
参见代码
AMap.service(["AMap.PlaceSearch"], function() {
var placeSearch = new AMap.PlaceSearch({ //构造地点查询类
pageSize: 5, // 单页显示结果条数
pageIndex: 1, // 页码
city: "010", // 兴趣点城市
citylimit: true, //是否强制限制在设置的城市内搜索
map: map, // 展现结果的地图实例
panel: "result", // 结果列表将在此容器中进行展示。
autoFitView: true // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
});
//多边形查
var polygonArr = [//多边形覆盖物节点坐标数组
[116.403322, 39.920255],
[116.410703, 39.897555],
[116.402292, 39.892353],
[116.389846, 39.891365]
];
var polygon = new AMap.Polygon({
path: polygonArr,//设置多边形边界路径
strokeColor: "#FF33FF", //线颜色
strokeOpacity: 0.2, //线透明度
strokeWeight: 3, //线宽
fillColor: "#1791fc", //填充色
fillOpacity: 0.35//填充透明度
});
placeSearch.searchInBounds('酒店', polygon);
});
从这里不难看出来,多边形检索与周边检索非常类似,当开发出来周边搜索,可类似开发多边形搜索功能。
参见代码
了解了上述几个简单功能之后,开始尝试将三个功能整合到一个html页面上。
以输入文本后搜索的html页面作为开发基础
增加周边搜索小窗口按钮
对上述按钮进行事件绑定,实现点击自动缩放到特定周边。详见:周边搜索
编辑周边搜索的默认图形,使得周边搜索更加灵活。 圆的编辑代码或圆的绘制和编辑
在此基础上,也可以增加清除覆盖物的实现。这使得当多次使用周边查询时页面仍能保持较为整洁的良好观感。有关覆盖物的清除方法可以参见:覆盖物
整合后所有的代码如下:
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
<title>输入提示后查询title>
<link rel="stylesheet" href="https://cache.amap.com/lbs/static/main1119.css"/>
<link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" />
<script src="https://webapi.amap.com/maps?v=1.4.15&key=YourKeyValue&plugin=AMap.CircleEditor">script>
<script src="https://a.amap.com/jsapi_demos/static/demo-center/js/demoutils.js">script>
<script src="https://cache.amap.com/lbs/static/es5.min.js">script>
<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=e1e9cc8dd1c2ea38bb2d5c885eccc357&plugin=AMap.Autocomplete,AMap.PlaceSearch">script>
<style>
html,
body,
#container {
width: 100%;
height: 100%;
}
label {
width: 55px;
height: 26px;
line-height: 26px;
margin-bottom: 0;
}
button.btn {
width: 80px;
margin-left: 3px;
margin-right: 3px;
margin-top: 3px;
margin-bottom: 3px;
}
#panel {
position: fixed;
background-color: white;
max-height: 90%;
overflow-y: auto;
top: 10px;
right: 10px;
width: 280px;
border-bottom: solid 1px silver;
}
#myPageTop{
}
style>
head>
<body>
<div id="container" >div>
<div id="panel">div>
<div id="myPageTop" style="width: 24rem; ">
<h4>请输入查找h4>
<div class="input-item">
<input id="tipinput" style="margin-right:1rem;"/>
div>
div>
<div class="input-card" style="width:45rem;">
<h4>POI查询/搜索服务h4>
<div class="input-item">
<label>功能:label>
<button class="btn" id="search-nearby"> 周边查询button>
<button class="btn" id="start-edit"> 开始编辑button>
<button class="btn" onclick="circleEditor.close()">结束编辑button>
<button class="btn" id="removeAllOverlay" >清除所有button>
div>
div>
<script type="text/javascript">
// 定义全局变量
var cpoint = [116.405467, 39.907761];
var lng;
var lat;
var radius = 200;
//地图加载
var map = new AMap.Map("container", {
resizeEnable: true
});
//输入提示
var autoOptions = {
input: "tipinput"
};
var auto = new AMap.Autocomplete(autoOptions);
var placeSearch = new AMap.PlaceSearch({
map: map
}); //构造地点查询类
AMap.event.addListener(auto, "select", select);//注册监听,当选中某条记录时会触发
function select(e) {
placeSearch.setCity(e.poi.adcode);
placeSearch.search(e.poi.name); //关键字查询查询
}
// 事件绑定:周边搜索
document.querySelector("#search-nearby").onclick = function() {
AMap.service(["AMap.PlaceSearch"], function() {
// 构造地点查询类
var placeSearch = new AMap.PlaceSearch({
//type: '餐饮服务', // 兴趣点类别
type: '汽车服务|汽车销售|汽车维修|摩托车服务|餐饮服务|购物服务|生活服务|体育休闲服务|\n' +
'\n' +
'医疗保健服务|住宿服务|风景名胜|商务住宅|政府机构及社会团体|科教文化服务|\n' +
'\n' +
'交通设施服务|金融保险服务|公司企业|道路附属设施|地名地址信息|公共设施',
pageSize: 5, // 单页显示结果条数
pageIndex: 1, // 页码
city: "010", // 兴趣点城市
citylimit: true, //是否强制限制在设置的城市内搜索
map: map, // 展现结果的地图实例
panel: "panel", // 结果列表将在此容器中进行展示。
autoFitView: true // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
});
//cpoint = [lng,lat]; //中心点坐标,要传入参数。
//var cpoint = [116.433320, 39.900255]; //中心点坐标,抱歉,未搜索到有效的结果
placeSearch.searchNearBy('', cpoint, radius, function(status, result) {
});
});
};
document.querySelector("#start-edit").onclick = function () {
var circle = new AMap.Circle({
map: map,
center:new AMap.LngLat("116.40332221984863","39.90025505675715"),// 116.405467, 39.907761
radius:1000,
strokeColor: "#F33",
strokeOpacity: 1,
strokeWeight: 3,
fillColor: "ee2200",
fillOpacity: 0.35
});
map.plugin(["AMap.CircleEditor"],function(){
circleEditor = new AMap.CircleEditor(map,circle);
circleEditor.open();
});
circleEditor.on('move', function(event) {
log.info('触发事件:move')
})
circleEditor.on('adjust', function(event) {
log.info('触发事件:adjust')
})
circleEditor.on('end', function(event) {
log.info('触发事件: end')
lng = circle.getCenter().getLng();
lat = circle.getCenter().getLat();
radius = circle.getRadius();
cpoint = [lng,lat];
// event.target 即为编辑后的圆形对象
})
};
function removeAllOverlay(){
// 清除地图上所有添加的覆盖物
map.clearMap();
}
// 绑定移除事件
document.getElementById("removeAllOverlay").onclick = removeAllOverlay;
script>
body>
html>
使用access创建数据库,并使用IE浏览器预览(因为要用到基于IE内核浏览器支持的ActiveX插件)。其他浏览器暂不支持ActiveX插件。
Name
,poiID
,Lng
,Lat
,数据类型都是短文本filePath
function addPOIData(strName, strId, strLongitude, strLatitude) {
//创建数据库连接对象
var conn = new ActiveXObject("ADODB.Connection");
//创建数据集对象
var rs = new ActiveXObject("ADODB.Recordset");
var connectionString = "DBQ=filePath.mdb;DRIVER={Microsoft Access Driver (*.mdb)};";
console.log(connectionString);
conn.open(connectionString);
var sql = "insert into poi(Name,poiID,Lng,Lat) values('" + strName + "','" + strId + "','" + strLongitude + "','" + strLatitude + "')";
try {
conn.execute(sql);
//关闭记录集
rs.close();
//关闭数据库连接
conn.close();
}
catch (e) {
document.write(e.description);
}
}
以根据搜索结果添加marker为例,把其中的数据写入到数据库:
placeSearch.search('东方明珠', function (status, result) {
// 查询成功时,result即对应匹配的POI信息
console.log(result)
var pois = result.poiList.pois;
for(var i = 0; i < pois.length; i++){
var poi = pois[i];
var marker = [];
marker[i] = new AMap.Marker({
position: poi.location, // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
title: poi.name
});
// 将创建的点标记添加到已有的地图实例:
map.add(marker[i]);
}
map.setFitView();
})
addPOIData
函数:map.add(marker[i]);
addPOIData(poi.name,poi.id,poi.location.lng,poi.location.lat);
ID | Name | poiID | Lng | Lat |
1 | 东方明珠广播电视塔 | B00150F6D6 | 121.499717 | 31.239702 |
2 | 东方明珠广播电视塔(公交站) | BV10385979 | 121.50161 | 31.239862 |
3 | 陆家嘴(地铁站) | BV10029743 | 121.502262 | 31.238195 |
4 | 东方明珠 | B0FFL7YY8J | 121.699108 | 31.187925 |
5 | 东方明珠 | B0FFL7L39N | 121.657356 | 31.584515 |
6 | 东方明珠 | B0FFLDUR2A | 121.412119 | 31.173262 |
7 | 东方明珠公园 | B0FFFS16ZK | 121.500127 | 31.241103 |
8 | 东方明珠广播电视塔(1门) | B00155DLW1 | 121.500617 | 31.23885 |
9 | 东方明珠-城市广场 | B0FFG4JZTG | 121.499649 | 31.239729 |
10 | 东方明珠广播电视塔(8号门) | B00155R4RT | 121.500861 | 31.239404 |
则说明数据添加成功了。
在打开ie的时候如果遇到ADO警告(通常是很多个弹窗警告),可以参见该链接解决。
placeSearch.search(e.poi.name,function (status, result){})
修改函数:
placeSearch.setCity(e.poi.adcode);
//关键字查询
placeSearch.search(e.poi.name,function (status, result) {
console.log(result);
var pois = result.poiList.pois;
for(var i = 0; i < pois.length; i++){
var poi = pois[i];
var marker = [];
marker[i]=new AMap.Marker({
position: poi.location,
title: poi.name
});
map.add(marker[i]);
addPOIData(poi.name,poi.id,poi.location.lng,poi.location.lat);
}
map.setFitView();
});
并在获取到poi对象之后添加addPOIData
函数,测试是否可用:ie打开该html页面,输入搜索:重庆。选择重庆市,等待地图页面加载出来。此时刷新poi表见到如下数据:
ID | Name | poiID | Lng | Lat |
176 | 重庆市 | B00178WI1P | 106.550464 | 29.563761 |
177 | 重庆市中心 | B00178TUGP | 106.551294 | 29.562943 |
178 | 重庆市人民政府 | B001702338 | 106.550483 | 29.563707 |
179 | 重庆市渝中区瑞天路61-8 | B0FFKTRMRS | 106.50242 | 29.553818 |
180 | 重庆市渝中区健康路卤店王烧腊 | B0FFKQZZVC | 106.543084 | 29.552855 |
181 | 重庆市包协 | B001709UXJ | 106.561941 | 29.555964 |
182 | 重庆市妇联 | B001783SH3 | 106.54805 | 29.564651 |
183 | 中国共产党重庆市委员会 | B00170CT3Z | 106.548386 | 29.563538 |
184 | 重庆市科学技术协会 | B00170L88M | 106.565265 | 29.561184 |
185 | 重庆市疾病预防控制中心(上肖家塆) | B0017098ZK | 106.527192 | 29.542505 |
placeSearch.searchNearBy('', cpoint, 200, function(status, result) {
});
为其添加对应函数
placeSearch.searchNearBy('', cpoint, radius, function(status, result) {
// 查询成功时,result即对应匹配的POI信息
console.log(result)
var pois = result.poiList.pois;
for(var i = 0; i < pois.length; i++){
var poi = pois[i];
var marker = [];
marker[i] = new AMap.Marker({
position: poi.location,
// 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
title: poi.name
});
// 将创建的点标记添加到已有的地图实例:
map.add(marker[i]);
addPOIData(poi.name, poi.id, poi.location.lng, poi.location.lat);
}
map.setFitView();
});
同样对其功能进行测试。周边搜索定位到北京。传入的坐标为:[116.405467, 39.907761]
ID | Name | poiID | Lng | Lat |
186 | 菖蒲河沿 | B0FFGZCBUD | 116.404956 | 39.908786 |
187 | 公共厕所 | B000A83BHO | 116.405332 | 39.908872 |
188 | 北库司胡同1号 | B0FFI7883D | 116.404825 | 39.909184 |
189 | 欧美同学会(菖蒲河沿) | B000AA21AN | 116.406377 | 39.9091 |
190 | 南河沿大街与菖蒲河沿交叉口 | B0FFI8LC5Z | 116.406674 | 39.908958 |
同样地,编辑圆形之后也可以进行搜索。
以上html布局中,不同功能之间相互遮挡。给出下面函数使得div可移动。
function dragDiv(id) {
var Drag = document.getElementById(id);
Drag.onmousedown = function (ev) {
var ev = event || window.event;
event.stopPropagation();
var disX = ev.clientX - Drag.offsetLeft;
var disY = ev.clientY - Drag.offsetTop;
document.onmousemove = function (ev2) {
var ev = event || window.event;
Drag.style.left = ev.clientX - disX + "px";
Drag.style.top = ev.clientY - disY + "px";
Drag.style.cursor = "move";
};
};
Drag.onmouseup = function (ev) {
document.onmousemove = null;
this.style.cursor = "default";
};
}
之前的案例中,覆盖物都是给定之后进行修改,不可自定义覆盖物。参考绘制矢量图形,进行圆的绘制。
var mouseTool = new AMap.MouseTool(map);
function drawCircle () {
mouseTool.circle({
strokeColor: "#FF33FF",
strokeOpacity: 1,
strokeWeight: 6,
strokeOpacity: 0.2,
fillColor: '#1791fc',
fillOpacity: 0.4,
strokeStyle: 'solid'
// 线样式还支持 'dashed'
// strokeDasharray: [30,10],
});
// mouseTool.circle();
}
mouseTool.on('draw', function(event) {
// event.obj 为绘制出来的覆盖物对象
log.info('覆盖物对象绘制完成');
})
由于绘制的对象是圆,那么event.obj.CLASS_NAME
就是AMap.Circle
。那么可以获取对应的参数进行相应设置。
cpoint = event.obj.getCenter();
lng = event.obj.getCenter().getLng();
lat = event.obj.getCenter().getLat();
radius = event.obj.getRadius();
按照前面的思路,开发多边形搜索功能。参照多边形搜索
var polygonArr = [//多边形覆盖物节点坐标数组
[116.403322, 39.920255],
[116.410703, 39.897555],
[116.402292, 39.892353],
[116.389846, 39.891365]
];
var polygon = new AMap.Polygon({
path: polygonArr,//设置多边形边界路径
strokeColor: "#FF33FF", //线颜色
strokeOpacity: 0.2, //线透明度
strokeWeight: 3, //线宽
fillColor: "#1791fc", //填充色
fillOpacity: 0.35//填充透明度
});
placeSearch.searchInBounds('酒店', polygon);
参考绘制矢量图形,将默认的多边形修改为绘制多边形,并获取动态坐标。如果不知道polygon有哪些属性,可以查看覆盖物-参考手册找到polygon对应的属性列表。在方法一栏中找到getPath()
,返回Array类型:获取折线路径的节点数组。说明:其中lat和lng是经纬度参数。
function drawPolygon () {
mouseTool.polygon({
strokeColor: "#FF33FF",
strokeOpacity: 1,
strokeWeight: 6,
strokeOpacity: 0.2,
fillColor: '#1791fc',
fillOpacity: 0.4,
// 线样式还支持 'dashed'
strokeStyle: "solid",
// strokeStyle是dashed时有效
// strokeDasharray: [30,10],
})
}
mouseTool.on('draw', function(event) {
// event.obj 为绘制出来的覆盖物对象
log.info('覆盖物对象绘制完成');
polygonArr= event.obj.getPath();
})
将上述polygonArr
替换为动态路径,然后再定义全局变量polygonArr
即可。测试代码搜索成功后,给placeSearch.searchInBounds('酒店', polygon);
增加回调函数。参照周边搜索及其修改后的代码。
function(status, result) {
// 查询成功时,result即对应匹配的POI信息
console.log(result)
var pois = result.poiList.pois;
for(var i = 0; i < pois.length; i++){
var poi = pois[i];
var marker = [];
marker[i] = new AMap.Marker({
position: poi.location, // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
title: poi.name
});
// 将创建的点标记添加到已有的地图实例:
map.add(marker[i]);
addPOIData(poi.name, poi.id, poi.location.lng, poi.location.lat);
}
map.setFitView();
}
测试:用ie浏览器打开,框选广州的一处地方,搜索并刷新数据库。
ID | Name | poiID | Lng | Lat |
191 | 微八连锁酒店(广州西村分店) | B00140WAL7 | 113.239592 | 23.140388 |
192 | 东盈快捷酒店 | B0FFGOFIHG | 113.545177 | 23.110201 |
193 | 原景商务酒店(广州北京路纪念堂地铁站店) | B00141JVYF | 113.262521 | 23.131277 |
194 | 广州斯维登服务公寓(洛溪渔人码头) | B0FFG1AB92 | 113.296751 | 23.048226 |
195 | 盈丰源酒店(会展中心店) | B00140W1Y4 | 113.280034 | 23.102697 |
可见多边形搜索功能也开发完成了。
需求:通过在地图上画Polyline折线覆盖物,对覆盖物区域进行搜索。并将数据存储到数据库。
关于Polyline属性详见
首先,增加绘制折线的函数:参考绘制矢量图形,进行折线绘制测试,并获取到覆盖物对象为:AMap.Polyline
,这与我们的预期一致。
function drawPolyline () {
mouseTool.polyline({
strokeColor: "#3366FF",
strokeOpacity: 1,
strokeWeight: 6,
// 线样式还支持 'dashed'
strokeStyle: "solid",
// strokeStyle是dashed时有效
// strokeDasharray: [10, 5],
})
}
mouseTool.on('draw', function(event) {
// event.obj 为绘制出来的覆盖物对象
log.info('覆盖物对象绘制完成')
polylineArr = event.obj.getPath();
})
高德地图没有对Polyline进行搜索的函数。先查找Polyline属性。通过查看覆盖物-参考手册,发现方法getPath( )
返回Array 获取折线路径的节点数组。其中lat和lng是经纬度参数。以及方法getBounds( )
返回 Bounds 获取当前折线的矩形范围对象。
所谓“沿线搜索”,本质上是把折线转化为具有较小宽度的长方形条带,再对这个带状区域进行多边形搜索。以上两个方法都能获取到折线相关信息,这里只需要“沿线搜索”,所以获取getPath()
即可(见上述代码)。首先把获取到的折线坐标转化为带状区域多边形坐标,然后将带状坐标通过setPath方法设置到Polyline对象即可。剩余步骤类似于多边形搜索。但这种方法,将折线数组转化为带状图形数组的难度比较大。另一种沿线搜索的策略是:先获取折线路径的路线规划,再从路线规划中获取相关poi信息。如此一来,沿线搜索就变成了取折线折点的点搜索。路线规划参考。
首先找到路线规划相关的函数:
var driving = new AMap.Driving(drivingOption)
// 根据起终点经纬度规划驾车导航路线
driving.search(new AMap.LngLat(116.379028, 39.865042), new AMap.LngLat(116.427281, 39.903719), function(status, result) {
// result 即是对应的驾车导航信息,相关数据结构文档请参考
//https://lbs.amap.com/api/javascript-api/reference/route-search#m_DrivingResult
if (status === 'complete') {
log.success('绘制驾车路线完成')
} else {
log.error('获取驾车数据失败:' + result)
}
});
接着查看回传参数result
的相关属性:DrivingResult对象,发现有start(起点),end(终点),waypoints(途经点,最多支持不大于16个途经点)三个属性可供使用,它们都属于poi类型。所以仿照上述的代码,添加marker并保存数据:
function drivingSearch() {
driving.search(path[0],path[path.length-1 ],{waypoints:path},function (status, result) {
if (status === 'complete') {
log.success('绘制驾车路线完成')
} else {
log.error('获取驾车数据失败:' + result)
}
// var pois = result.poiList.pois;
var pois = [];
pois.push(result.start);
for(i=0;i<result.waypoints.length;i++)
pois.push(result.waypoints[i]);
pois.push(result.end);
for(var i = 0; i < pois.length; i++){
var poi = pois[i];
var marker = [];
marker[i] = new AMap.Marker({
position: poi.location,
// 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
title: poi.name
});
// 将创建的点标记添加到已有的地图实例:
map.add(marker[i]);
addPOIData(poi.name, poi.id, poi.location.lng, poi.location.lat);
}
map.setFitView();
});
}
ID | Name | poiID | Lng | Lat |
196 | 起点 | undefined | 87.454022 | 43.870275 |
197 | 途经点 | undefined | 87.454022 | 43.870275 |
198 | 途经点 | undefined | 87.507031 | 43.882154 |
199 | 途经点 | undefined | 87.543286 | 43.864334 |
200 | 途经点 | undefined | 87.530377 | 43.84017 |
201 | 途经点 | undefined | 87.567455 | 43.801329 |
202 | 途经点 | undefined | 87.661663 | 43.837001 |
203 | 终点 | undefined | 87.661663 | 43.837001 |
document.querySelector("#search-nearby").onclick = function() {
AMap.service(["AMap.PlaceSearch"], function() {
// 构造地点查询类
var placeSearch = new AMap.PlaceSearch({
//type: '餐饮服务', // 兴趣点类别
type: '汽车服务|汽车销售|汽车维修|摩托车服务|餐饮服务|购物服务|生活服务|体育休闲服务|\n' +
'\n' +
'医疗保健服务|住宿服务|风景名胜|商务住宅|政府机构及社会团体|科教文化服务|\n' +
'\n' +
'交通设施服务|金融保险服务|公司企业|道路附属设施|地名地址信息|公共设施',
pageSize: 5, // 单页显示结果条数
pageIndex: 1, // 页码
city: "010", // 兴趣点城市
citylimit: true, //是否强制限制在设置的城市内搜索
map: map, // 展现结果的地图实例
panel: "panel", // 结果列表将在此容器中进行展示。
autoFitView: true // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
});
//cpoint = [lng,lat]; //中心点坐标,要传入参数。
//var cpoint = [116.433320, 39.900255]; //中心点坐标,抱歉,未搜索到有效的结果
for(j=0;j<pois.length;j++) {
placeSearch.searchNearBy('', pois[j].location, 200, function (status, result) {
// 查询成功时,result即对应匹配的POI信息
console.log(result)
var pois0 = result.poiList.pois;
for (var i = 0; i < pois0.length; i++) {
var poi = pois0[i];
var marker = [];
marker[i] = new AMap.Marker({
position: poi.location, // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
title: poi.name
});
// 将创建的点标记添加到已有的地图实例:
map.add(marker[i]);
addPOIData(poi.name, poi.id, poi.location.lng, poi.location.lat);
}
map.setFitView();
});
}
});
};
证明沿线搜索也能运行了。
该实验以高德地图JS API开发文档为基础,对基础查询功能进行了开发。
其中沿线搜索的功能开发并不是很理想,因为绘制的折线并没有能很好的转化为包含折线带状区域。如果通过折线的getPath或者getBound方法得到坐标进行多边形查询,本质都是多边形查询,并没有体现“沿线”这一功能。刚开始想到将折线坐标数组转化为多边形坐标数组(从头到尾将折线坐标偏移一遍,再反过来反方向偏移来构成一个大致包裹折线的多边形),如下:
var polygonArr1=[];
var polygonArr2=[];
var polygonB = [];
for(i=0;i<polygonArr.length;i++){
j=polygonArr.length-i-1;
polygonArr1.push([polygonArr[i][0],polygonArr[i][1]+10.000000]);
polygonArr2.push([polygonArr[j][0],polygonArr[j][1]-20.000000]);
}
var polygonB = polygonArr1.concat(polygonArr2);
但是这样的转化效果并不理想,适用性非常差。只能针对角度接近于180度的折线拟合。
后来想到通过规划沿线导航进而获取导航路径的信息poi,经过查询发现也不能如意。driving.search函数只能返回到传入参数的poi信息,而不能获取沿途的poi信息。这样一来,沿线搜索就变成折线折点坐标群体的周边搜索了。关于如何更好实现“沿线搜索”的问题值得深入研究。
其次,代码逻辑性不强,有待完善。例如获取marker(其实是获取poi)并且存储到数据库的代码,每一次不同覆盖物查询都用到一样的语法逻辑。将其封装起来成为一个函数供调用会减少代码重复性。每一次覆盖物查询(或者关键字查询)都是固定不变的:
function(status, result) {
// 查询成功时,result即对应匹配的 POI信息
console.log(result)
var pois = result.poiList.pois;
for(var i = 0; i < pois.length; i++){
var poi = pois[i];
var marker = [];
marker[i] = new AMap.Marker({
position: poi.location, // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
title: poi.name
});
// 将创建的点标记添加到已有的地图实例:
map.add(marker[i]);
addPOIData(poi.name, poi.id, poi.location.lng, poi.location.lat);
}
map.setFitView();
}
将这部分代码抽取得到
// 抽取添加 marker和存储数据的函数
function addMarkerAndPoi(status,result){
console.log(result);
var pois = result.poiList.pois;
for(var i = 0; i < pois.length; i++){
var poi = pois[i];
var marker = [];
marker[i]=new AMap.Marker({
position: poi.location,
title: poi.name
});
map.add(marker[i]);
addPOIData(poi.name,poi.id,poi.location.lng,poi.location.lat);
}
map.setFitView();
}
将减少代码的冗余性,也更方便阅读和更新。
此外,还可以针对覆盖物开发更多的个性化功能。例如开发支持圆形的编辑;多边形的编辑以及折线的编辑;删除单个覆盖物,移动覆盖物等。高德地图JS API示例都给出了编辑覆盖物/矢量图形相关教程。
通过本次开发实验,了解了高德地图JS API有关搜索查询以及覆盖物的简单知识;学会如何读懂html代码并对相应的元素修改;学会了根据报错信息找到代码疏忽错漏的地方。