效果图:

一 、注册/登录获取key
使用手机号 / 邮箱注册开发者账号,完成实名认证(个人可身份证 / 企业可执照)。

html
<template>
<div style="height: 50px; display: flex; align-items: center">
<div style="width: 200px; display: flex; justify-content: center">
<el-select v-model="option.mapOptions.lang" placeholder="请选择语言">
<el-option
v-for="item in langOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</div>
<div style="width: 200px; display: flex; justify-content: center">
<el-select
v-model="option.mapOptions.amapStyleKey"
placeholder="请选择主题"
>
<el-option
v-for="item in themeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</div>
<div style="width: 200px; display: flex; justify-content: center">
<el-radio-group v-model="option.mapOptions.viewMode">
<el-radio
v-for="item in viewModeOptions"
:key="item.value"
:label="item.value"
>{{ item.label }}</el-radio
>
</el-radio-group>
</div>
<div style="width: 200px; display: flex; justify-content: center">
<el-select
v-model="option.mapOptions.mapMarkerType"
placeholder="请选择标记样式"
>
<el-option
v-for="item in MarkerOptions"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</div>
</div>
<div ref="vChartRef" style="width: 100%; height: calc(100vh - 50px)"></div>
</template>
<script setup lang="ts">
import { ref, toRefs, onMounted, watch } from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";
import {
FeaturesEnum,
LangEnum,
MarkerEnum,
ThemeEnum,
ViewModeEnum,
} from "./chartEnum";
import { reactive } from "vue";
import { isArray } from "lodash";
/*********************** 地图切换 ***********************/
const themeOptions = [
{
value: ThemeEnum.NORMAL,
label: "标准",
},
{
value: ThemeEnum.DARK,
label: "幻影黑",
},
{
value: ThemeEnum.LIGHT,
label: "月光银",
},
{
value: ThemeEnum.WHITES_MOKE,
label: "远山黛",
},
{
value: ThemeEnum.FRESH,
label: "草色青",
},
{
value: ThemeEnum.GREY,
label: "雅士灰",
},
{
value: ThemeEnum.GRAFFITI,
label: "涂鸦",
},
{
value: ThemeEnum.MACARON,
label: "马卡龙",
},
{
value: ThemeEnum.BLUE,
label: "靛青蓝",
},
{
value: ThemeEnum.DARKBLUE,
label: "极夜蓝",
},
{
value: ThemeEnum.WINE,
label: "酱籽",
},
{
value: ThemeEnum.WEIXIN,
label: "卫星",
},
];
const langOptions = [
{
value: LangEnum.ZH_CN,
label: "中文简体",
},
{
value: LangEnum.EN,
label: "英文",
},
{
value: LangEnum.ZH_EN,
label: "中英文对照",
},
];
const viewModeOptions = [
{
value: ViewModeEnum.PLANE,
label: "2D",
},
{
value: ViewModeEnum.STEREOSCOPIC,
label: "3D",
},
];
const featuresOptions = [
{
value: FeaturesEnum.BG,
label: "显示地图背景",
},
{
value: FeaturesEnum.POINT,
label: "显示标识",
},
{
value: FeaturesEnum.ROAD,
label: "显示道路",
},
{
value: FeaturesEnum.BUILDING,
label: "显示建筑",
},
];
const MarkerOptions = [
{
value: MarkerEnum.CIRCLE_MARKER,
label: "圆形标点",
},
{
value: MarkerEnum.MARKER,
label: "定位标点",
},
{
value: MarkerEnum.NONE,
label: "隐藏标点",
},
];
/*********************** 地图 ***********************/
const chartData = ref([
{
name: "某某地市",
value: 10,
position: [116.300467, 39.907761],
},
{
name: "某某地市",
value: 15,
position: [116.400567, 39.908761],
},
{
name: "某某地市",
value: 20,
position: [116.200467, 39.937761],
},
]);
const option = reactive({
mapOptions: {
pitch: 60, ///俯仰角度
skyColor: "#53A9DE", //天空颜色
amapKey: "AAAAASSDDDFFFFFFFFFFSDDDSDSADSDFSDFDDSD", //使用自己的高德应用key
amapStyleKey: ThemeEnum.DARK, //地图主题
amapStyleKeyCustom: "", //自定义地图样式
amapLon: 116.397428, //地图中心经度
amapLat: 39.90923, //地图中心纬度
amapZindex: 11, //初始缩放
marker: {
fillColor: "#E98984FF", //填充颜色
fillOpacity: 0.5, //透明度
strokeColor: "white", //边框颜色
strokeWeight: 2, //边框宽度
strokeOpacity: 0.5, //边框透明度
zIndex: 10, //层级
bubble: true, //鼠标悬停时是否显示信息窗体
cursor: "pointer", //鼠标悬停样式
clickable: true, //是否可点击
},
mapMarkerType: MarkerEnum.CIRCLE_MARKER, //标点类型
viewMode: ViewModeEnum.PLANE, // 2D/3D
lang: LangEnum.ZH_CN, //语言
features: [
FeaturesEnum.BG, //显示地图背景
FeaturesEnum.POINT, //显示标识
FeaturesEnum.ROAD, //显示道路
FeaturesEnum.BUILDING, //显示建筑
],
},
});
let {
amapKey,
amapStyleKey,
amapLon,
amapLat,
amapZindex,
mapMarkerType,
lang,
amapStyleKeyCustom,
features,
viewMode,
pitch,
skyColor,
marker,
} = toRefs(option.mapOptions);
let mapIns: any = null;
let markers: any = [];
let AMapIns: any = null;
const vChartRef = ref<HTMLElement>();
const dataHandle = (newData: any) => {
if (!mapIns && !AMapIns) {
initMap(option);
return;
}
if (isArray(newData)) {
// 先清除旧标记
mapIns.remove(markers);
markers = [];
// 记录新标记
if (mapMarkerType.value === MarkerEnum.MARKER) {
newData.forEach((markerItem: any) => {
const markerInstance = new AMapIns.Marker({
position: [markerItem.position[0], markerItem.position[1]],
offset: new AMapIns.Pixel(-13, -30),
});
markers.push(markerInstance);
markerInstance.setMap(mapIns);
});
} else if (mapMarkerType.value === MarkerEnum.CIRCLE_MARKER) {
newData.forEach((markerItem: any) => {
const markerInstance = new AMapIns.CircleMarker({
center: [markerItem.position[0], markerItem.position[1]],
radius: markerItem.value,
...marker.value,
});
markers.push(markerInstance);
markerInstance.setMap(mapIns);
});
}
}
};
const initMap = (newData: any) => {
// 初始化
AMapLoader.load({
key: amapKey.value, //api服务key--另外需要在public中使用安全密钥!!!
version: "1.4.8", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ["AMap.PlaceSearch", "AMap.AutoComplete"], // 需要使用的的插件列表
}).then((AMap: any) => {
AMapIns = AMap;
mapIns = new AMap.Map(vChartRef.value, {
resizeEnable: true,
zoom: amapZindex.value, // 地图显示的缩放级别
center: [amapLon.value, amapLat.value],
lang: lang.value,
features: features.value,
pitch: pitch.value, // 地图俯仰角度,有效范围 0 度- 83 度
skyColor: skyColor.value,
viewMode: viewMode.value, // 地图模式
willReadFrequently: true,
});
dataHandle(chartData.value);
let satellite = new AMap.TileLayer.Satellite();
let roadNet = new AMap.TileLayer.RoadNet();
if (newData.amapStyleKey === ThemeEnum.WEIXIN) {
mapIns.add([satellite, roadNet]);
} else {
mapIns.remove([satellite, roadNet]);
mapIns.setMapStyle(
`amap://styles/${
amapStyleKeyCustom.value !== ""
? amapStyleKeyCustom.value
: amapStyleKey.value
}`
);
}
});
};
// 监听语言变化
watch(lang, (newLang) => {
if (mapIns) {
mapIns.setLang(newLang);
}
});
// 监听主题变化
watch(amapStyleKey, (newStyle) => {
if (mapIns && AMapIns) {
let satellite = new AMapIns.TileLayer.Satellite();
let roadNet = new AMapIns.TileLayer.RoadNet();
if (newStyle === ThemeEnum.WEIXIN) {
mapIns.add([satellite, roadNet]);
} else {
mapIns.remove([satellite, roadNet]);
mapIns.setMapStyle(
`amap://styles/${
amapStyleKeyCustom.value !== "" ? amapStyleKeyCustom.value : newStyle
}`
);
}
}
});
// 监听视角模式变化
watch(viewMode, (newViewMode) => {
if (mapIns && AMapIns) {
try {
// 先设置俯仰角度
if (newViewMode === ViewModeEnum.STEREOSCOPIC) {
mapIns.setPitch(pitch.value);
} else {
mapIns.setPitch(0);
}
// 重新初始化地图以确保viewMode正确应用
const currentCenter = mapIns.getCenter();
const currentZoom = mapIns.getZoom();
const currentLang = lang.value;
const currentFeatures = features.value;
const currentSkyColor = skyColor.value;
const currentStyleKey = amapStyleKey.value;
const currentStyleKeyCustom = amapStyleKeyCustom.value;
// 销毁并重新创建地图
mapIns.destroy();
mapIns = new AMapIns.Map(vChartRef.value, {
resizeEnable: true,
zoom: currentZoom,
center: [currentCenter.lng, currentCenter.lat],
lang: currentLang,
features: currentFeatures,
pitch: newViewMode === ViewModeEnum.STEREOSCOPIC ? pitch.value : 0,
skyColor: currentSkyColor,
viewMode: newViewMode,
willReadFrequently: true,
});
// 重新添加标记
dataHandle(chartData.value);
// 重新设置地图样式
let satellite = new AMapIns.TileLayer.Satellite();
let roadNet = new AMapIns.TileLayer.RoadNet();
if (currentStyleKey === ThemeEnum.WEIXIN) {
mapIns.add([satellite, roadNet]);
} else {
mapIns.remove([satellite, roadNet]);
mapIns.setMapStyle(
`amap://styles/${
currentStyleKeyCustom !== ""
? currentStyleKeyCustom
: currentStyleKey
}`
);
}
} catch (error) {}
}
});
// 监听俯仰角度变化
watch(pitch, (newPitch) => {
if (mapIns) {
mapIns.setPitch(newPitch);
}
});
// 监听标记类型变化
watch(mapMarkerType, () => {
if (mapIns && AMapIns) {
// 重新处理数据以应用新的标记类型
dataHandle(chartData.value);
}
});
onMounted(() => {
initMap(option);
});
</script>
枚举
TypeScript
export enum ThemeEnum {
NORMAL = 'normal',
DARK = 'dark',
LIGHT = 'light',
WHITES_MOKE = 'whitesmoke',
FRESH = 'fresh',
GREY = 'grey',
GRAFFITI = 'graffiti',
MACARON = 'macaron',
BLUE = 'blue',
DARKBLUE = 'darkblue',
WINE = 'wine',
WEIXIN = 'tileLayer',
}
export enum LangEnum {
ZH_CN = 'zh_cn',
EN = 'en',
ZH_EN = 'zh_en',
}
export enum ViewModeEnum {
PLANE = '2D',
STEREOSCOPIC = '3D',
}
export enum FeaturesEnum {
BG = 'bg',
POINT = 'point',
ROAD = 'road',
BUILDING = 'building',
}
export enum MarkerEnum {
// 圆圈
CIRCLE_MARKER = 'CircleMarker',
// 定位标点
MARKER = 'Marker',
// 暂无
NONE = 'none',
}