2025-06-24 vue2 引入高德地图实现搜索显示位置标记

2025-06-24  本文已影响0人  木木呀暮暮

1.申请高德地图key

1.1登录 高德开放平台,注册成为开发者并登录
1.2 创建新应用
进入【应用管理】,点击页面右上角【创建新应用】,填写表单即可创建新的应用。

image.png
1.3 创建 Key
进入【应用管理】,在我的应用中选择需要创建 Key 的应用,点击【添加 Key】,表单中的服务平台选择【Web 端】。
image.png

2.引入到vue2项目中

2.1. 安装amap

cnpm i @amap/amap-jsapi-loader --save

2.2 在components组件中创建MapCon.vue 文件

<template>
  <div id="container"></div>
</template>

<script>
import AMapLoader from '@amap/amap-jsapi-loader'
    window._AMapSecurityConfig = {
        securityJsCode: '你的秘钥'
    }
export default {
  data() {
    return {
      map: null
    }
  },
  methods: {
    initMap() {
      AMapLoader.load({
        key: '你的key', // 申请好的Web端开发者Key,首次调用 load 时必填
        version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
        plugins: [''] // 需要使用的的插件列表,如比例尺'AMap.Scale'等
      })
        .then(AMap => {
          this.map = new AMap.Map('container', {
              zoom: 6
          })
          
        })
        .catch(e => {
          console.log(e)
        })
    }
  },
  mounted() {
    //DOM初始化完成进行地图初始化
    // this.initMap()
  }
}
</script>

<style lang="less">
#container {
  padding: 0px;
  margin: 0px;
  width: 100%;
  height: 100%;
  min-height: 500px;
  border:1px solid #ccc;
}
</style>

2.3 在需要的页面引入

<template>
  <div>
    <map-container></map-container>
  </div>
</template>

<script>
import MapCon from "@/components/MapCon";
export default {
  components: {MapContainer},
}
</script>

效果如下:


image.png

3. 搜索定位,标记等

3.1 components中修改MapCon.vue 文件

<template>
  <el-row :gutter="15" class="container">
    <!-- 地图 -->
    <div class="mapbox">
      <div class="search_box">
        <div class="label">地址搜索</div>
        <el-input v-model="input" placeholder="请输入内容" id="tipinput"></el-input>
      </div>
      <div ref="gaode_Map" id="gaode_Map"></div>
    </div>
  </el-row>
</template>

<script>
import AMapLoader from "@amap/amap-jsapi-loader";

window._AMapSecurityConfig = {
  securityJsCode: "你的秘钥",
};

export default {
  props: {
    initData: [],
  },
  data() {
    return {
      district: null,
      polygons: [],
      form: {},
      loading: false,
      visible: true,
      isDetail: false,
      dataForm: {
        kqName: undefined,
        kqLocation: undefined,
        kqLongitude: undefined,
        kqLatitude: undefined,
        kqWorkUnit: undefined,
        cronkqAccredit: [],
        kqValidCardRange: undefined,
      },
      rules: {},
      input: "",
      map: null,
      auto: null,
      placeSearch: null,
      lnglat: [],
      markers: [],
      position: {
        longitude: null,
        latitude: null,
        address: "",
      },
      circleMarker1: null,
      marker: null,
      geocoder: null, // 复用 Geocoder 实例
      province: "",
      city: "",
    };
  },

  mounted() {
    AMapLoader.reset();
    this.initMap();
  },

  beforeUnmount() {
    if (this.map) {
      this.map.off("click", this.clickMapHandler);
      this.map.destroy();
      this.map = null; // 清空引用
    }
  },

  methods: {
    dataFormSubmit() {
      this.setCircle(this.lnglat, this.dataForm.kqValidCardRange);
    },

    setCircle(lnglat, radius = 500, fillColor = "#ff00ff") {
      if (this.marker) {
        this.map.remove(this.marker);
      }
      if (this.circleMarker1) {
        this.map.remove(this.circleMarker1);
      }

      this.marker = new AMap.Marker({ position: lnglat });
      this.marker.setMap(this.map);

      this.circleMarker1 = new AMap.CircleMarker({
        map: this.map,
        center: lnglat,
        radius,
        fillColor,
      });

      this.circleMarker1.setMap(this.map);
    },

    searchMap() {
      this.auto = new AMap.AutoComplete({ input: "tipinput" });
      this.placeSearch = new AMap.PlaceSearch({ map: this.map });
      this.auto.on("select", this.selectSite);
    },

    // 选择地址
    selectSite(e) {
      console.log(e);
      if (e.poi.location) {
        const lnglat = [e.poi.location.lng, e.poi.location.lat];
        console.log('选择地址', lnglat);
        this.lnglat = lnglat;
        this.setCircle(lnglat);
        this.placeSearch.setCity(e.poi.adcode);
        this.placeSearch.search(e.poi.name);


        this.geocoder.getAddress(lnglat, (status, result) => {
          if (status === "complete" && result.regeocode) {
            const addrComp = result.regeocode.addressComponent;
            this.form = {
              province: addrComp.province,
              city: addrComp.city,
              address: e.poi.name,
              coordinate: `${e.poi.location.lng},${e.poi.location.lat}`,
            };
            console.log(this.form);

            this.dataForm.kqLongitude = e.poi.location.lat;
            this.dataForm.kqLatitude = e.poi.location.lng;
            this.dataForm.kqLocation = e.poi.name
            this.$emit("updateLocation", this.dataForm);

          } else {
            console.log("查询地址失败");
          }
        });
      } else {
        this.placeSearch.setCity(e.poi.adcode)
        this.placeSearch.search(e.poi.name) //关键字查询查询
        // this.drawBounds(e.poi.name)
        this.map.setZoom(16, true, 1)
      }
    },
    feedBack(msg, feedBackType) {
      this.$message({
        showClose: true,
        message: msg,
        type: feedBackType
      })
    },
    // 行政区区域划分
    drawBounds(newValue) {
    
      //加载行政区划插件
      if (!this.district) {
        //实例化DistrictSearch
        var opts = {
          subdistrict: 1, //获取边界不需要返回下级行政区
          extensions: 'all', //返回行政区边界坐标组等具体信息
          level: 'district' //查询行政级别为 市
        }

        this.map.plugin(['AMap.DistrictSearch'], () => {
          this.district = new AMap.DistrictSearch(opts)
        })
        // this.district = new AMap.DistrictSearch(opts)
      }
      //行政区查询
      this.district.search(newValue, (status, result) => {
        console.log(result)
        if (result != null) {
          this.feedBack('区域搜索成功', 'success')
          if (this.polygons != null) {
            this.map.remove(this.polygons) //清除上次结果
            this.polygons = []
          }
          var bounds = result.districtList[0].boundaries
          if (bounds) {
            for (var i = 0, l = bounds.length; i < l; i++) {
              //生成行政区划polygon
              var polygon = new AMap.Polygon({
                strokeWeight: 1,
                path: bounds[i],
                fillOpacity: 0.4,
                fillColor: '#80d8ff',
                strokeColor: '#0091ea'
              })
              this.polygons.push(polygon)
            }
          }
          this.map.add(this.polygons)
          this.map.setFitView(this.polygons) //视口自适应
        } else {
          this.feedBack('区域搜索失败', 'error')
        }
      })
    },
    clickMapHandler(e) {
            console.log(e);
      const lng = e.lnglat.getLng();
      const lat = e.lnglat.getLat();
      this.dataForm.kqLongitude = lat;
      this.dataForm.kqLatitude = lng;
      this.lnglat = [lng, lat];
      this.setCircle(this.lnglat);

      this.geocoder.getAddress(this.lnglat, (status, result) => {
        if (status === "complete" && result.regeocode) {
          const regeo = result.regeocode;
          this.dataForm.kqLocation = regeo.formattedAddress;
          this.dataForm.localName = regeo.addressComponent.neighborhood || "";
          this.input = regeo.formattedAddress;

          this.position = {
            longitude: lng,
            latitude: lat,
            address: regeo.formattedAddress,
          };

          this.$emit("updateLocation", this.dataForm);
        } else {
          console.log("查询地址失败");
        }
      });
    },

    initMap() {
      AMapLoader.load({
        key: "你的key",
        version: "2.0",
        plugins: ['AMap.Scale', 'AMap.ToolBar',"AMap.AutoComplete", 'AMap.ControlBar', "AMap.PlaceSearch", "AMap.Geocoder"],
      })
        .then((AMap) => {
          this.map = new AMap.Map("gaode_Map", {
            viewMode: "3D",
            zoom: 18,
            center: this.initData,
            resizeEnable: true,
          });

          this.geocoder = new AMap.Geocoder({
            // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
            city: '全国'
          });
          this.map.addControl(new AMap.Scale()); //比例尺
          this.map.addControl(new AMap.ToolBar()); //缩放工具条
          this.map .addControl(new AMap.ControlBar()); //控制罗盘
          this.setCircle(this.initData);
          this.searchMap();
          this.map.on("click", this.clickMapHandler);
        })
        .catch(() => {
          this.$message.error("地图加载失败");
        });
    },
  },
};
</script>

<style lang="less">
.container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;

  .mapbox {
    width: 100%;
  }
}

.search_box {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  height: 50px;
  margin-bottom: 20px;

  .label {
    color: #000;
    width: 100px;
  }
}

#gaode_Map {
  overflow: hidden;
  width: 100%;
  height: 350px;
  margin: 0;
  margin-bottom: 50px;
}

.amap-sug-result {
  z-index: 2999 !important;
}
</style>

3.2 修改引用的文件

<template>
  <div>
    <el-button type="primary" plain icon="el-icon-plus" @click="handleAdd">新增打卡位置</el-button>
    <el-table v-loading="loading" :data="recordsList" border @selection-change="handleSelectionChange">
      <!-- <el-table-column type="selection" width="55" align="center" /> -->
      <el-table-column label="序号" type="index" align="center" width="100" />
      <el-table-column label="打卡地点" align="center" prop="clockInLocation" />
      <el-table-column label="打卡详细地址" align="center" prop="clockInAddress" />
      <el-table-column label="有效范围/米" align="center" prop="range" />
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)">修改</el-button>
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <!-- 添加或修改打卡位置记录对话框 -->
    <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
      <Map ref="map" v-if="open" :initData="maprops" @updateLocation="updateLocation"></Map>

      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="打卡地点" prop="clockInLocation">
          <el-input v-model="form.clockInLocation" placeholder="请输入打卡地点名称" />
        </el-form-item>
        <el-form-item label="详细地址" prop="clockInAddress">
          <el-input v-model="form.clockInAddress" placeholder="自动带出" disabled />
        </el-form-item>
        <el-form-item label="经度坐标" prop="longitude">
          <el-input v-model="form.longitude" placeholder="自动带出" disabled />
        </el-form-item>
        <el-form-item label="纬度坐标" prop="latitude">
          <el-input v-model="form.latitude" placeholder="自动带出" disabled />
        </el-form-item>
        <el-form-item label="有效范围" prop="range">
          <el-select v-model="form.range" placeholder="请选择有效范围">
            <el-option label="300米" value="300"></el-option>
            <el-option label="500米" value="500"></el-option>
            <el-option label="1000米" value="1000"></el-option>
          </el-select>
        </el-form-item>
      </el-form>

      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">确 定</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
// import { 打卡列表, 某条打卡位置详情, 删除打卡数据, 新增打卡, 修改打卡 } from "@/api/modules/打卡api文件";
import Map from "@/components/MapCon";
export default {
  components: { Map },
  data() {
    return {
      loading: true,
      ids: [],
      single: true,
      multiple: true,
      total: 0,
      recordsList: [],
      title: "",
      open: false,
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        mapType: null,
        longitude: null,
        latitude: null,
        range: null,
        clockInLocation: null,
        clockInAddress: null,
        updateTime: null
      },
      form: this.getInitialForm(),
      rules: {
        longitude: [
          { required: true, message: "经度坐标不能为空", trigger: "blur" }
        ],
        latitude: [
          { required: true, message: "纬度坐标不能为空", trigger: "blur" }
        ],
        range: [
          { required: true, message: "定位范围不能为空", trigger: "blur" }
        ],
        clockInLocation: [
          { required: true, message: "打卡地点名称不能为空", trigger: "blur" }
        ],
        clockInAddress: [
          { required: true, message: "打卡详细地址不能为空", trigger: "blur" }
        ]
      },
      map: null,
      maprops: [] // 初始化为空数组
    };
  },
  created() {
    this.getList();
  },
  methods: {
    getInitialForm() {
      return {
        id: 0,
        mapTypeEnum: 2,
        longitude: null,
        latitude: null,
        range: null,
        clockInLocation: null,
        clockInAddress: null
      };
    },

    updateLocation(mapData) {
      this.form = {
        id: this.form.id,
        mapTypeEnum: 2,
        longitude: mapData.kqLongitude,
        latitude: mapData.kqLatitude,
        clockInAddress: mapData.kqLocation
      };
    },

    getList() {
      this.loading = true;
      // 打卡列表().then(response => {
      //   this.recordsList = response.data;
      //   this.total = response.total;
      //   this.loading = false;
      // });
    },

    cancel() {
      this.open = false;
      this.reset();
      if (this.map) {
        this.map.destroy();
        this.map = null;
      }
    },

    reset() {
      this.form = this.getInitialForm();
      this.maprops = []
    },

    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },

    resetQuery() {
      this.resetForm("queryForm");
      this.handleQuery();
    },

    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.id);
      this.single = selection.length !== 1;
      this.multiple = !selection.length;
    },

    handleAdd() {

      this.reset();
      this.open = true;
      this.title = "添加打卡地点";
      this.maprops = [116.397428, 39.90923]
    },

    handleUpdate(row) {
      this.reset();
      const id = row.id;
      某条打卡位置详情({ id }).then(response => {
        this.form = response.data;
        this.open = true;
        this.title = "修改打卡地点";
        // this.maprops = { lat: row.latitude, lng: row.longitude };
        this.maprops = [row.latitude, row.longitude]
      });
    },

    submitForm() {
      this.$refs["form"].validate(valid => {
        if (valid) {
          const request = this.form.id > 0 ? 修改打卡 : 新增打卡;
          console.log('this.form.id=', this.form.id)
          request(this.form).then(() => {
            this.$message.success(`${this.form.id > 0 ? '修改' : '新增'}成功`);
            this.open = false;
            this.getList();
          });
        }
      });
    },

    handleDelete(row) {
      this.$confirm('是否确认删除该数据项?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        删除打卡数据({ id: row.id }).then(() => {
          this.getList();
          this.$message.success('删除成功!');
        });
      }).catch(() => {
        this.$message.info('已取消删除');
      });
    },

    handleExport() {
      this.download('system/records/export', { ...this.queryParams }, `records_${new Date().getTime()}.xlsx`);
    }
  }
};
</script>
效果图: image.png

注意:文章参考[https://blog.csdn.net/ssk777888/article/details/134059902]

<template>
  <el-dialog :title="!dataForm.id ? '新建' : isDetail ? '详情' : '编辑'" :close-on-click-modal="false" :visible.sync="visible"
    class="rv-dialog rv-dialog_center" lock-scroll width="74%">
    <el-row :gutter="15" class="">
      <el-col :span="8">
        <el-form ref="elForm" :model="dataForm" :rules="rules" size="small" label-width="70px" label-position="right"
          :disabled="!!isDetail">
          <el-col :span="24">
            <el-form-item label="名称" prop="kqName">
              <el-input v-model="dataForm.kqName" placeholder="请输入" clearable :style="{ width: '100%' }">
              </el-input>
            </el-form-item>
          </el-col>
 
          <el-col :span="24">
            <el-form-item label="地点" prop="kqLocation">
              <el-input v-model="dataForm.kqLocation" placeholder="自动带出" clearable :style="{ width: '100%' }" disabled>
              </el-input>
            </el-form-item>
          </el-col>
 
          <el-col :span="24">
            <el-form-item label="经度" prop="kqLongitude">
              <el-input v-model="dataForm.kqLongitude" placeholder="自动带出" clearable :style="{ width: '100%' }" disabled>
              </el-input>
            </el-form-item>
          </el-col>
 
          <el-col :span="24">
            <el-form-item label="纬度" prop="kqLatitude">
              <el-input v-model="dataForm.kqLatitude" placeholder="自动带出" clearable :style="{ width: '100%' }" disabled>
              </el-input>
            </el-form-item>
          </el-col>
 
          <el-col :span="24">
            <el-form-item label="单位" prop="kqWorkUnit">
              <el-input v-model="dataForm.kqWorkUnit" placeholder="请输入" clearable :style="{ width: '100%' }">
              </el-input>
            </el-form-item>
          </el-col>
 
          <el-col :span="24">
            <el-form-item label="授权" prop="cronkqAccredit">
              <uDSelect v-model="dataForm.cronkqAccredit" :multiple="true" placeholder="选择范围" title="选择范围" />
            </el-form-item>
          </el-col>
 
          <el-col :span="24">
            <el-form-item label="有效签卡范围(米)" label-width="150px" prop="kqValidCardRange">
              <el-input v-model="dataForm.kqValidCardRange" placeholder="请输入" clearable :style="{ width: '100%' }">
              </el-input>
            </el-form-item>
          </el-col>
        </el-form>
      </el-col>
      <el-col :span="16">
        <div style="width: 100%">
          <div class="search_box">
            <div class="label">关键字搜索</div>
            <el-input v-model="input" placeholder="请输入内容" id="tipinput"></el-input>
          </div>
          <div ref="gaode_Map" id="gaode_Map"></div>
        </div>
      </el-col>
    </el-row>
    <span slot="footer" class="dialog-footer">
      <el-button @click="visible = false">取 消</el-button>
      <el-button type="primary" @click="dataFormSubmit()" v-if="!isDetail">确 定</el-button>
    </span>
  </el-dialog>
</template>
<script>
import AMapLoader from "@amap/amap-jsapi-loader"; //引入AMapLoader
window._AMapSecurityConfig = {
  // 设置安全密钥
  securityJsCode: "申请的安全密钥",
};
export default {
  components: {},
  props: [],
  data () {
    return {
      loading: false,
      visible: false,
      isDetail: false,
      dataForm: {
        kqName: undefined,
        kqLocation: undefined,
        kqLongitude: undefined,
        kqLatitude: undefined,
        kqWorkUnit: undefined,
        cronkqAccredit: [],
        kqValidCardRange: undefined,
      },
      rules: {},
      input: "",
      map: null,
      auto: null,
      placeSearch: null,
      lnglat: [],
      markers: [],
      position: {},
    };
  },
  computed: {},
  watch: {},
  created () { },
  mounted() {
    AMapLoader.reset();
    this.initMap();
  },
  methods: {
    // 地图初始化
    initMap () {
      let centerLen = [116.397428, 39.90923];
      AMapLoader.load({
        key: "申请的key值", // 申请好的Web端开发者Key,首次调用 load 时必填
        version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
        plugins: ["AMap.AutoComplete", "AMap.PlaceSearch", "AMap.Geocoder"],
      })
        .then((AMap) => {
          this.map = new AMap.Map("gaode_Map", {
            // 设置地图容器id
            viewMode: "3D", //  是否为3D地图模式
            zoom: 18, // 初始化地图级别
            center: centerLen, //中心点坐标
            resizeEnable: true,
          });
          this.setMarker(centerLen)
          // 关键字查询
          this.searchMap();
          // 监听鼠标点击事件
          this.map.on("click", this.clickMapHandler);
        })
        .catch((e) => { });
    },
    // 关键字查询
    searchMap () {
      // 搜索框自动完成类
      this.auto = new AMap.AutoComplete({
        input: "tipinput", // 使用联想输入的input的id
      });
      //构造地点查询类
      this.placeSearch = new AMap.PlaceSearch({
        map: this.map,
      });
      // 当选中某条搜索记录时触发
      this.auto.on("select", this.selectSite);
    },
    //选中查询出的记录
    selectSite (e) {
      if (e.poi.location) {
        // this.lnglat = [e.poi.location.lng, e.poi.location.lat];
        this.placeSearch.setCity(e.poi.adcode);
        this.placeSearch.search(e.poi.name); //关键字查询
        let geocoder = new AMap.Geocoder({});
        let that = this;
        geocoder.getAddress(this.lnglat, function (status, result) {
          if (status === "complete" && result.regeocode) {
            that.province = result.regeocode.addressComponent.province;
            that.city = result.regeocode.addressComponent.city;
            //自己想要赋的值,根据自己的做修改
            that.$set(that.form, "province", that.province);
            that.$set(that.form, "city", that.city);
            that.$set(that.form, "address", e.poi.name);
            that.$set(
              that.form,
              "coordinate",
              e.poi.location.lng + "," + e.poi.location.lat
            ); //纬度,经度
          } else {
          }
        });
      } else {
        this.$message.error("查询地址失败,请重新输入地址");
      }
    },
    // 点击地图事件获取经纬度,并添加标记
    clickMapHandler (e) {
      this.dataForm.kqLongitude = e.lnglat.getLng();
      this.dataForm.kqLatitude = e.lnglat.getLat();
      this.lnglat = [e.lnglat.getLng(), e.lnglat.getLat()];
      this.setMarker(this.lnglat);
      // 点击地图上的位置,根据经纬度转换成详细地址
      let geocoder = new AMap.Geocoder({});
      let that = this;
      geocoder.getAddress(this.lnglat, function (status, result) {
        if (status === "complete" && result.regeocode) {
          that.dataForm.kqLocation = result.regeocode.formattedAddress;
        } else {
        }
      });
      this.position = {
        longitude: e.lnglat.getLng(),
        latitude: e.lnglat.getLat(),
        address: that.address,
      };
      this.input = that.address; //把查询到的地址赋值到输入框
    },
    //  添加标记
    setMarker (lnglat) {
      this.removeMarker();
      let marker = new AMap.Marker({
        position: lnglat,
      });
      marker.setMap(this.map);
      this.markers.push(marker);
    },
    // 删除之前后的标记点
    removeMarker () {
      if (this.markers) {
        this.map.remove(this.markers);
      }
    },
  },
};
</script>
 
 
<style lang="scss">
.search_box {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  height: 50px;
 
  .label {
    color: #000;
    width: 100px;
  }
}
 
.content {
  position: relative;
}
 
#panel {
  position: absolute;
  top: 50px;
  right: 20px;
}
 
#gaode_Map {
  overflow: hidden;
  width: 100%;
  height: 540px;
  margin: 0;
}
 
.amap-sug-result {
  z-index: 2999 !important;
}
</style>
image.png
坐标拾取器:https://lbs.amap.com/tools/picker
上一篇 下一篇

猜你喜欢

热点阅读