vue项目中使用vue-amap和高德地图原生Api

邢修明
2023-12-01

1.在官网进行注册 https://lbs.amap.com/
2.在main.js中引入配置,按需引入插件

import VueAMap from 'vue-amap';
Vue.use(VueAMap)
VueAMap.initAMapApiLoader({
  // 高德的key
  key: 'af3036364576bf0fb5572996ef9f4850',
  // 插件集合
  plugin:[
    'AMap.Autocomplete',
    'AMap.PlaceSearch'
  ],
  // 高德 sdk 版本,默认为 1.4.4
  v: '1.4.4',
  uiVersion: '1.0.11' // 版本号
});

3.安装 :npm install vue-amap --save
使用示例代码中的接口文件没放上去

// workbench.vue
<template>
  <div class="amap-page-container">
    <el-amap
      :vid="'amap-vue'"
      :zoom="zoom"
      :events="mapEvents"
      :center="[center.lng, center.lat]"
    >
      <div class="button-style">
        <el-button type="success">月安装数:{{ monthInstall }}</el-button>
        <el-button type="success">年安装数:{{ yearInstall }}</el-button>
        <el-button type="danger">月拆装数:{{ monthUninstall }}</el-button>
        <el-button type="danger">年拆装数:{{ yearUninstall }}</el-button>
      </div>
      <el-amap-marker
        v-for="marker in markers"
        :position="marker.position"
        :key="marker.id"
        :events="marker.events"
        :icon="marker.icon"
      >
      </el-amap-marker>
    </el-amap>
    <infoWindowComponent ref="infoWindowComponent"></infoWindowComponent>
    <detailInfo ref="detailInfo"></detailInfo>
  </div>
</template>
 
<script>
const workbenchApi = require("../api/workbench");
import infoWindowComponent from "../components/infoWindow.vue";
import detailInfo from "../components/detailInfo.vue";
export default {
  components: {
    infoWindowComponent,
    detailInfo,
  },
  data() {
    let self = this;
    return {
      showInfoWindow: false,
      infoMsg: {},
      search: "",
      zoom: 6,
      mapEvents: {
        init(map) {
          self.map = map;
          self.setMap();
        },
      },
      map: "",
      center: {
        lng: 107.989207,
        lat: 34.996855,
      },
      markers: [],
      windows: [],
      window: "",
      dataSource: [],
      monthInstall: "", //月安装数
      monthUninstall: "", //月拆装数
      yearInstall: "", //年安装数
      yearUninstall: "", //年拆装数
    };
  },
  activated() {
    this.loadData();
  },
  methods: {
    loadData() {
      workbenchApi.detail().then((data) => {
        this.dataSource = data.craneInfos;
        this.monthInstall = data.monthInstall;
        this.monthUninstall = data.monthUninstall;
        this.yearInstall = data.yearInstall;
        this.yearUninstall = data.yearUninstall;
        this.setMarkers();
      });
    },
    setMarkers() {
      let markers = [];
      let that = this;
      this.dataSource.forEach((item, index) => {
        //未进场: 使用中:绿色 维修中: 已拆除:灰色 拆装报停: 临时报停:
        //图标
        item.icon = new AMap.Icon({
          size: new AMap.Size(40, 40),
          image: getImage(),
          imageSize: new AMap.Size(40, 40),
          anchor: "center",
        });
        function getImage() {
          if (item.status=="未进场") {
            return require("../icons/blue.png")
          }
          else if (item.status=="使用中") {
            return require("../icons/green.png")
          }
          else if (item.status=="维修中") {
            return require("../icons/red.png")
          }
          else if (item.status=="已拆除") {
            return require("../icons/grey.png")
          }
          else if (item.status=="拆装报停") {
            return require("../icons/yellow.png")
          }
          else if (item.status=="临时报停") {
            return require("../icons/yellow.png")
          }
          else{
            return require("../icons/abnormal.png")
          }
        }
        markers.push({
          position: [item.longitude, item.latitude],
          icon: item.icon,
          events: {
            click() {
              that.$nextTick(() => {
                that.setInfoWindows(item);
                that.center = {
                  lat: item.latitude,
                  lng: item.longitude,
                };
              });
            },
            mouseover(){
              that.$nextTick(() => {
                 that.getDetailWindow(item);
              });
            },
            mouseout(){
              that.$nextTick(() => {
                 that.$refs.detailInfo.close();
              });
            },
          },
        });
      });
      //加窗体
      this.markers = markers;
    },
    setMap() {
      //行政区域划分
      let self = this;
      AMapUI.load(
        ["ui/geo/DistrictCluster", "lib/$"],
        function (DistrictCluster, $) {
          //启动页面
          initPage(DistrictCluster, $);
        }
      );
      function initPage(DistrictCluster, $) {
        var distCluster = new DistrictCluster({
          map: self.map, //所属的地图实例
          zIndex: 11,
          getPosition: function (item) {
            if (!item) {
              return null;
            }
            //返回经纬度
            return item.position;
          },
          renderOptions: {
            //基础样式
            featureStyle: {
              fillStyle: "rgba(102,170,0,0.5)", //填充色
              lineWidth: 2, //描边线宽
              strokeStyle: "rgb(31, 119, 180)", //描边色
              //鼠标Hover后的样式
              hoverOptions: {
                fillStyle: "rgba(255,255,255,0.2)",
              },
            },
            //特定区划级别的默认样式
            featureStyleByLevel: {
              //全国
              country: {
                fillStyle: "rgba(49, 163, 84, 0.8)",
              },
              //省
              province: {
                fillStyle: "rgba(116, 196, 118, 0.7)",
              },
              //市
              city: {
                fillStyle: "rgba(161, 217, 155, 0.6)",
              },
              //区县
              district: {
                fillStyle: "rgba(199, 233, 192, 0.5)",
              },
            },
            //直接定义某写区划面的样式
            getFeatureStyle: function (feature, dataItems) {
              if (dataItems.length > 10) {
                return {
                  fillStyle: "rgba(116, 196, 118, 0.7)",
                };
              } else if (dataItems.length > 0) {
                return {
                  fillStyle: "rgba(161, 217, 155, 0.6)",
                };
              } else if (dataItems.length == 0) {
                return {
                  fillStyle: "rgba(0,0,0,0.0)",
                };
              }
              return {};
            },
          },
        });
        distCluster.setData(self.markers);
      }
    },
    getDetailWindow(e){
      let self = this;
      self.showInfoWindow = true;
      self.infoMsg = e;
      var infoWindow = new AMap.InfoWindow({
        isCustom: true, //使用自定义窗体
        content: self.$refs.detailInfo.$el,
        offset: new AMap.Pixel(16, -50),
      });
      infoWindow.open(self.map, [e.longitude, e.latitude]);
      self.$refs.detailInfo.initialize({
        infoWindow: infoWindow,
        infoMsg: e,
      });
    },
    setInfoWindows(e) {
      let self = this;
      self.showInfoWindow = true;
      self.infoMsg = e;
      var infoWindow = new AMap.InfoWindow({
        isCustom: true, //使用自定义窗体
        content: self.$refs.infoWindowComponent.$el,
        offset: new AMap.Pixel(16, -50),
      });
      infoWindow.open(self.map, [e.longitude, e.latitude]);
      self.$refs.infoWindowComponent.initialize({
        infoWindow: infoWindow,
        infoMsg: e,
      });
    },
  },
};
</script>
 
<style lang="scss" scoped="">
.amap-page-container {
  width: 100%;
  height: 100%;
}
.button-style {
  position: absolute;
  top: 65px;
  left: 20px;
}
.search-input {
  position: absolute;
  top: 65px;
}
/deep/.amap-logo {
  display: none;
  opacity: 0;
}
/deep/.amap-copyright {
  opacity: 0;
}
</style>

// 信息弹窗文件infoWindow.vue
<template>
  <div>
    <el-card
      class="box-card"
      style="width: 200px; border-radius: 10px"
    >
      <div class="del-div">
        <el-link type="primary" icon="el-icon-close" @click="close()"></el-link>
      </div>
      <div v-if="!showDetail">
        <div class="button-style">
          <el-button size="small" type="primary" @click="showDetail = true"
            >信息明细</el-button
          >
        </div>
        <div class="button-style">
          <el-button size="small" type="primary"
            ><router-link
              :to="{
                name: 'MaintenanceIndex',
                params: {
                  search: infoMsg.sn,
                },
              }"
              >维保记录</router-link
            ></el-button
          >
        </div>
        <div class="button-style">
          <el-button size="small" type="primary"><router-link
              :to="{
                name: 'RepairReport',
                params: {
                  search: infoMsg.sn,
                },
              }"
              >维修记录</router-link
            ></el-button>
        </div>
        <!-- <div class="button-style">
          <el-button size="small" type="primary">预警信息</el-button>
        </div>
        <div class="button-style">
          <el-button size="small" type="primary">视频监控</el-button>
        </div> -->
      </div>
      <div v-else>
        <div class="text item">
          <span>项目名称:{{ infoMsg.name }}</span>
        </div>
        <div class="text item">
          <span>项目负责人:{{ infoMsg.principalName }}</span>
        </div>
        <div class="text item">
          <span>机长:{{ captainName }}</span>
        </div>
        <div class="text item">
          <span>塔机型号:{{ infoMsg.model }}</span>
        </div>
        <div class="text item">
          <span>塔机编号:{{ infoMsg.sn }}</span>
        </div>
        <div class="text item">
          <span>动力源:{{ infoMsg.powerSource }}</span>
        </div>
        <div class="text item">
          <span>使用方式:{{ infoMsg.type }}</span>
        </div>
        <div class="text item">
          <span>状态:{{ infoMsg.status }}</span>
        </div>
      </div>
    </el-card>
  </div>
</template>
<script>
export default {
  data() {
    return {
      infoWindow: "",
      infoMsg: "",
      showDetail: false,
      captainName:"",
    };
  },
  methods: {
    initialize(e) {
      console.log(e);
      this.infoWindow = e.infoWindow;
      this.infoMsg = e.infoMsg;
      const members = this.infoMsg.workers
      if (members.length>0) {
        let captain = members.find(obj => obj.type==0)
        this.captainName = captain.username
      }
    },
    close() {
      // 高德地图信息窗关闭的api
      this.infoWindow.close();
      this.showDetail = false;
    },
  },
};
</script>
 
<style lang="css" scoped>
.del-div {
  position: absolute;
  transform: scale(1.2);
  margin-left: 153px;
  margin-top: -15px;
}
.button-style {
  text-align: center;
  margin-bottom: 5px;
  margin-top: 5px;
}
.text {
  font-size: 14px;
}
.item {
  margin-bottom: 5px;
  margin-top: 5px;
}
</style>

vue-amap结合amap原生Api示例

// 查看定位和修改定位功能
// 父组件调用该文件的openPosition,并传入三个参数:
// 1.obj:定位的坐标和其他参数。2.bol:标识判断是编辑还是修改。3.title:弹窗标题
// 代码中数据参数由父组件调用该文件的openPosition。
<template>
  <div>
    <el-dialog
      :title="title"
      :visible.sync="mapDialog"
      width="1000px"
      v-dialogDrag
    >
      <div class="amap-page-container">
        <div v-if="isCheck">
          <el-amap-search-box
            class="search-box"
            :search-option="searchOption"
            :on-search-result="onSearchResult"
          ></el-amap-search-box>
        </div>
        <el-amap
          :vid="'amap-vue'"
          :zoom="zoom"
          :center="[marker.lng, marker.lat]"
          :events="events"
        >
          <el-amap-marker
            :position="[marker.lng, marker.lat]"
          ></el-amap-marker>
        </el-amap>
      </div>
      <div v-if="isCheck">
        <el-form ref="editForm" :model="editForm" label-width="100px">
          <el-form-item
            label="塔机地址"
            prop="address"
            :rules="[
              {
                required: true,
                message: '请输入塔机地址',
                trigger: 'bulr',
              },
            ]"
          >
            <el-input type="text" v-model="editForm.address"></el-input>
          </el-form-item>
        </el-form>
        <div slot="footer" class="dialog-footer">
          <el-button @click="mapDialog = false">取消</el-button>
          <el-button type="primary" @click="confirmPosition('editForm')"
            >确定</el-button
          >
        </div>
      </div>
    </el-dialog>
  </div>
</template>
 
<script>
const craneApi = require("../api/craneManage");
export default {
  data() {
    let self = this
    return {
      mapDialog: false,
      marker: {
        lng: "",
        lat: "",
      },
      zoom: 15,
      searchOption: {
        citylimit: false,
      },
      events: {
        click: (e) => {
          if (self.isCheck) {
            self.marker.lng = e.lnglat.lng;
            self.marker.lat = e.lnglat.lat;
            let lnglat = [self.marker.lng,self.marker.lat]
            self.getaddress(lnglat)
          }
        },
      },
      editForm: {
        id: "",
        longitude: "",
        latitude: "",
        address: "",
      },
      isCheck: true,
      title: "",
      formattedAddress:"",
    };
  },
  methods: {
  //逆地理编码,在地图中点击点图获取该点的详细结构化的地址。
  //例如:116.480881,39.989410 转换地址描述后:北京市朝阳区阜通东大街6号
    getaddress: function (lnglat) {
      let self = this;
      AMap.plugin("AMap.Geocoder", function () {
        var geocoder = new AMap.Geocoder({
          // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
          city: "010",
        });
        geocoder.getAddress(lnglat, function (status, result) {
          if (status === "complete" && result.info === "OK") {
            self.editForm.address = result.regeocode.formattedAddress;
            // result为对应的地理位置详细信息
          }
        });
      });
    },
    openPosition(obj, bol, title) {
      this.isCheck = bol;
      this.title = title;
      if (obj.latitude != "" && obj.longitude != "") {
        this.marker.lat = obj.latitude;
        this.marker.lng = obj.longitude;
      } else {
        this.marker.lat = 39.909104;
        this.marker.lng = 116.397453;
      }
      this.mapDialog = true;
    },
    editPosition(obj, bol, title) {
      this.isCheck = bol;
      this.title = title;
      if (obj.latitude != "" && obj.longitude != "") {
        this.marker.lat = obj.latitude;
        this.marker.lng = obj.longitude;
      } else {
        this.marker.lat = 39.909104;
        this.marker.lng = 116.397453;
      }
      this.mapDialog = true;
      this.editForm.id = obj.eid;
      this.editForm.address = ""
    },
    onSearchResult(pois) {
      this.marker.lng = pois[0].lng;
      this.marker.lat = pois[0].lat;
    },
    confirmPosition(editForm) {
      this.editForm.longitude = this.marker.lng;
      this.editForm.latitude = this.marker.lat;
      this.$refs[editForm].validate((v) => {
        if (v) {
          craneApi
            .position(this.editForm)
            .then(() => {
              this.$refs[editForm].resetFields();
              this.mapDialog = false;
              this.$parent.loadData();
              this.$message({
                showClose: true,
                message: "编辑成功",
                type: "success",
              });
            })
            .catch(() => {});
        }
      });
    },
  },
};
</script>
 
<style lang="scss" scoped="">
// .el-form-item {
//   margin-bottom: -20px;
//   margin-top: 20px;
// }
.amap-page-container {
  width: 100%;
  height: 600px;
}
.search-box {
  position: absolute;
  top: 65px;
  left: 20px;
}
/deep/.amap-logo {
  display: none;
  opacity: 0;
}
/deep/.amap-copyright {
  opacity: 0;
}
</style>

 类似资料: