⚡️ 由于高德api省界描边样式与ui差别很大,所以尝试自定义省界线样式
⚡️ vue2、vue3实现方式一致,本篇记录vue3实现方式

效果图(河北省为例)

Android 高德地图省份边界_Android 高德地图省份边界

vue3设置了高德地图安全密钥
简述主要实现方式
  • 新建图片图层覆盖到所要展示的省份之上,高德图层 apiAMap.ImageLayer,图层图片由ui提供
  • AMap.Bounds([poitn1,poitn2],[poitn3,poitn4])四个点位置控制图层宽高与其地图实际大小重叠
高德地图获取key、密钥不再叙述
完整代码(vue3+vite)

mapConfig.js

// 高德Key Web端(JS API)
 export const MapKey='你申请的key'
// 高德安全密钥 Web端(JS API)
 export const MapSecretKey='你的密钥'

组件代码

<!-- 省界自定义样式 -->
<template>
  <div class="box">
    <!-- 高德地图容器 -->
    <div id="container"></div>
  </div>
</template>

<script setup>

import { MapKey, MapSecretKey } from "../config/mapConfig";

//设置安全密钥
window._AMapSecurityConfig = {
  securityJsCode: `${MapSecretKey}`,
};

//高德API加载器 安装命令: npm i @amap/amap-jsapi-loader
import AMapLoader from "@amap/amap-jsapi-loader";

import { onBeforeMount, onMounted, ref } from "vue";

onBeforeMount(() => {
  initMap
    .then((ok) => {
      //加载行政区查询插件
      initDistrictSearch();
      //绘制默认地区边界
      // searchAndBounds("河北省");
    })
    .catch((err) => {
      console.log(err);
    });
});

// 地图容器
var map;

//行政区查询容器
var district;
//行政区边界数据暂存
var polygons = [];

// 初始化地图函数
const initMap = new Promise((resolve, reject) => {
  AMapLoader.load({
    key: `${MapKey}`, // 申请好的Web端开发者Key,首次调用 load 时必填
    version: "1.4.15", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15。 2.0地图加载慢,地图上下留有网格空白,本人小白找不到原因
    plugins: [],
  })
    .then((AMap) => {
      map = new AMap.Map("container", {
        viewMode: "3D", //是否为3D地图模式
        zoom: 7, //初始化地图级别
        center: [116.418261, 39.921984], //初始化地图中心点位置
        mapStyle: "amap://styles/1ab4919ee8d46968b49d9127e873d767",
      });

      map.setFeatures(["road", "bg"]);

      //获取Bounds四个点位置
      let southwest = getLnglatByDistAndAngle(
        652,
        [116.468664, 39.537057],
        227
      );
      let northeast = getLnglatByDistAndAngle(652, [116.468664, 39.537057], 43);
		
		//四个点控制图层位置与省界重合
      let bounds = new AMap.Bounds(
        [southwest[0], southwest[1]],
        [northeast[0], northeast[1]]
      );
		
		//设置区域控制,移出区域后自动返回到范围区域
      map.setLimitBounds(new AMap.Bounds(southwest, northeast));

      var imageLayer = new AMap.ImageLayer({
        //vue2版本使用require url: require("./bbg.png"),
        url: new URL("./bbg.jpg", import.meta.url).href,//vue3+vite使用这种方式获取图片
        bounds: bounds ,//图片图层
        zooms: [2, 20],
        // opacity: 0.5,
      });
      map.add(imageLayer);
		
		//打点的数据
      let cityData = [
        {
          title: "唐山市",
          position: [117.611242, 39.778112],
        },
        {
          title: "张家口市",
          position: [114.885895, 40.768931],
        },
        {
          title: "承德市",
          position: [116.798254, 41.198462],
        },

        {
          title: "秦皇岛市",
          position: [118.830725, 40.039356],
        },
        {
          title: "保定市",
          position: [114.480139, 39.039631],
        },
        {
          title: "廊坊市",
          position: [116.064916, 39.303664],
        },

        {
          title: "衡水市",
          position: [115.668987, 37.739367],
        },
        {
          title: "沧州市",
          position: [116.838715, 38.304676],
        },
        {
          title: "石家庄市",
          position: [114.514976, 38.042007],
        },
        {
          title: "邯郸市",
          position: [114.53915, 36.6258497],
        },
        {
          title: "邢台市",
          position: [114.765783, 37.548025],
        },
      ];
	
	//调用封装的打点方法
      createPoints(cityData, true);

      //操作成功
      resolve();
    })
    .catch((e) => {
      //操作失败
      reject(e);
    });
});



//传入需要打点的数组-arr,type判断是否带title
function createPoints(arr, type) {
  let cityArr = [];
  if (type) {
    arr.map((city) => {
      let markerObj = city;
      var markerContent =
        '<div class="custom-content-marker">' + city.title + "</div>";
      markerObj.content = markerContent;

      var mark = new AMap.Marker(markerObj);
      cityArr.push(mark);
    });
  } else {
    arr.map((city) => {
      let markerObj = city;
      var markerContent = '<div class="custom-content-marker">' + "</div>";
      markerObj.content = markerContent;

      let mark = new AMap.Marker(markerObj);
      cityArr.push(mark);
    });
  }

  map.add(cityArr);
}
//计算点的位置
function getLnglatByDistAndAngle(dist, lnglat, angle) {
  let dealDist = dist / Math.sin((45 * Math.PI) / 180);
  const currlng = lnglat[0];
  const currlat = lnglat[1];
  const lng =
    currlng +
    (dealDist * Math.sin((angle * Math.PI) / 180)) /
      (111 * Math.cos((currlat * Math.PI) / 180));
  const lat =
    currlat +
    (dealDist * Math.sin((angle * Math.PI) / 180)) /
      (130 * Math.cos((currlat * Math.PI) / 180));
  return [lng, lat];
}

//行政区查询插件加载
function initDistrictSearch() {
  AMap.plugin(["AMap.DistrictSearch"], function () {
    //加载行政区划插件
    if (!district) {
      //实例化DistrictSearch
      let opts = {
        subdistrict: 0, //获取边界不需要返回下级行政区
        extensions: "all", //返回行政区边界坐标组等具体信息
        level: "district", //查询行政级别为 区
      };
      district = new AMap.DistrictSearch(opts);
    }
  });
}

//边界查询并绘制
function searchAndBounds(dis) {
  district.search(dis, function (status, result) {
    // 获取边界信息
    let bounds = result.districtList[0].boundaries;
    map.remove(polygons); //清除上次结果
    polygons = [];
    if (bounds) {
      for (let i = 0, l = bounds.length; i < l; i++) {
        //生成行政区划polygon
        let polygon = new AMap.Polygon({
          map: map,
          strokeWeight: 1,
          path: bounds[i],
          fillOpacity: 0,
          fillColor: "red",
          strokeColor: "#031d44",
        });
        polygons.push(polygon);
      }
      // 地图自适应
      map.setFitView();
    }
  });
}
</script>

<style scoped>
.box {
  width: 60%;
  margin-left: 20%;
  height: 100%;
}

#container {
  width: 100%;
  height: 100%;
}
:deep(.custom-content-marker) {
  word-break: keep-all;
  color: #2ddcce;
  font-size: 16px;
  position: relative;
  padding-left: 25px;
  font-weight: 900;
}
:deep(.custom-content-marker::before) {
  content: ".";
  width: 6px;
  height: 6px;
  position: absolute;
  text-indent: -9999px;
  background: #fff;
  display: block;
  top: 3px;
  left: 0;
  border-radius: 10px;
  border: 6px solid #00deff;
  -webkit-box-shadow: 0px 0px 12px #fff;
  box-shadow: 0px 0px 12px #fff;
}
#controller {
  position: absolute;
  z-index: 99;
  top: 20px;
  left: 100px;
  background: white;
  list-style-type: none;
  width: 120px;
}
</style>
案例中UI图片,背景图省界线图分开效果更好

分开实现方式:

  • 容器区域单独设置背景图片
  • 高德地图个人中心自定义高德地图样式,使其陆地背景样式不透明度为0
  • 代码定义只显示一个省份,将省界线图与展示身份重叠

这样拖动地图不会超出背景图范围