- 准备工作如下:
- 安装TS插件依赖 以及 地图基础类所需TS类型 tips:高德官方提供的地图类型与api2.0版本 存在问题,需要自行调整 github.com/Ludidi/amap...
- 自定义类型声明文件 amap.api.d.ts 内容如下
TS
// 声明命名空间
type options = {
key: string; // 高德地图的API Key
version?: string; // API版本,默认为最新版本
plugins?: string[]; // 需要加载的插件列表
AMapUI?: any;
Loca?: any;
};
declare namespace AMapLoader {
export function load<T>(settings: options): Promise<T>;
}
- 申请好的Web端开发者Key,在项目入口文件引入 我使用的是Vue3的框架 如图:

tips:如果担心自己申请的秘钥被用户F12打开控制台查看后使用,可以让后端代理服务器转发
js
<script type="text/javascript">
window._AMapSecurityConfig = {
serviceHost: '你的代理服务器域名或地址/_AMapService',
}
</script>
其中_AMapService为代理请求固定前缀,不可省略或修改
//例如 :serviceHost:'http://1.1.1.1:80/_AMapService',
一 地图初始化
新建utils文件夹 /index.ts文件 封装工具,此工具内包含了 对高德地图api2,0的一些封装方法 内容如下: 1.1 初始化方法:
js
export function initMap(): Promise<typeof AMap> {
return new Promise((resolve, reject) => {
//如果全局已经存在AMap对象 则直接返回
if (window.AMap) {
resolve(window.AMap);
return;
}
AMapLoader.load<typeof AMap>({
key: "XXXXXXXXXXXXXX", // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JS API 的版本,缺省时默认为 1.4.15
plugins: [
"AMap.MoveAnimation,AMap.MouseTool,AMap.PlaceSearch,AMap.DistrictSearch,AMap.Geocoder",
], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
// "AMapUI": { // 是否加载 AMapUI,缺省不加载
// "version": '1.1', // AMapUI 版本
// "plugins": [], // 需要加载的 AMapUI ui插件
// },
// "Loca": { // 是否加载 Loca, 缺省不加载
// "version": '2.0' // Loca 版本
// },
})
.then((AMap) => {
window.AMap = AMap;
resolve(AMap); //防止上方全局添加amap失败手动返回Amap
})
.catch((e) => {
console.error(e); //加载错误提示
reject(e);
});
});
}
1.2 新建myMap 类
导入类型 import "@amap/amap-jsapi-types";
ts
/**
* 高德地图使用的是 GCJ-02 坐标系,若采用的其他坐标系请初始化配置此处转换
*/
type CoordinateType = "gcj02" | "wgs84" | "bd09";
type MyMapOptions = {
_AmapCoordinate: CoordinateType;
} & AMap.MapOptions;
class myMap {
private _AmapCoordinate: CoordinateType = "gcj02"; //地图坐标系 默认自动转换(后续加上)
public mapConfig: AMap.MapOptions = {
zoom: 11,
center: [121.732487, 31.086897],
viewMode: "3D",
mapStyle: "amap://styles/2a268264f80b6efc60d848838404e726",
rotateEnable: false,
pitchEnable: false,
skyColor: "#002d56", //天空颜色 倾斜后才会产生 仅限于3D 模式下
};
public aMap!: AMap.Map; //地图对象
/**
* 地图初始化
* @param {dom元素} el 传入地图容器 DIV 的 ID 值或者 DIV 对象
* @param {配置参数} config 对传入的配置合并
* @return {Promise<void>} 返回一个 Promise 对象,表示地图初始化完成
*/
public init(
el: string | HTMLDivElement,
config: MyMapOptions
): Promise<typeof AMap> {
Object.assign(this.mapConfig, config);
if (config._AmapCoordinate) {
this._AmapCoordinate = config._AmapCoordinate;
}
return new Promise((resolve, reject) => {
initMap().then((AMap) => {
this.aMap = new AMap.Map(el, {
...this.mapConfig,
});
this.aMap.on("complete", () => {
resolve(AMap);
});
});
});
}
}
掉用如下:
js
<template>
<div class="home" id="mapId"></div>
</template>
<script lang="ts" setup>
import { onMounted, ref, nextTick } from "vue";
import myMap from "@/utils/amap-utils";
let currentMap: myMap;
onMounted(() => {
currentMap = new myMap();
currentMap
.init("mapId", { _AmapCoordinate: "gcj02" })
.then((res) => {
console.log("地图初始化成功", res);
// currentMap.setMapAreaOutline();
})
.catch((err) => {
console.error("地图初始化失败", err);
});
});
</script>
.home{
width:100vw;height:100vh
}
二 设置地图区域轮廓 (用于突出显示某块区域)
在原有类中添加方法 setMapAreaOutline
添加属性: private _areaOutlineFeatures!: AMap.Polygon; //地图区域轮覆盖物
js
/**
* 设置地图区域轮廓
* 通过行政区查询获取地图区域轮廓,最后绘制轮廓
* @param lineConfig 轮廓线条配置
* @param districtOptions 区域查询配置
*/
public setMapAreaOutline(
lineConfig?: AMap.PolygonOptions,
districtOptions?: { keyword: string } & AMap.DistrictSearchOptions
): void {
const config: AMap.PolygonOptions = {
strokeWeight: 4,
strokeColor: "#004eff",
fillColor: "",
fillOpacity: 0.3,
zIndex: 10,
bubble: true,
};
Object.assign(config, lineConfig);
let disOptipns: { keyword: string } & AMap.DistrictSearchOptions = {
extensions: "all",
level: "district",
subdistrict: 1,
showbiz: false, //最后一级返回街道信息
keyword: "310115",
};
Object.assign(disOptipns, districtOptions);
new AMap.DistrictSearch({
extensions: "all",
level: "district",
subdistrict: 1,
showbiz: false, //最后一级返回街道信息
}).search(disOptipns.keyword, (status, result) => {
if (status === "complete" && result.districtList.length > 0) {
const holes = result.districtList[0].boundaries;
this._areaOutlineFeatures = new AMap.Polygon();
this._areaOutlineFeatures.setOptions({ ...config, path: holes });
this.aMap.add(this._areaOutlineFeatures);
}
});
}
实际调用如下:
currentMap.setMapAreaOutline();

三 添加点位以及信息窗体
原有类中添加属性:
js
private _overlaysMapObject = new Map<
string,
| AMap.Marker
| AMap.Polyline
| AMap.Polygon
| AMap.Circle
| AMap.Rectangle
| AMap.MassMarks
>(); //覆盖物对象集合
新增方法 addMarker
js
/**
* 添加一个点位
* @param markConfig mark配置
*/
public addMarker(markConfig: MarkerOptions): void {
const fconfig: MarkerOptions = {
clickable: true,
position: undefined,
anchor: "bottom-center",
icon: "https://a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
extData: {},
key: "", //key 点位唯一标识 后期用于控制某个点
};
Object.assign(fconfig, markConfig);
if (!this._overlaysMapObject.has(fconfig.key)) { //地图已有点位则不再添加 而是直接显示,具体看实际业务需求
const mark = new AMap.Marker({
...fconfig,
});
if (fconfig.markClickFn) {
mark.on("click", (e) => {
fconfig.markClickFn && fconfig.markClickFn(e);
});
}
this._overlaysMapObject.set(fconfig.key, mark);
this.aMap.add(mark);
} else {
this._overlaysMapObject.get(fconfig.key)?.show();
}
}
//实际调用如下:仅仅添加点位
currentMap.addMarker({
icon: "https://a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
position: [121.698747, 31.12806],
key: "mark1",
title: "鼠标显示的内容",
extData: {
otherData: 111,
},
markClickFn: (e) => {
console.log(e);
},
});
新增信息窗体方法: 原有类中添加属性
js
private _InfoWindow: AMap.InfoWindow | null = null; //信息窗体
方法如下:
/**
*
* @param opt 信息窗体配置
* @description 打开一个信息窗体
* 关键参数 InfoOptions : {position:[123.22,31.22] , content:(String | HTMLElement)}
*/
public openInfoWindow(opt: InfoOptions): void {
const infoWindow = new AMap.InfoWindow({
isCustom: true,
// offset: new AMap.Pixel(0, -50), //信息窗体偏移量
autoMove: true,
...opt,
});
this._InfoWindow = infoWindow;
infoWindow.open(this.aMap, opt.position);
}
/**
* 关闭信息窗体
*/
public closeInfoWindow(): void {
if (this._InfoWindow) {
this._InfoWindow.close();
this._InfoWindow = null;
}
}
使用:
js
currentMap.addMarker({
icon: "https://a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
position: [121.698652, 31.12706],
key: "mark2",
extData: {
otherData: 111,
},
markClickFn: (e) => {
showInfoWindow.value = true;
nextTick(() => {
currentMap.openInfoWindow({
position: e.target.getPosition(),
content: elemntRef.value,
offset: new AMap.Pixel(0, -80), //信息窗体偏移量
});
});
},
});
templete
// dom元素如下:
<div ref="elemntRef" class="InfoWindowClass" v-if="showInfoWindow">
<div class="InfoWindowClass-header">
<span>信息窗口标题{{ otherData.name }}</span>
<span class="close-btn" @click="currentMap.closeInfoWindow()"></span>
</div>
<div class="InfoWindowClass-content">这里是信息窗口的内容区域...</div>
<div class="InfoWindowClass-arrow"></div>
</div>
//js
const elemntRef = ref();
const showInfoWindow = ref(false);
css 样式
// 基础信息窗样式
.InfoWindowClass {
background-color: #fff;
border-radius: 6px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
overflow: hidden;
z-index: 1000;
width: 300px;
// 头部区域样式
&-header {
padding: 12px 16px;
border-bottom: 1px solid #e8e8e8;
position: relative;
// 关闭按钮样式
.close-btn {
position: absolute;
top: 12px;
right: 12px;
width: 16px;
height: 16px;
cursor: pointer;
color: #999;
font-size: 14px;
line-height: 14px;
&:hover {
color: #333;
}
&:before,
&:after {
content: "";
position: absolute;
width: 16px;
height: 2px;
background-color: currentColor;
top: 50%;
left: 0;
transform: translateY(-50%);
}
&:before {
transform: translateY(-50%) rotate(45deg);
}
&:after {
transform: translateY(-50%) rotate(-45deg);
}
}
}
// 内容区域样式
&-content {
padding: 16px;
font-size: 14px;
line-height: 1.5;
}
// 底部箭头样式
&-arrow {
position: absolute;
bottom: -7px;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 12px solid transparent;
border-right: 12px solid transparent;
border-top: 12px solid #fff;
border-bottom: 0;
z-index: 1;
// // 阴影增强立体感
// &:after {
// content: "";
// position: absolute;
// top: 1px;
// left: -12px;
// width: 0;
// height: 0;
// border-left: 12px solid transparent;
// border-right: 12px solid transparent;
// border-top: 12px solid rgba(0, 0, 0, 0.2);
// border-bottom: 0;
// z-index: -1;
// }
}
}
效果如下:

四 添加海量点
js
/**
* @param config 海量点配置
* @param data.style 样式索引值 对应的是config.style的自定义点的样式下标索引(与z-index无关)
* @description 在地图上显示大量的点位数据
* click事件回调通过InfoWindow 将页面的dom 和 InfoWindow相关联亦可实现海量点信息窗展示
*/
public addMassMarks<T>(
data: { lnglat: AMap.Vector2; otherData: T; style: number }[],
config: AMap.MassMarkersOptions & MarkerOptions
): void {
if (!this._overlaysMapObject.has(config.key)) {
const mass = new AMap.MassMarks(data, {
...config,
});
if (config.markClickFn) {
mass.on("click", (e) => {
config.markClickFn && config.markClickFn(e);
});
}
mass.setMap(this.aMap);
this._overlaysMapObject.set(config.key, mass);
}
}
//实际调用
interface MassDataType { //用于点击海量点后的自定义的数据,可用于信息窗体展示,如无则无需添加
name: string;
age: number;
}
currentMap.addMassMarks<MassDataType>(
[
{
lnglat: [121.698652, 31.12706],
otherData: {
name: "景县1111",
age: 17,
},
style: 0,
},
{
lnglat: [121.698421, 31.1212],
otherData: {
name: "景县2222",
age: 17,
},
style: 1,
},
{
lnglat: [121.694153, 31.12412],
otherData: {
name: "景县3333",
age: 17,
},
style: 1,
},
{
lnglat: [121.698121, 31.12711],
otherData: {
name: "景县4444",
age: 17,
},
style: 0,
},
{
lnglat: [121.698147, 31.124516],
otherData: {
name: "景县5555",
age: 17,
},
style: 1,
},
],
{
key: "mass1",
style: [
{
url: "https://a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
size: new AMap.Size(30, 30),
rotation: 0,
},
{
url: "https://webapi.amap.com/images/mass/mass1.png",
size: new AMap.Size(30, 30),
rotation: 0,
},
],
zIndex: 130,
markClickFn: (e) => {
console.log("海量点点击事件", e);
otherData.value = e.data.otherData;
showInfoWindow.value = true;
nextTick(() => {
currentMap.openInfoWindow({
position: e.data.lnglat,
content: elemntRef.value,
offset: [15, 0],
});
});
},
}
);
效果如图:(此处只举例了几条数据测试使用 实际可承载上千条数据并不会卡顿)

五 使用mouseTool 插件 绘制电子围栏
原有类中添加属性
js
private _MouseTool: AMap.MouseTool | null = null; //鼠标工具
private _polygonList: AMap.Polygon[] = []; //多边形列表
/**
* 使用mouseTool 插件 绘制电子围栏
* 鼠标单击地图选点/线,右键结束
* @param drawConfig: {nobatch : 是否批量绘制 电子围栏(多边形)} nobatch ? '每次只能绘制一个' : '不限制'
* @param drawCompletedfn 每次绘制完毕的回调
*/
public drawpolygon(
polygonConfig: AMap.PolygonOptions,
drawConfig: DrawConfigType
): void {
if (!this._MouseTool) {
this._MouseTool = new AMap.MouseTool(this.aMap);
}
const initPolyConfig: AMap.PolygonOptions = {
fillColor: "#00b0ff",
strokeColor: "#80d8ff",
strokeWeight: 2,
bubble: true,
zIndex: 130,
};
Object.assign(initPolyConfig, polygonConfig);
this._MouseTool.polygon(initPolyConfig);
this._MouseTool.on("draw", (e: any) => {
//每次绘制完图形的回调
if (drawConfig.nobatch) {
if (this._polygonList.length) {
this.aMap.remove(this._polygonList);
this._polygonList = [];
}
}
this._polygonList.push(e.obj);
drawConfig.drawCompletedfn(e);
});
}
/**
* 关闭鼠标工具
*/
public closeDrawpolygon(): void {
if (this._MouseTool) {
this._MouseTool.close();
this._MouseTool = null;
}
}
//开始绘制围栏方法
currentMap.drawpolygon(
{
strokeColor: "#FF33FF", //线颜色
fillColor: "#1791fc", //填充颜色
strokeWeight: 3, //线宽
fillOpacity: 0.2, //填充透明度
zIndex: 100,
},
{
nobatch: false,
drawCompletedfn: (e: any) => {
console.log("绘制完成回调", e);
console.log(currentMap.getDrawedpolygon());
},
}
);
//结束绘制围栏方法
currentMap.closeDrawpolygon();

最后补充一个填充多边形的方法
js
/**
* 填充电子围栏(多边形)
*/
public setPolygonList(polygonList: AMap.PolygonOptions[]): void {
const config: AMap.PolygonOptions = {
strokeWeight: 4,
strokeColor: "#004eff",
fillColor: "#80d8ff",
fillOpacity: 0.3,
zIndex: 10,
bubble: true,
};
polygonList.forEach((citem) => {
const poly = new AMap.Polygon();
poly.setOptions({ ...config, ...citem, path: citem.path });
this.aMap.add(poly);
this._polygonList.push(poly);
});
}
//实际使用
currentMap.setPolygonList([
{
path: [
[121.568722, 31.317126],
[121.65112, 31.317126],
[121.64906, 31.28251],
[121.566662, 31.286031],
],
},
{
path: [
[121.776895, 31.121916],
[121.628117, 31.194152],
[121.607861, 31.102773],
[121.751026, 31.051903],
],
},
]);
六 绘制车辆实时轨迹
js
/**
* 清除轨迹相关的覆盖物
*/
public clearTrajectory(): void {
this._overlaysMapObject.forEach((overlay, key) => {
if (key.includes("map-traj")) {
if (
overlay instanceof AMap.Marker &&
overlay.getExtData() == "stopdrawGj"
) {
overlay.stopMove(); //停止正在移动的轨迹
}
this.aMap.remove(overlay);
this._overlaysMapObject.delete(key);
}
});
}
/**
*
* @param 轨迹数据 cj02坐标 arrPath :[[121.4363,31.222]] || [[[121.4363,31.222],[121.4363,31.222]]]
* @param *轨迹线条样式 options
* 内含车辆开始位置,结束位置,以及车辆运行时轨迹动画
* 如果是成千上万条的轨迹数据 得使用https://lbs.amap.com/api/amap-ui/reference-amap-ui/mass-data/pathsimplifier 组件
*/
public drawTrajectory(
arrPath: [number, number][],
options?: AMap.PolylineOptions
): void {
let polylineStyle: AMap.PolylineOptions = {
strokeColor: "#1cac2e", //线颜色
strokeWeight: 7, //线宽
lineJoin: "round",
isOutline: true,
showDir: true, //显示箭头 3D 模式下不支持
borderWeight: 1,
dirColor: "#fff",
strokeStyle: "solid", //线样式
};
Object.assign(polylineStyle, options);
const start = arrPath[0]; //开始点
const end = arrPath[arrPath.length - 1]; //结束点
this.clearTrajectory(); //每次绘制下一次轨迹前 先清除上一次轨迹
this.addMarker({
icon: "https://a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
position: start,
key: "vehicleMarkStart",
title: "车辆开始位置",
});
const driveCar = new AMap.Marker({
position: start,
icon: new AMap.Icon({
image: "https://a.amap.com/jsapi_demos/static/demo-center-v2/car.png", //注意车头的方向
imageOffset: new AMap.Pixel(0, 0),
}),
offset: new AMap.Pixel(-13, -26),
extData: "stopdrawGj",
map: this.aMap,
});
const polyline = new AMap.Polyline({
...polylineStyle,
});
this.aMap.add(polyline);
// 路程总览
const allPahtline = new AMap.Polyline({
path: arrPath,
showDir: true,
strokeColor: "#28F", //线颜色
strokeWeight: 6, //线宽
});
this.aMap.add(allPahtline);
this.aMap.setFitView([polyline]);
driveCar.on("moving" as any, (e) => {
polyline.setPath(e.passedPath);
this.aMap.setCenter(e.target.getPosition(), true); //镜头随着动画移动
});
//开始绘制轨迹 //对于每秒钟接收的轨迹数据 做简化,否则会卡顿且会被延迟播放
driveCar.moveAlong(arrPath, {
// // 每一段的时长
duration: 200,
// JSAPI2.0 是否延道路自动设置角度在 moveAlong 里设置
autoRotation: true,
});
driveCar.on("movealong" as any, (e) => {
console.log("动画执行结束");
//最终动画执行结束
this.addMarker({
icon: "https://a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
position: end,
key: "vehicleMarkEnd",
title: "车辆结束位置",
});
driveCar.hide();
});
this._overlaysMapObject.set("map-traj-driveCar", driveCar);
this._overlaysMapObject.set("map-traj-live-polyline", polyline);
this._overlaysMapObject.set("map-traj-all-polyline", allPahtline);
}
//调用
const tdata: [number, number][] = [
[121.5326, 31.17348],
[121.5327, 31.1734],
[121.5327, 31.1734],
[121.5327, 31.17339],
[121.5327, 31.1734],
[121.5327, 31.17338],
[121.5327, 31.17338],
[121.5327, 31.17338],
[121.5327, 31.17338],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17335],
[121.5326, 31.17335],
[121.5326, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5326, 31.17335],
[121.5327, 31.17332],
[121.533, 31.1731],
[121.533, 31.173],
[121.5336, 31.17312],
[121.5344, 31.17336],
[121.5255, 31.16332],
[121.5267, 31.16382],
[121.5278, 31.16425],
[121.5292, 31.1647],
[121.5305, 31.16506],
[121.5316, 31.16553],
[121.5321, 31.16562],
[121.5322, 31.16532],
[121.5322, 31.1653],
[121.5322, 31.1653],
[121.5322, 31.1653],
[121.5322, 31.1653],
[121.5322, 31.1653],
[121.5322, 31.1653],
[121.5322, 31.1653],
[121.5322, 31.16529],
[121.5322, 31.16529],
[121.5322, 31.16529],
[121.5322, 31.16529],
[121.5322, 31.16529],
[121.5322, 31.16529],
[121.5323, 31.16524],
[121.5326, 31.16475],
[121.5328, 31.1644],
[121.5328, 31.16429],
[121.5331, 31.16372],
[121.5334, 31.16321],
[121.5335, 31.16302],
[121.5335, 31.1627],
[121.5328, 31.16236],
[121.532, 31.162],
[121.5311, 31.16157],
[121.5308, 31.16145],
[121.5307, 31.16146],
[121.5307, 31.16147],
[121.5307, 31.16147],
[121.5307, 31.16147],
[121.5307, 31.16146],
[121.5307, 31.16146],
[121.5307, 31.16146],
[121.5307, 31.16148],
[121.5307, 31.16148],
[121.5307, 31.16148],
[121.5307, 31.16148],
[121.5307, 31.16148],
[121.5307, 31.16148],
[121.5307, 31.16148],
[121.5307, 31.16148],
[121.5307, 31.16148],
[121.5307, 31.16146],
[121.5304, 31.16122],
[121.5303, 31.16122],
[121.5303, 31.16123],
[121.5302, 31.16115],
[121.5299, 31.16081],
[121.5304, 31.16002],
[121.531, 31.15898],
[121.5311, 31.15876],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5312, 31.1586],
[121.5315, 31.1581],
[121.532, 31.1572],
[121.5326, 31.15606],
[121.533, 31.15545],
[121.5327, 31.15534],
[121.5325, 31.15534],
[121.5325, 31.15536],
[121.5325, 31.15538],
[121.5325, 31.15537],
[121.5325, 31.15537],
[121.5325, 31.15537],
[121.5325, 31.15535],
[121.5325, 31.15535],
[121.5325, 31.15533],
[121.5326, 31.15533],
[121.5326, 31.15531],
[121.5324, 31.15527],
[121.5316, 31.15508],
[121.5308, 31.15487],
[121.5305, 31.15475],
[121.5305, 31.15473],
[121.5303, 31.15461],
[121.5295, 31.15433],
[121.5289, 31.15353],
[121.5293, 31.15257],
[121.5297, 31.15203],
[121.5297, 31.15202],
[121.5297, 31.15202],
[121.5297, 31.15201],
[121.5297, 31.15168],
[121.5299, 31.15163],
];
// currentMap.drawEasyrajectory(tdata);
currentMap.drawTrajectory(tdata)


最后附上一个简易版的轨迹 直接传入数据 然后绘制轨迹
js
/**
*
* @param 轨迹数据 arrPath
* @param 轨迹线条样式 options
* 简易车辆轨迹 不包含动画-直接生成轨迹
*/
public drawEasyrajectory(
arrPath: [number, number][],
options?: AMap.PolylineOptions
): void {
let polylineStyle: AMap.PolylineOptions = {
strokeColor: "#1cac2e", //线颜色
strokeWeight: 7, //线宽
lineJoin: "round",
isOutline: true,
showDir: true, //显示箭头 3D 模式下不支持
borderWeight: 1,
dirColor: "#fff",
strokeStyle: "solid", //线样式
};
Object.assign(polylineStyle, options);
this.clearTrajectory(); //每次绘制下一次轨迹前 先清除上一次轨迹
// 路程总览
const allPahtline = new AMap.Polyline({
path: arrPath,
showDir: true,
strokeColor: "#1cac2e", //线颜色
strokeWeight: 10, //线宽
});
this.aMap.add(allPahtline);
this._overlaysMapObject.set("map-traj-all-polyline", allPahtline);
}
七 逆地理编码(地址 -> 坐标),(坐标 -> 地址)支持批量最多20
根据地址 查询对应坐标信息,以及根据坐标查询地址信息
js
/**
* 逆地理编码(地址 -> 坐标)
* @param {*}geocoder 配置
* @param {*}address 文本地址批量查询时字符串以逗号分开传入,最多20个
* @param {*}successCollbackFn 成功后的信息的回调
*/
public byAddressGetLocation(
geoOptions: AMap.GeocoderOptions,
address: string,
successCollbackFn: (r: Regeocode[]) => void
): void {
const geocoder = new AMap.Geocoder({
extensions: "all",
...geoOptions,
});
//@ts-ignore
geocoder.getLocation(address, (status, result: GeocodeResponse) => {
if (status === "complete" && result.regeocodes) {
successCollbackFn(result.regeocodes);
} else {
successCollbackFn([]);
}
});
}
/**
* 逆地理编码(坐标 -> 地址)支持批量最多20
* @param geoOptions geocoder 配置
* @param location 二维的坐标数组,以批量的传入以及返回形式
* @param successCollbackFn 成功后的信息的回调
*/
public byLocationGetAddress(
geoOptions: AMap.GeocoderOptions,
location: AMap.Vector2[],
successCollbackFn: (r: Regeocode[]) => void
): void {
const geocoder = new AMap.Geocoder({
radius: 1000,
extensions: "all",
...geoOptions,
});
//经纬度转地址
geocoder.getAddress(
//@ts-ignore //根据官方提供的类型存在问题 此处忽悠类型
location,
(status: string, result: GeocodeResponse) => {
console.log(status);
console.log(result);
if (status === "complete" && result.regeocodes) {
successCollbackFn(result.regeocodes);
} else {
successCollbackFn([]);
}
}
);
}
调用如下:
//根据坐标查询
urrentMap.byLocationGetAddress(
{
city: "上海",
},
[[121.5326, 31.17348]],
(r) => {
console.log(r);
}
);
最后附上全部代码
js
import "@amap/amap-jsapi-types";
/**
* 高德地图使用的是 GCJ-02 坐标系,若采用的其他坐标系请初始化配置此处转换
*/
type CoordinateType = "gcj02" | "wgs84" | "bd09";
type MyMapOptions = {
_AmapCoordinate: CoordinateType;
} & AMap.MapOptions;
interface MarkerOptions extends AMap.MarkerOptions {
key: string; //标记的唯一标识
markClickFn?: (e: any) => void;
}
interface InfoOptions extends AMap.InfoOptions {
position: AMap.Vector2; //信息窗体类型扩展
}
interface DrawConfigType {
nobatch: boolean;
drawCompletedfn: (e: any) => void;
}
// 逆地理编码结果项类型
interface Regeocode {
addressComponent: any;
formattedAddress: string;
}
interface GeocodeResponse {
info: string;
regeocodes: Regeocode[];
}
//枚举所有点位类型
type AllLocationDataType =
| AMap.Vector2
| AMap.LngLat
| AMap.LngLatLike[]
| AMap.LngLatLike[][]
| AMap.LngLatLike[][][]
| [number, number][];
class myMap {
private _polygonList: AMap.Polygon[] = []; //多边形列表
private _InfoWindow: AMap.InfoWindow | null = null; //信息窗体
private _areaOutlineFeatures!: AMap.Polygon; //地图区域轮覆盖物
private _MouseTool: AMap.MouseTool | null = null; //鼠标工具
private _AmapCoordinate: CoordinateType = "gcj02"; //地图坐标系 默认自动转换(后续加上)
private _overlaysMapObject = new Map<
string,
| AMap.Marker
| AMap.Polyline
| AMap.Polygon
| AMap.Circle
| AMap.Rectangle
| AMap.MassMarks
>(); //覆盖物对象集合
public mapConfig: AMap.MapOptions = {
zoom: 11,
center: [121.732487, 31.086897],
viewMode: "3D",
mapStyle: "amap://styles/2a268264f80b6efc60d848838404e726",
rotateEnable: false,
pitchEnable: false,
skyColor: "#002d56", //天空颜色 倾斜后才会产生 仅限于3D 模式下
};
public aMap!: AMap.Map; //地图对象
/**
* 地图初始化
* @param {dom元素} el 传入地图容器 DIV 的 ID 值或者 DIV 对象
* @param {配置参数} config 对传入的配置合并
* @return {Promise<void>} 返回一个 Promise 对象,表示地图初始化完成
*/
public init(
el: string | HTMLDivElement,
config: MyMapOptions
): Promise<typeof AMap> {
Object.assign(this.mapConfig, config);
if (config._AmapCoordinate) {
this._AmapCoordinate = config._AmapCoordinate;
}
return new Promise((resolve, reject) => {
initMap().then((AMap) => {
this.aMap = new AMap.Map(el, {
...this.mapConfig,
});
this.aMap.on("complete", () => {
resolve(AMap);
});
});
});
}
/**
* 设置地图区域轮廓
* 通过行政区查询获取地图区域轮廓,最后绘制轮廓
* @param lineConfig 轮廓线条配置
* @param districtOptions 区域查询配置
*/
public setMapAreaOutline(
lineConfig?: AMap.PolygonOptions,
districtOptions?: { keyword: string } & AMap.DistrictSearchOptions
): void {
const config: AMap.PolygonOptions = {
strokeWeight: 4,
strokeColor: "#004eff",
fillColor: "",
fillOpacity: 0.3,
zIndex: 10,
bubble: true,
};
Object.assign(config, lineConfig);
let disOptipns: { keyword: string } & AMap.DistrictSearchOptions = {
extensions: "all",
level: "district",
subdistrict: 1,
showbiz: false, //最后一级返回街道信息
keyword: "310115",
};
Object.assign(disOptipns, districtOptions);
new AMap.DistrictSearch({
extensions: "all",
level: "district",
subdistrict: 1,
showbiz: false, //最后一级返回街道信息
}).search(disOptipns.keyword, (status, result) => {
if (status === "complete" && result.districtList.length > 0) {
const holes = result.districtList[0].boundaries;
this._areaOutlineFeatures = new AMap.Polygon();
this._areaOutlineFeatures.setOptions({ ...config, path: holes });
this.aMap.add(this._areaOutlineFeatures);
}
});
}
/**
* 添加一个点位
* @param markConfig mark配置
*/
public addMarker(markConfig: MarkerOptions): void {
const fconfig: MarkerOptions = {
clickable: true,
position: undefined,
anchor: "bottom-center",
icon: "https://a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
extData: {},
key: "", //key 点位唯一标识 后期用于控制某个点
};
Object.assign(fconfig, markConfig);
if (!this._overlaysMapObject.has(fconfig.key)) {
const mark = new AMap.Marker({
...fconfig,
});
if (fconfig.markClickFn) {
mark.on("click", (e) => {
fconfig.markClickFn && fconfig.markClickFn(e);
});
}
this._overlaysMapObject.set(fconfig.key, mark);
this.aMap.add(mark);
} else {
this._overlaysMapObject.get(fconfig.key)?.show();
}
}
/**
*
* @param opt 信息窗体配置
* @description 打开一个信息窗体
* 关键参数 InfoOptions : {position:[123.22,31.22] , content:(String | HTMLElement)}
*/
public openInfoWindow(opt: InfoOptions): void {
const infoWindow = new AMap.InfoWindow({
isCustom: true,
// offset: new AMap.Pixel(0, -50), //信息窗体偏移量
autoMove: true,
...opt,
});
this._InfoWindow = infoWindow;
infoWindow.open(this.aMap, opt.position);
}
/**
* 关闭信息窗体
*/
public closeInfoWindow(): void {
if (this._InfoWindow) {
this._InfoWindow.close();
this._InfoWindow = null;
}
}
/**
* @param config 海量点配置
* @param data.style 样式索引值 对应的是config.style的自定义点的样式下标索引(与z-index无关)
* @description 在地图上显示大量的点位数据
* click事件回调通过InfoWindow 将页面的dom 和 InfoWindow相关联亦可实现海量点信息窗展示
*/
public addMassMarks<T>(
data: { lnglat: AMap.Vector2; otherData: T; style: number }[],
config: AMap.MassMarkersOptions & MarkerOptions
): void {
if (!this._overlaysMapObject.has(config.key)) {
const mass = new AMap.MassMarks(data, {
...config,
});
if (config.markClickFn) {
mass.on("click", (e) => {
config.markClickFn && config.markClickFn(e);
});
}
mass.setMap(this.aMap);
this._overlaysMapObject.set(config.key, mass);
}
}
/**
* 使用mouseTool 插件 绘制电子围栏
* 鼠标单击地图选点/线,右键结束
* @param drawConfig: {nobatch : 是否批量绘制 电子围栏(多边形)} nobatch ? '每次只能绘制一个' : '不限制'
* @param drawCompletedfn 每次绘制完毕的回调
*/
public drawpolygon(
polygonConfig: AMap.PolygonOptions,
drawConfig: DrawConfigType
): void {
if (!this._MouseTool) {
this._MouseTool = new AMap.MouseTool(this.aMap);
}
const initPolyConfig: AMap.PolygonOptions = {
fillColor: "#00b0ff",
strokeColor: "#80d8ff",
strokeWeight: 2,
bubble: true,
zIndex: 130,
};
Object.assign(initPolyConfig, polygonConfig);
this._MouseTool.polygon(initPolyConfig);
this._MouseTool.on("draw", (e: any) => {
//每次绘制完图形的回调
if (drawConfig.nobatch) {
if (this._polygonList.length) {
this.aMap.remove(this._polygonList);
this._polygonList = [];
}
}
this._polygonList.push(e.obj);
drawConfig.drawCompletedfn(e);
});
}
/**
* 关闭鼠标工具
*/
public closeDrawpolygon(): void {
if (this._MouseTool) {
this._MouseTool.close();
this._MouseTool = null;
}
}
/**
* 填充电子围栏(多边形)
*/
public setPolygonList(polygonList: AMap.PolygonOptions[]): void {
const config: AMap.PolygonOptions = {
strokeWeight: 4,
strokeColor: "#004eff",
fillColor: "#80d8ff",
fillOpacity: 0.3,
zIndex: 10,
bubble: true,
};
polygonList.forEach((citem) => {
const poly = new AMap.Polygon();
poly.setOptions({ ...config, ...citem, path: citem.path });
this.aMap.add(poly);
this._polygonList.push(poly);
});
}
/**
* 获取已绘制的图形路径
* @return 多边形轮廓线的节点坐标数组。 支持 单个普通多边形({Array }),单个带孔多边形({Array<Array >}),多个带孔多边形({Array<Array<Array >>})
*/
public getDrawedpolygon():
| AMap.LngLat[]
| AMap.LngLat[][]
| AMap.LngLat[][][] {
return this._polygonList.map((polygon) => {
return polygon.getPath() as AMap.LngLat[];
});
}
/**
*
* @param 轨迹数据 cj02坐标 arrPath :[[121.4363,31.222]] || [[[121.4363,31.222],[121.4363,31.222]]]
* @param *轨迹线条样式 options
* 内含车辆开始位置,结束位置,以及车辆运行时轨迹动画
* 如果是成千上万条的轨迹数据 得使用https://lbs.amap.com/api/amap-ui/reference-amap-ui/mass-data/pathsimplifier 组件
*/
public drawTrajectory(
arrPath: [number, number][],
options?: AMap.PolylineOptions
): void {
let polylineStyle: AMap.PolylineOptions = {
strokeColor: "#1cac2e", //线颜色
strokeWeight: 7, //线宽
lineJoin: "round",
isOutline: true,
showDir: true, //显示箭头 3D 模式下不支持
borderWeight: 1,
dirColor: "#fff",
strokeStyle: "solid", //线样式
};
Object.assign(polylineStyle, options);
const start = arrPath[0]; //开始点
const end = arrPath[arrPath.length - 1]; //结束点
this.clearTrajectory(); //每次绘制下一次轨迹前 先清除上一次轨迹
this.addMarker({
icon: "https://a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
position: start,
key: "vehicleMarkStart",
title: "车辆开始位置",
});
const driveCar = new AMap.Marker({
position: start,
icon: new AMap.Icon({
image: "https://a.amap.com/jsapi_demos/static/demo-center-v2/car.png", //注意车头的方向
imageOffset: new AMap.Pixel(0, 0),
}),
offset: new AMap.Pixel(-13, -26),
extData: "stopdrawGj",
map: this.aMap,
});
const polyline = new AMap.Polyline({
...polylineStyle,
});
this.aMap.add(polyline);
// 路程总览
const allPahtline = new AMap.Polyline({
path: arrPath,
showDir: true,
strokeColor: "#28F", //线颜色
strokeWeight: 6, //线宽
});
this.aMap.add(allPahtline);
this.aMap.setFitView([polyline]);
driveCar.on("moving" as any, (e) => {
polyline.setPath(e.passedPath);
this.aMap.setCenter(e.target.getPosition(), true); //镜头随着动画移动
});
//开始绘制轨迹 //对于每秒钟接收的轨迹数据 做简化,否则会卡顿且会被延迟播放
driveCar.moveAlong(arrPath, {
// // 每一段的时长
duration: 200,
// JSAPI2.0 是否延道路自动设置角度在 moveAlong 里设置
autoRotation: true,
});
driveCar.on("movealong" as any, (e) => {
console.log("动画执行结束");
//最终动画执行结束
this.addMarker({
icon: "https://a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
position: end,
key: "vehicleMarkEnd",
title: "车辆结束位置",
});
driveCar.hide();
});
this._overlaysMapObject.set("map-traj-driveCar", driveCar);
this._overlaysMapObject.set("map-traj-live-polyline", polyline);
this._overlaysMapObject.set("map-traj-all-polyline", allPahtline);
}
/**
*
* @param 轨迹数据 arrPath
* @param 轨迹线条样式 options
* 简易车辆轨迹 不包含动画-直接生成轨迹
*/
public drawEasyrajectory(
arrPath: [number, number][],
options?: AMap.PolylineOptions
): void {
let polylineStyle: AMap.PolylineOptions = {
strokeColor: "#1cac2e", //线颜色
strokeWeight: 7, //线宽
lineJoin: "round",
isOutline: true,
showDir: true, //显示箭头 3D 模式下不支持
borderWeight: 1,
dirColor: "#fff",
strokeStyle: "solid", //线样式
};
Object.assign(polylineStyle, options);
this.clearTrajectory(); //每次绘制下一次轨迹前 先清除上一次轨迹
// 路程总览
const allPahtline = new AMap.Polyline({
path: arrPath,
showDir: true,
strokeColor: "#1cac2e", //线颜色
strokeWeight: 10, //线宽
});
this.aMap.add(allPahtline);
this._overlaysMapObject.set("map-traj-all-polyline", allPahtline);
}
/**
* 逆地理编码(地址 -> 坐标)
* @param {*}geocoder 配置
* @param {*}address 文本地址批量查询时字符串以逗号分开传入,最多20个
* @param {*}successCollbackFn 成功后的信息的回调
*/
public byAddressGetLocation(
geoOptions: AMap.GeocoderOptions,
address: string,
successCollbackFn: (r: Regeocode[]) => void
): void {
const geocoder = new AMap.Geocoder({
extensions: "all",
...geoOptions,
});
//@ts-ignore
geocoder.getLocation(address, (status, result: GeocodeResponse) => {
if (status === "complete" && result.regeocodes) {
successCollbackFn(result.regeocodes);
} else {
successCollbackFn([]);
}
});
}
/**
* 逆地理编码(坐标 -> 地址)支持批量最多20
* @param geoOptions geocoder 配置
* @param location 二维的坐标数组,以批量的传入以及返回形式
* @param successCollbackFn 成功后的信息的回调
*/
public byLocationGetAddress(
geoOptions: AMap.GeocoderOptions,
location: AMap.Vector2[],
successCollbackFn: (r: Regeocode[]) => void
): void {
const geocoder = new AMap.Geocoder({
radius: 1000,
extensions: "all",
...geoOptions,
});
//经纬度转地址
geocoder.getAddress(
//@ts-ignore //根据官方提供的类型存在问题 此处忽悠类型
location,
(status: string, result: GeocodeResponse) => {
console.log(status);
console.log(result);
if (status === "complete" && result.regeocodes) {
successCollbackFn(result.regeocodes);
} else {
successCollbackFn([]);
}
}
);
}
/**
* 清除轨迹相关的覆盖物
*/
public clearTrajectory(): void {
this._overlaysMapObject.forEach((overlay, key) => {
if (key.includes("map-traj")) {
if (
overlay instanceof AMap.Marker &&
overlay.getExtData() == "stopdrawGj"
) {
overlay.stopMove(); //停止正在移动的轨迹
}
this.aMap.remove(overlay);
this._overlaysMapObject.delete(key);
}
});
}
/**
* 清除地图覆盖物(不包括轮廓),但包括停止轨迹
*/
public clearMap(): void {
this.aMap.clearInfoWindow();
this._overlaysMapObject.forEach((overlay, key) => {
if (
overlay instanceof AMap.Marker &&
overlay.getExtData() == "stopdrawGj"
) {
overlay.stopMove(); //停止正在移动的轨迹
}
this.aMap.remove(overlay);
});
this._overlaysMapObject.clear();
this.aMap.remove(this._polygonList); //清除多边形
}
/**
* 对外暴露的获取地图对象方法
* @returns {AMap.Map} 返回地图对象
*/
public getAmapObj(): AMap.Map {
return this.aMap;
}
// /**
// * 对高德坐标系进行转换
// * 全部统一转换为高德所需坐标系 gcj-02
// */
// public formatCoordinateType(
// type: CoordinateType = this._AmapCoordinate,
// geoData: AllLocationDataType
// ): AllLocationDataType {
// function getDataType(data: AllLocationDataType) {
// if(data){
// }
// }
// switch (type) {
// case "bd09":
// break;
// case "wgs84":
// break;
// case "gcj02":
// return geoData;
// }
// return geoData;
// }
}
export function initMap(): Promise<typeof AMap> {
return new Promise((resolve, reject) => {
//如果全局已经存在AMap对象 则直接返回
if (window.AMap) {
resolve(window.AMap);
return;
}
AMapLoader.load<typeof AMap>({
key: "XXXX", // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JS API 的版本,缺省时默认为 1.4.15
plugins: [
"AMap.MoveAnimation,AMap.MouseTool,AMap.PlaceSearch,AMap.DistrictSearch,AMap.Geocoder",
], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
// "AMapUI": { // 是否加载 AMapUI,缺省不加载
// "version": '1.1', // AMapUI 版本
// "plugins": [], // 需要加载的 AMapUI ui插件
// },
// "Loca": { // 是否加载 Loca, 缺省不加载
// "version": '2.0' // Loca 版本
// },
})
.then((AMap) => {
window.AMap = AMap;
resolve(AMap); //防止上方全局添加amap失败手动返回Amap
})
.catch((e) => {
console.error(e); //加载错误提示
reject(e);
});
});
}
export default myMap;
vue代码:
<template>
<div class="home" id="mapId">
<div class="btnList">
<el-button size="small" @click="addMark()">添加点位</el-button>
<el-button size="small" @click="openMarkInfoWindow()"
>点击点位打开信息窗体</el-button
>
<el-button size="small" @click="addMassMarks()">添加海量点</el-button>
<el-button size="small" @click="startDrawRect()"
>点击开始绘制围栏</el-button
>
<el-button size="small" @click="closeDrawRect()">结束绘制围栏</el-button>
<el-button size="small" @click="fillRect()">填充绘制围栏</el-button>
<el-button size="small" @click="currentMap.clearMap()"
>清除地图覆盖物</el-button
>
<el-button size="small" @click="playMapTrajectory()"
>开始绘制轨迹</el-button
>
<el-button size="small" @click="searchAddress()">地址查询</el-button>
<el-button size="small" @click="getLocation()">获取坐标</el-button>
</div>
<div ref="elemntRef" class="InfoWindowClass" v-if="showInfoWindow">
<div class="InfoWindowClass-header">
<span>信息窗口标题{{ otherData.name }}</span>
<span class="close-btn" @click="currentMap.closeInfoWindow()"></span>
</div>
<div class="InfoWindowClass-content">这里是信息窗口的内容区域...</div>
<div class="InfoWindowClass-arrow"></div>
</div>
</div>
</template>
<script lang="ts" setup>
import myMap from "@/utils/amap-utils";
import { onMounted, ref, nextTick } from "vue";
const elemntRef = ref();
const showInfoWindow = ref(false);
const otherData: any = ref({});
interface MassDataType {
name: string;
age: number;
}
let currentMap: myMap;
onMounted(() => {
currentMap = new myMap();
currentMap
.init("mapId", { _AmapCoordinate: "gcj02" })
.then((res) => {
console.log("地图初始化成功", res);
currentMap.setMapAreaOutline();
})
.catch((err) => {
console.error("地图初始化失败", err);
});
});
const addMark = () => {
currentMap.addMarker({
icon: "https://a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
position: [121.698747, 31.12806],
key: "mark1",
title: "鼠标显示的内容",
extData: {
otherData: 111,
},
markClickFn: (e) => {
console.log(e);
},
});
};
const openMarkInfoWindow = () => {
currentMap.addMarker({
icon: "https://a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
position: [121.698652, 31.12706],
key: "mark2",
extData: {
otherData: 111,
},
markClickFn: (e) => {
showInfoWindow.value = true;
nextTick(() => {
currentMap.openInfoWindow({
position: e.target.getPosition(),
content: elemntRef.value,
offset: new AMap.Pixel(0, -80), //信息窗体偏移量
});
});
},
});
};
const addMassMarks = () => {
currentMap.addMassMarks<MassDataType>(
[
{
lnglat: [121.698652, 31.12706],
otherData: {
name: "景县1111",
age: 17,
},
style: 0,
},
{
lnglat: [121.698421, 31.1212],
otherData: {
name: "景县2222",
age: 17,
},
style: 1,
},
{
lnglat: [121.694153, 31.12412],
otherData: {
name: "景县3333",
age: 17,
},
style: 1,
},
{
lnglat: [121.698121, 31.12711],
otherData: {
name: "景县4444",
age: 17,
},
style: 0,
},
{
lnglat: [121.698147, 31.124516],
otherData: {
name: "景县5555",
age: 17,
},
style: 1,
},
],
{
key: "mass1",
style: [
{
url: "https://a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
size: new AMap.Size(30, 30),
rotation: 0,
},
{
url: "https://webapi.amap.com/images/mass/mass1.png",
size: new AMap.Size(30, 30),
rotation: 0,
},
],
zIndex: 130,
markClickFn: (e) => {
console.log("海量点点击事件", e);
otherData.value = e.data.otherData;
showInfoWindow.value = true;
nextTick(() => {
currentMap.openInfoWindow({
position: e.data.lnglat,
content: elemntRef.value,
offset: [15, 0],
});
});
},
}
);
};
const startDrawRect = () => {
currentMap.drawpolygon(
{
strokeColor: "#FF33FF", //线颜色
fillColor: "#1791fc", //填充颜色
strokeWeight: 3, //线宽
fillOpacity: 0.2, //填充透明度
zIndex: 100,
},
{
nobatch: false,
drawCompletedfn: (e: any) => {
console.log("绘制完成回调", e);
console.log(currentMap.getDrawedpolygon());
},
}
);
};
const closeDrawRect = () => {
currentMap.closeDrawpolygon();
};
const fillRect = () => {
currentMap.setPolygonList([
{
path: [
[121.568722, 31.317126],
[121.65112, 31.317126],
[121.64906, 31.28251],
[121.566662, 31.286031],
],
},
{
path: [
[121.776895, 31.121916],
[121.628117, 31.194152],
[121.607861, 31.102773],
[121.751026, 31.051903],
],
},
]);
};
const playMapTrajectory = () => {
const tdata: [number, number][] = [
[121.5326, 31.17348],
[121.5327, 31.1734],
[121.5327, 31.1734],
[121.5327, 31.17339],
[121.5327, 31.1734],
[121.5327, 31.17338],
[121.5327, 31.17338],
[121.5327, 31.17338],
[121.5327, 31.17338],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17337],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17336],
[121.5326, 31.17335],
[121.5326, 31.17335],
[121.5326, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5327, 31.17335],
[121.5326, 31.17335],
[121.5327, 31.17332],
[121.533, 31.1731],
[121.533, 31.173],
[121.5336, 31.17312],
[121.5344, 31.17336],
[121.5255, 31.16332],
[121.5267, 31.16382],
[121.5278, 31.16425],
[121.5292, 31.1647],
[121.5305, 31.16506],
[121.5316, 31.16553],
[121.5321, 31.16562],
[121.5322, 31.16532],
[121.5322, 31.1653],
[121.5322, 31.1653],
[121.5322, 31.1653],
[121.5322, 31.1653],
[121.5322, 31.1653],
[121.5322, 31.1653],
[121.5322, 31.1653],
[121.5322, 31.16529],
[121.5322, 31.16529],
[121.5322, 31.16529],
[121.5322, 31.16529],
[121.5322, 31.16529],
[121.5322, 31.16529],
[121.5323, 31.16524],
[121.5326, 31.16475],
[121.5328, 31.1644],
[121.5328, 31.16429],
[121.5331, 31.16372],
[121.5334, 31.16321],
[121.5335, 31.16302],
[121.5335, 31.1627],
[121.5328, 31.16236],
[121.532, 31.162],
[121.5311, 31.16157],
[121.5308, 31.16145],
[121.5307, 31.16146],
[121.5307, 31.16147],
[121.5307, 31.16147],
[121.5307, 31.16147],
[121.5307, 31.16146],
[121.5307, 31.16146],
[121.5307, 31.16146],
[121.5307, 31.16148],
[121.5307, 31.16148],
[121.5307, 31.16148],
[121.5307, 31.16148],
[121.5307, 31.16148],
[121.5307, 31.16148],
[121.5307, 31.16148],
[121.5307, 31.16148],
[121.5307, 31.16148],
[121.5307, 31.16146],
[121.5304, 31.16122],
[121.5303, 31.16122],
[121.5303, 31.16123],
[121.5302, 31.16115],
[121.5299, 31.16081],
[121.5304, 31.16002],
[121.531, 31.15898],
[121.5311, 31.15876],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5311, 31.15875],
[121.5312, 31.1586],
[121.5315, 31.1581],
[121.532, 31.1572],
[121.5326, 31.15606],
[121.533, 31.15545],
[121.5327, 31.15534],
[121.5325, 31.15534],
[121.5325, 31.15536],
[121.5325, 31.15538],
[121.5325, 31.15537],
[121.5325, 31.15537],
[121.5325, 31.15537],
[121.5325, 31.15535],
[121.5325, 31.15535],
[121.5325, 31.15533],
[121.5326, 31.15533],
[121.5326, 31.15531],
[121.5324, 31.15527],
[121.5316, 31.15508],
[121.5308, 31.15487],
[121.5305, 31.15475],
[121.5305, 31.15473],
[121.5303, 31.15461],
[121.5295, 31.15433],
[121.5289, 31.15353],
[121.5293, 31.15257],
[121.5297, 31.15203],
[121.5297, 31.15202],
[121.5297, 31.15202],
[121.5297, 31.15201],
[121.5297, 31.15168],
[121.5299, 31.15163],
];
// currentMap.drawEasyrajectory(tdata);
currentMap.drawTrajectory(tdata);
};
const searchAddress = () => {
currentMap.byLocationGetAddress(
{
city: "上海",
},
[[121.5326, 31.17348]],
(r) => {
console.log(r);
}
);
};
const getLocation = () => {
currentMap.byAddressGetLocation(
{
city: "上海",
},
"上海市浦东新区",
(r) => {
console.log(r);
}
);
};
</script>
<style lang="less" scoped>
.border {
border: 1px solid red;
box-sizing: border-box;
}
// 基础信息窗样式
.InfoWindowClass {
background-color: #fff;
border-radius: 6px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
overflow: hidden;
z-index: 1000;
width: 300px;
// 头部区域样式
&-header {
padding: 12px 16px;
border-bottom: 1px solid #e8e8e8;
position: relative;
// 关闭按钮样式
.close-btn {
position: absolute;
top: 12px;
right: 12px;
width: 16px;
height: 16px;
cursor: pointer;
color: #999;
font-size: 14px;
line-height: 14px;
&:hover {
color: #333;
}
&:before,
&:after {
content: "";
position: absolute;
width: 16px;
height: 2px;
background-color: currentColor;
top: 50%;
left: 0;
transform: translateY(-50%);
}
&:before {
transform: translateY(-50%) rotate(45deg);
}
&:after {
transform: translateY(-50%) rotate(-45deg);
}
}
}
// 内容区域样式
&-content {
padding: 16px;
font-size: 14px;
line-height: 1.5;
}
// 底部箭头样式
&-arrow {
position: absolute;
bottom: -7px;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 12px solid transparent;
border-right: 12px solid transparent;
border-top: 12px solid #fff;
border-bottom: 0;
z-index: 1;
// // 阴影增强立体感
// &:after {
// content: "";
// position: absolute;
// top: 1px;
// left: -12px;
// width: 0;
// height: 0;
// border-left: 12px solid transparent;
// border-right: 12px solid transparent;
// border-top: 12px solid rgba(0, 0, 0, 0.2);
// border-bottom: 0;
// z-index: -1;
// }
}
}
.home {
position: relative;
width: 100vw;
height: 100vh;
.btnList {
position: absolute;
top: 0;
left: 0;
width: 150px;
height: 250px;
z-index: 10;
display: flex;
flex-direction: column;
justify-content: space-around;
background-color: rgb(211, 201, 187);
align-items: center;
}
.el-button + .el-button {
margin-left: 0;
}
}
</style>
后续若有其他未实现的方法 亦可自行添加即可