基于高德地图JS API实现Vue地图选点组件

本文详细描述了如何在Vue项目中利用高德地图JSAPI2.0实现地址搜索功能,并将搜索结果显示给父组件以及支持地图中心点自动定位。开发者需要获取并设置Web端开发者Key,实现地图初始化、搜索事件监听和地址标记等功能。
摘要由CSDN通过智能技术生成

基于高德地图JS API2.0实现一个搜索选择地点后返回给父组件位置信息的功能,同时可以进行回显

1 创建key和秘钥

1.1 登录高德地图开放平台

打开开放平台地址

注册账号申请账号

1.2 创建应用

在这里插入图片描述

1.3 绑定服务创建秘钥

在这里插入图片描述

在这里插入图片描述

2 使用组件前准备

2.1 导入loader

推荐pnpm

pnpm i @amap/amap-jsapi-loader -D

2.2 在对应的组件设置秘钥

<script type="text/javascript" lang="ts">
window._AMapSecurityConfig = {
  securityJsCode: "安全秘钥"
};
</script>

2.3 引入css样式

<link rel="stylesheet" href="https://cache.amap.com/lbs/static/main1119.css" />

3 功能实现

3.1 初始化地图

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";
import { Search } from "@element-plus/icons-vue";

let map = null;
let aMap = null;
onMounted(() => {
  AMapLoader.load({
    key: "key", // 申请好的Web端开发者Key,首次调用 load 时必填
    version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
    plugins: ["AMap.PlaceSearch", "AMap.AutoComplete"] // 需要使用的的插件列表,如比例尺'AMap.Scale'等
  }).then(AMap => {
    // 第一参数是对应的div的id
    map = new AMap.Map("container", {
      // 设置地图容器id
      viewMode: "3D", // 是否为3D地图模式
      zoom: 11, // 初始化地图级别
      center: [116.397428, 39.90923] // 初始化地图中心点位置
    });
    aMap = AMap;
  });
});
onUnmounted(() => {
  map?.destroy();
});
</script>
<template>
  <div id="map-box">
    <div id="container" />
    
  </div>
</template>
<style scoped>
#map-box {
  width: 100%;
  height: 450px;
  position: relative;
}
#container {
  width: 100%;
  height: 100%;
}

#myPageTop {
  position: absolute;
  top: 5px;
  right: 10px;
  font-family: "Microsoft Yahei", Pinghei;
  font-size: 14px;
  background: none 0px 0px repeat scroll rgb(255, 255, 255);
  border-width: 1px;
  border-style: solid;
  border-color: rgb(204, 204, 204);
  border-image: initial;
  margin: 10px auto;
  padding: 6px;
}
#panel {
  background-color: white;
  max-height: 400px;
  overflow-y: auto;
}
</style>

3.2 增加搜索功能

function search() {
  const placeSearch = new aMap.PlaceSearch({
    pageSize: 10, // 单页显示结果条数
    pageIndex: 1, // 页码
    map: map, // 展现结果的地图实例
    panel: "panel", // 结果列表将在此容器中进行展示。
    autoFitView: true // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
  });
  //关键字查询
  placeSearch.search(keyword.value);
  placeSearch.on("selectChanged", function (e) {
    const data = e.selected.data;
    const temp = {
      province: data.pname,
      provinceCode: data.pcode,
      city: data.cityname,
      cityCode: data.citycode,
      county: data.adname,
      countyCode: data.adcode,
      storeAddr: data.address,
      storeDetailAddr: data.pname + data.cityname + data.adname + data.address,
      longitude: `${data.location.lng}`,
      latitude: `${data.location.lat}`
    };
    // 回调父组件
    emit("change", temp);
  });
}
// 宏注册emit
const emit = defineEmits(["change"]);

const keyword = ref("");
<template>
  <div id="map-box">
    <div id="container" />
    <!-- 增加的部分 -->
    <div id="myPageTop">
      <el-input
        @keyup.enter="search"
        placeholder="请输入地址"
        v-model="keyword"
      >
        <template #prepend>
          <el-button :icon="Search" @click="search" />
        </template>
      </el-input>
      <div id="panel" />
    </div>
  </div>
</template>

3.3 暴露增加标记函数

let loaded = false; // 判断地图是否完成渲染
const record = []; // 记录地图未加载完成之前的添加标签记录
// 循环渲染之前记录的地址
function loadRecord() {
  record.forEach(item => {
    addMarker(item.longitude, item.latitude, item.content);
  });
}
function addMarker(longitude: number, latitude: number, content: string) {
  if (!loaded) {
    record.push({ longitude, latitude, content });
    return;
  }
  if (!longitude || !latitude) return;
  const marker = new aMap.Marker({
    position: [longitude, latitude],
    icon: "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
    anchor: "bottom-center",
    offset: new aMap.Pixel(0, 0)
  });

  marker.setMap(map);
  marker.setTitle(content);
  // 设置label标签
  // label默认蓝框白底左上角显示,样式className为:amap-marker-label
  marker.setLabel({
    direction: "bottom",
    offset: new aMap.Pixel(0, 0), //设置文本标注偏移量
    content: `<div style='padding:1px 5px;'>${content}</div>` //设置文本标注内容
  });
  map.setZoomAndCenter(11, [longitude, latitude]); //同时设置地图层级与中心点
}
defineExpose({
  addMarker
});

4 全部代码

<link rel="stylesheet" href="https://cache.amap.com/lbs/static/main1119.css" />
<script type="text/javascript" lang="ts">
window._AMapSecurityConfig = {
  securityJsCode: "秘钥"
};
</script>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";
import { Search } from "@element-plus/icons-vue";

let map = null;
let aMap = null;
let loaded = false;
const record = []; // 记录地图未加载完成之前的添加标签记录
onMounted(() => {
  AMapLoader.load({
    key: "key", // 申请好的Web端开发者Key,首次调用 load 时必填
    version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
    plugins: ["AMap.PlaceSearch", "AMap.AutoComplete"] // 需要使用的的插件列表,如比例尺'AMap.Scale'等
  }).then(AMap => {
    // 第一参数是对应的div的id
    map = new AMap.Map("container", {
      // 设置地图容器id
      viewMode: "3D", // 是否为3D地图模式
      zoom: 11, // 初始化地图级别
      center: [116.397428, 39.90923] // 初始化地图中心点位置
    });
    aMap = AMap;
    // 地图加载完成后会触发此回调函数
    loaded = true;
    loadRecord();
  });
});
onUnmounted(() => {
  map?.destroy();
});
// 循环渲染之前记录的地址
function loadRecord() {
  record.forEach(item => {
    addMarker(item.longitude, item.latitude, item.content);
  });
}
function addMarker(longitude: number, latitude: number, content: string) {
  if (!loaded) {
    record.push({ longitude, latitude, content });
    return;
  }
  if (!longitude || !latitude) {
  	console.error("缺少必要信息")
  	return;
  }
  const marker = new aMap.Marker({
    position: [longitude, latitude],
    icon: "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
    anchor: "bottom-center",
    offset: new aMap.Pixel(0, 0)
  });

  marker.setMap(map);
  marker.setTitle(content);
  // 设置label标签
  // label默认蓝框白底左上角显示,样式className为:amap-marker-label
  marker.setLabel({
    direction: "bottom",
    offset: new aMap.Pixel(0, 0), //设置文本标注偏移量
    content: `<div style='padding:1px 5px;'>${content}</div>` //设置文本标注内容
  });
  map.setZoomAndCenter(11, [longitude, latitude]); //同时设置地图层级与中心点
}
defineExpose({
  addMarker
});
function search() {
  const placeSearch = new aMap.PlaceSearch({
    pageSize: 10, // 单页显示结果条数
    pageIndex: 1, // 页码
    map: map, // 展现结果的地图实例
    panel: "panel", // 结果列表将在此容器中进行展示。
    autoFitView: true // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
  });
  //关键字查询
  placeSearch.search(keyword.value);
  placeSearch.on("selectChanged", function (e) {
    const data = e.selected.data;
    const temp = {
      province: data.pname,
      provinceCode: data.pcode,
      city: data.cityname,
      cityCode: data.citycode,
      county: data.adname,
      countyCode: data.adcode,
      storeAddr: data.address,
      storeDetailAddr: data.pname + data.cityname + data.adname + data.address,
      longitude: `${data.location.lng}`,
      latitude: `${data.location.lat}`
    };
    // 回调父组件
    emit("change", temp);
  });
}
const emit = defineEmits(["change"]);

const keyword = ref("");
</script>

<template>
  <div id="map-box">
    <div id="container" />
    <!-- 增加的部分 -->
    <div id="myPageTop">
      <el-input
        @keyup.enter="search"
        placeholder="请输入地址"
        v-model="keyword"
      >
        <template #prepend>
          <el-button :icon="Search" @click="search" />
        </template>
      </el-input>
      <div id="panel" />
    </div>
  </div>
</template>

<style scoped>
#map-box {
  width: 100%;
  height: 450px;
  position: relative;
}
#container {
  width: 100%;
  height: 100%;
}

#myPageTop {
  position: absolute;
  top: 5px;
  right: 10px;
  font-family: "Microsoft Yahei", Pinghei;
  font-size: 14px;
  background: none 0px 0px repeat scroll rgb(255, 255, 255);
  border-width: 1px;
  border-style: solid;
  border-color: rgb(204, 204, 204);
  border-image: initial;
  margin: 10px auto;
  padding: 6px;
}
#panel {
  background-color: white;
  max-height: 400px;
  overflow-y: auto;
}
</style>

5 实现效果

回显效果,会自动设置到地图中心
在这里插入图片描述
选点效果
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值