近期在做可视化大屏相关业务,把涉及到的高德API部分做一个分享,一下是开发流程和场景实例
一、注册账号并申请Key
1.首先,注册开发者账号,成为高德开放平台开发者
不同开发者权限,针对某项服务在日配额和每秒响应请求次数上存在差别
2.登陆之后,在进入「应用管理」 页面「创建新应用」
3.选择服务平台添加Key
二、引入
<script type="text/javascript" id="AMapJS_id" src="https://webapi.amap.com/maps? v=1.4.15&key=xxx&plugin=AMap.Geocoder,AMap.Autocomplete,AMap.PlaceSearch,AMap.Heatmap" async ></script>
// AMapLoader.js
let waitAMapExpList = []; // 解决同一页面 不同组件各自引入MapLoader,callback只执行一次引起的bug
export default function MapLoader() {
let AMapJS_id = document.getElementById('AMapJS_id');
return new Promise((resolve, reject) => {
if (window.AMap) {
resolve(window.AMap);
} else if (!window.AMap && AMapJS_id) {
waitAMapExpList.push({
resolve,
reject
});
} else {
let script = document.createElement('script');
script.type = 'text/javascript';
script.id = 'AMapJS_id';
script.async = true;
script.src =
'https://webapi.amap.com/maps?v=1.4.15&callback=initAMap&key=xxx&plugin=AMap.Geocoder,AMap.Autocomplete,AMap.PlaceSearch,AMap.Heatmap';
script.onerror = reject;
document.head.appendChild(script);
window.initAMap = () => {
resolve(window.AMap);
if (waitAMapExpList.length !== 0) {
waitAMapExpList.forEach(item => {
item.resolve(window.AMap);
});
}
};
}
});
}
三、自定义地图主题
从高德开放平台,自定义地图模板,获取样式ID
this.mapInstance.setMapStyle('amap://styles/c1c78364476283c25201f6c342b4d636');
四、目前使用插件和API介绍
1. 搜索选点和地图选点
const AMap = await MapLoader(); // 加载地图
// 搜索选点
AMap.plugin(['AMap.Autocomplete', 'AMap.PlaceSearch'], () => {
const autocomplete = new AMap.Autocomplete({
input: 'address-input'
});
this.placeSearch = new AMap.PlaceSearch({
pageSize: 1
});
AMap.event.addListener(autocomplete, 'select', e => {
console.log(e, 'autocomplete');
this.curSelectPoi.address = e.poi.name;
let poi_selected = e.poi,
lng,
lat;
lat = poi_selected.location.lat;
lng = poi_selected.location.lng;
this.curSelectPoi.lat = lat;
this.curSelectPoi.lng = lng;
this.curSelectPoi.cityCode = e.poi.adcode;
// 移动地图中心并标记位置
if (lng && lat) {
let lnglat = new AMap.LngLat(lng, lat);
this.curSelectPoi.address &&
this.$refs.amapCom.setMarker({ lnglat });
}
});
});
// 地图选点
if (!this.mapInstance) {
this.mapInstance = new AMap.Map(this.$refs.mapid, {
resizeEnable: true,
doubleClickZoom: false,
center: this.center,
zoom: this.zoom
});
}
// 点击地图,获取经纬度
this.mapInstance.on('click', e => {
console.log(e.lnglat);
this.geocoderInfo.lng = e.lnglat.lng;
this.geocoderInfo.lat = e.lnglat.lat;
let lnglat = [e.lnglat.lng, e.lnglat.lat];
this.setMarker({ lnglat });
this.getGeocoderInfo(lnglat);
});
// 创建地理编码对象
AMap.plugin(['AMap.Geocoder'], () => {
this.geocoder = new AMap.Geocoder({});
});
// 逆解析,根据经纬度获取地址信息,
// 或者使用 web服务api https://restapi.amap.com/v3/geocode/regeo?location=${lnglat}&key=xxx`);
getGeocoderInfo(lnglat) {
this.geocoder.getAddress(lnglat, (status, result) => {
if (status === 'complete' && result.regeocode) {
this.geocoderInfo.address = result.regeocode.formattedAddress;
this.$emit('getGeocoderInfo', this.geocoderInfo);
} else {
console.error('根据经纬度查询地址失败');
this.geocoderInfo.address = '';
this.$emit('getGeocoderInfo', this.geocoderInfo);
}
});
},
setMarker(e) {
console.log('marker info', e);
// 创建marker
if (!this.locationMarker) {
this.locationMarker = new AMap.Marker({
icon: new AMap.Icon({
size: new AMap.Size(29, 37),
image:
'locationIcon.png',
imageSize: new AMap.Size(29, 37)
})
});
this.mapInstance.add([this.locationMarker]);
}
this.locationMarker.setPosition(e.lnglat);// 设置marker位置
this.center = [e.lnglat.lng, e.lnglat.lat];
this.mapInstance.setZoomAndCenter(e.zoom || this.zoom, e.lnglat);// 移动地图中心点
this.mapInstance.setFitView(this.locationMarker); // 自动缩放地图到合适的视野级别
},
2. 搜索+半径圈选
const AMap = await MapLoader(); // 加载地图
let circleInstance = new AMap.Circle({
center: this.center, // 圆心位置
radius: this.scope * 1000, // 半径
strokeColor: '#ee5d40', // 线颜色
strokeWeight: 2, // 线宽
fillColor: '#ef4d2d', // 填充色
fillOpacity: 0.2 // 填充透明度
})
circleInstance.setMap(map) // 显示圆圈
this.mapInstance.setFitView() // 根据地图上添加的覆盖物分布情况,自动缩放地图到合适的视野级别
// 修改 scope 大小
circleInstance.setOptions({
radius: this.scope * 1000, // 半径
center: this.center, // 圆心位置
strokeColor: '#ee5d40', // 线颜色
strokeWeight: 2, // 线宽
fillColor: '#ef4d2d', // 填充色
fillOpacity: 0.2 // 填充透明度
})
3. 多边形圈选区域
<amap-draw ref="amapDraw" width="100%" height="500px" :showDrawTool="true" :mapCenter="center" :cityCode="cityCode" @getPathData="getPathData" />
const AMap = await MapLoader(); // 加载地图
this.mapInstance = new AMap.Map(this.$refs.mapid, {
resizeEnable: true,
doubleClickZoom: false,
center: this.center,
zoom: this.zoom
});
initPath() {
// 查看进入,复现路径
if (this.pathData.type) {
if (this.pathData.type == 'Circle') {
this.circle_radius = this.pathData.circle_radius;
this.center = this.pathData.location_center;
} else {
this.PolygonPath = this.pathData.location_circle;
}
} else {
// 编辑进入,基础路径设置
this.PolygonPath = [
[this.center[0], this.center[1] + 0.005],
[this.center[0] - 0.005, this.center[1] - 0.005],
[this.center[0] + 0.005, this.center[1] - 0.005]
];
let southWest = new AMap.LngLat(
this.center[0] - 0.01,
this.center[1] - 0.005
);
let northEast = new AMap.LngLat(
this.center[0] + 0.01,
this.center[1] + 0.005
);
this.rectangleBounds = new AMap.Bounds(southWest, northEast);
}
},
// 绘制路径
drawPath(pathType) {
this.pathType = pathType;
// 通过搜索获取圈选中心点
if (this.cityCode == '' && this.showDrawTool) {
this.$message.closeAll();
this.$message({
showClose: true,
duration: 2000,
type: 'error',
message: '请您先通过搜索选择圈选位置'
});
return;
}
this.initPath(); // 加载以搜索位置为中心点创建的默认圈选路径
!this.pathData.type && this.mapInstance.clearMap(); // type默认值为“”,避免重复绘制初始路径
switch (pathType) {
case 'Circle':
this.linePath = new AMap.Circle({
center: this.center,
radius: this.circle_radius, //半径
borderWeight: 3,
strokeColor: '#FF33FF',
strokeOpacity: 1,
strokeWeight: 6,
strokeOpacity: 0.6,
fillOpacity: 0.4,
strokeStyle: 'dashed',
strokeDasharray: [10, 10],
fillColor: '#1791fc',
zIndex: 50
});
this.linePath.setMap(this.mapInstance);
this.pathEditor = new AMap.CircleEditor(
this.mapInstance,
this.linePath
);
break;
case 'Polygon':
this.linePath = new AMap.Polygon({
path: this.PolygonPath,
strokeColor: '#FF33FF',
strokeWeight: 6,
strokeStyle: 'dashed',
strokeOpacity: 0.6,
fillOpacity: 0.4,
fillColor: '#1791fc',
zIndex: 50
});
this.mapInstance.add(this.linePath);
this.pathEditor = new AMap.PolyEditor(
this.mapInstance,
this.linePath
);
break;
case 'Rectangle':
this.linePath = new AMap.Rectangle({
bounds: this.rectangleBounds,
strokeColor: '#FF33FF',
strokeWeight: 6,
strokeOpacity: 0.6,
strokeDasharray: [30, 10],
strokeStyle: 'dashed',
fillColor: '#1791fc',
fillOpacity: 0.4,
cursor: 'pointer',
zIndex: 50
});
this.linePath.setMap(this.mapInstance);
this.pathEditor = new AMap.RectangleEditor(
this.mapInstance,
this.linePath
);
break;
}
// 绘制并缩放地图到合适的视野级别
this.mapInstance.setFitView([this.linePath]);
// 打开区域编辑
!this.pathData.type && this.pathEditor.open();
// 区域调整时触发
this.pathEditor.on('adjust', event => {
console.log('adjust', '限制区域code', this.cityCode, event);
});
// 编辑结束时触发,获取路径
this.pathEditor.on('end', async event => {
console.log('end', event.target);
});
},
// 确认圈选区域,获取路径
closePathEditor() {
this.pathEditor.close(); // 触发关闭区域编辑,获取编辑路径
let path = this.linePath.getPath();
let pathData = {
type: this.pathType,
location_circle = path.map(ele => [ele.lng, ele.lat]); // 联通所需路径格式
};
this.$emit('getPathData', pathData);
},
// 清除圈选,重置数据
clearPath() {
this.mapInstance.clearMap();
this.$emit('getPathData', {
type: '',
location_circle: []
});
this.pathEditor = null;
}
4.按行政区展示数据
const AMap = await MapLoader(); // 加载地图
// 初始化地图实例
this.mapInstance = new AMap.Map('geo-map', {
viewMode: '3D',
resizeEnable: false,
center: this.center,
mapStyle: 'amap://styles/c1c78364476283c25201f6c342b4d636',
zoom: this.zoom
});
AMapUI.load([], (DistrictExplorer, $) => {
//创建一个实例
this.districtExplorer = new DistrictExplorer({
map: this.mapInstance,
eventSupport: true // 打开事件支持
});
//鼠标hover提示内容
let $tipMarkerContent = $('<div class="tipMarker"></div>');
let tipMarker = new AMap.Marker({
content: $tipMarkerContent.get(0),
offset: new AMap.Pixel(0, 0),
bubble: true
});
this.switch2AreaNode(this.adcode);
//feature被点击
this.districtExplorer.on('featureClick', async (e, feature) => {
console.log(feature.properties);
let props = feature.properties;
let { level, name } = feature.properties;
//如果存在子节点
if (props.childrenNum > 0) {
// 获取数据
this.curRenderData = await this.getInsideArea({
label: name,
level:
level == 'province' && name.indexOf('市') > -1
? 'district'
: level == 'city'
? 'district'
: 'city'
});
//切换聚焦区域
this.switch2AreaNode(props.adcode);
}
});
//外部区域被点击
this.districtExplorer.on('outsideClick', e => {
this.districtExplorer.locatePosition(
e.originalEvent.lnglat,
async (error, routeFeatures) => {
console.log(routeFeatures);
if (routeFeatures && routeFeatures.length > 1) {
//切换到省级区域
let { level, name } = routeFeatures[1].properties;
this.curRenderData = await this.getInsideArea({
label: routeFeatures[1].properties.name,
level:
level == 'province' && name.indexOf('市') > -1
? 'district'
: level == 'city'
? 'district'
: 'city'
});
this.switch2AreaNode(routeFeatures[1].properties.adcode);
} else {
//切换到全国
this.curRenderData = this.provinceData;
this.switch2AreaNode(100000);
}
},
{
levelLimit: 2
}
);
});
});
switch2AreaNode(adcode){
this.districtExplorer.loadAreaNode(adcode, (error, areaNode) => {
this.currentAreaNode = areaNode;
//设置当前使用的定位用节点
this.districtExplorer.setAreaNodesForLocating([this.currentAreaNode]);
this.renderAreaPolygons(areaNode);
});
};
renderAreaPolygons(areaNode) {
//更新地图视野
this.mapInstance.setBounds(areaNode.getBounds(), null, null, true);
//清除已有的绘制内容
this.districtExplorer.clearFeaturePolygons();
//绘制子区域
this.districtExplorer.renderSubFeatures(areaNode, (feature, i) => {
let fillColor = this.getFillColor(
this.curRenderData,
feature.properties.name
);
const strokeColor = '#fff';
return {
cursor: 'default',
bubble: true,
strokeColor: strokeColor, //线颜色
strokeOpacity: 1, //线透明度
strokeWeight: 1, //线宽
fillColor: fillColor, //填充色
fillOpacity: 0.35 //填充透明度
};
});
//绘制父区域
this.districtExplorer.renderParentFeature(areaNode, {
cursor: 'default',
bubble: true,
strokeColor: '#fff', //线颜色
strokeOpacity: 1, //线透明度
strokeWeight: 1, //线宽
fillColor: null, //填充色
fillOpacity: 0.35 //填充透明度
});
}
5.历史热力分时刻轮播
const AMap = await MapLoader(); // 加载地图
this.mapInstance = new AMap.Map('loca-map', {
mapStyle: 'amap://styles/c1c78364476283c25201f6c342b4d636',
pitch: 60,
center: this.center,
zoom: this.zoom
});
// Loca是一个基于高德 JS API 地图、纯 JavaScript 实现的地理空间数据可视化渲染引擎
this.heatMapLayer = new Loca.HeatmapLayer({
map: this.mapInstance,
eventSupport: true
});
this.heatMapLayer.setOptions({
style: {
radius: 30,
color: {
0.5: 'blue',
0.65: 'rgb(117,211,248)',
0.7: 'rgb(0, 255, 0)',
0.9: '#ffea00',
1.0: 'red'
}
}
});
// 渲染热力
renderHeatData() {
this.heatMapLayer.setData(this.heatmapData, {
lnglat: function(obj) {
let val = obj.value;
return [val['lng'], val['lat']];
},
value: 'count',
type: 'json'
});
this.heatMapLayer.render();
},
6.坐标系转化
/*
地球上同一个地理位置的经纬度,在不同的坐标系中,会有少于偏移,国内目前常见的坐标系主要分为三种:
地球坐标系——WGS84:常见于 GPS 设备,Google 地图等国际标准的坐标体系。
火星坐标系——GCJ-02:中国国内使用的被强制加密后的坐标体系,高德坐标就属于该种坐标体系。
百度坐标系——BD-09:百度地图所使用的坐标体系,是在火星坐标系的基础上又进行了一次加密处理。
因此在使用不同坐标系前,我们需要使用 AMap.convertFrom() 方法将这些非高德坐标系进行转换。
*/
let ltapi_geo_json = [[116.3, 39.9], [116.3, 39.9]];
AMap.convertFrom(ltapi_geo_json, 'gps', (status, result) => {
if (result.info === 'ok') {
console.log(result);
ltapi_geo_json = result.locations.map(ele => [ele.lng, ele.lat]);
console.log(ltapi_geo_json);
}
});
五、echarts 配置高德地图
import MapLoader from '@/utils/AMapUtil'; // AMap 加载
// 按需引入所需echarts模块
const echarts = require('echarts/lib/echarts'); // 引入 ECharts 主模块
require('echarts/lib/chart/effectScatter'); // 引入散点
require('echarts/lib/chart/lines'); // 引入航线
require('zrender/lib/svg/svg'); // svg支持
let AMapOption = {
maxPitch: 60,
pitch: 30, //45 俯仰角
resizeEnable: true,
center: [103.788625, 36.136601],
viewMode: '3D', // 电视端浏览器渲染不出来,会启用2D
mapStyle: 'amap://styles/c1c78364476283c25201f6c342b4d636',
zoom: 8, // 地图缩放等级
zooms: [5, 18] // 默认缩放范围值3-18
};
const AMapChart = null; // echarts实例
const mapInstance = null; // 地图实例
const heatmapInstance = null; // 热力图实例
// 获取地图实例,渲染高德热力图
MapLoader().then(AMap => {
// 初始化echarts
AMapChart = echarts.init(
document.getElementById('heat-map'),
null,
{ renderer: 'canvas' }
); // lines渲染,需要用canvas
AMapChart.setOption({amap: AMapOption});
// 获取地图实例
mapInstance = AMapChart
.getModel()
.getComponent('amap')
.getAMap();
// 设置主题样式
mapInstance.setMapStyle(
'amap://styles/c1c78364476283c25201f6c342b4d636'
);
// 使用高德热力图插件,减少数据处理
mapInstance.plugin(['AMap.Heatmap'], () => {
//创建heatmap实例
heatmapInstance = new AMap.Heatmap(mapInstance, {
radius: 30, //给定半径
opacity: [0, 0.8],
gradient: {
'0.2': '#571545',
'0.4': '#91083c',
'0.6': '#ca0436',
'0.8': '#e16118',
'1.0': '#ee903e'
}
});
});
}).catch(err => console.log(err));
// 渲染数据
let linesConfig = [
{
offset: 0,
color: '#6b46f9' // 0% 处的颜色
},
{
offset: 1,
color: '#00d7e6' // 100% 处的颜色
}
];
// 渲染热力图
let heatData = [{"count":"1","lat":"39.86183166503906","lng":"116.40495300292969"}]
heatmapInstance.setDataSet({data: heatData});
// 渲染散点和航线
let topPoiList = [{"index":1,"label":"中国地质大学学生宿舍19 号","value":"8.81","lng":116.348902,"lat":39.992882,"count":17,"symbolSize":55}]
AMapChart.setOption({
amap: AMapOption,
series: [{
type: 'lines', // 航线
zlevel: 2, // 控制lines和effectScatter层级
animation: false,
coordinateSystem: 'amap',// 使用高德坐标系
effect: {
show: self.level == 1, // 电视端卡顿严重,基础版关闭特效动画
period: 4,
trailLength: 0.1,
color: '#fff',
symbolSize: 8
},
lineStyle: {
normal: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: linesConfig // 线颜色
},
width: 2,
curveness: 0.2
}
},
data: self.formtLinesData(topPoiList, self.screenCenter, false)
},
{
type: 'effectScatter', // 散点
coordinateSystem: 'amap',
zlevel: 3,
rippleEffect: {
period: 6,
scale: 2.5,
brushType: 'stroke'
},
label: {
normal: {
color: '#fff',
show: true,
position: 'inside',
formatter: '{b}',
textBorderColor: '#000'
}
},
itemStyle: {
normal: {
color: linesConfig[0].color // 点颜色
}
},
data: self.formtVData(topPoiList, self.screenCenter)
}]
});
如果觉得对你有帮助,可以给我点赞哦。随着使用场景的增加,我会持续更新的,欢迎mark