setFitView的zoom只是整数,导致缩放尺寸不合适的解决方案

一,zoom要是小数,需要3d地图模式

const Map = new AMap.Map(that.idHash, {
          mask: mask, //只显示包裹起来的区域
          resizeEnable: true, //是否监控地图容器尺寸变化
          showIndoorMap: false, //关闭室内地图
          center: [96.01906121185537, 35.874643454131984],
          viewMode: "3D",
          dragEnable: false, //初始状态下不可移动
          pitch: 0,
          zoom: that.zoom - 0.1,
          features: that.depFeatures, //初始色块模式下,不显示标注等信息
          mapStyle: "amap://styles/021981e1781074e215441507a954df4b" //设置地图的显示样式
        });

主要是这两个3d模式打开:

viewMode: "3D",
pitch: 0,

但是呢,使用setFitView,根据覆盖物自动调整地图的大小,以适应容器,还是使用的整数。例如,要正好完美地显示地图在容器中,需要地缩放zoom是6.66时,setFitView只会使用zoom=6进行处理,这就导致,所渲染的地图只有少部分情况下是正常满足要求的缩放级别。大部分情况是偏小的。
如下图所示:
在这里插入图片描述

二,采取的解决方案

现在,我们的主要问题是,setFitView是以整数来处理zoom的,从而导致有的时候,地图偏小。

1,取到容器边界的经度值:

在这里插入图片描述

//获取当前缩放级别下,左侧容器的经纬度(左上角的点在当前地图中的经纬度)
    getLnglat() {
      let pixel = new AMap.Pixel(0, 0);
      let lnglat = this.map.containerToLngLat(pixel);
      return lnglat;
    },

2,通过官网的获取我们要展示地图的最左侧点的经纬度(实际上只要经度即可)

https://lbs.amap.com/demo/jsapi-v2/example/event/map-click-event
在这里插入图片描述
右侧点也先取到,后续用:
在这里插入图片描述
所以,现在,我们知道了我们要显示的地图的最左侧和最右侧的经度:
89.84339和103.123006,
于是,我们要显示的地图跨度:

103.123006-89.84339=13.279616

并且第一步可以取到容器最左侧的经度。

3,计算地图最左侧到容器最左侧的经度差距

这样一来,2中得到的目标地图跨度,加上这里计算的经度差距的2倍,就是容器能够容纳的经度跨度了,如下图所示:

在这里插入图片描述

4,自己给定合适的上图黄绿色的经纬度值

		Map.setFitView();
        that.zoom = Map.getZoom() + 0.5;
        Map.setZoomAndCenter(that.zoom, [
          96.01906121185537,
          35.874643454131984
        ]);
        console.log("当前放大级别", Map.getZoom());
        let leftValue;
        setTimeout(() => {
          leftValue = that.getLnglat();
          console.log("左侧容器的经纬度", leftValue.lng);
          console.log(
            "目标地图距离容器最左侧的经度:",
            89.84339 - leftValue.lng
          ); //青海省地图经度范围89.84339和103.123006
          // that.zoom = Map.getZoom() + 0.66;
          // Map.setZoomAndCenter(that.zoom, [
          //   96.01906121185537,
          //   35.874643454131984
          // ]);
          console.log("当前级别", Map.getZoom());
        }, 0);

在这里插入图片描述
所以,我的目标是无论浏览器大小怎么变,只要这个黄绿色的经度跨度是1.196642左右,就可以满足我的需求。
但是,问题是,目前这个效果,是我手动调试出来的,也就是上面的代码:

		Map.setFitView();
        that.zoom = Map.getZoom() + 0.5;
        Map.setZoomAndCenter(that.zoom, [
          96.01906121185537,
          35.874643454131984
        ]);

先是自适应后,手动加了这个0.5,才达到的效果。因为之前已经说过,这个setFitView是按整数来的,所以加的值必然在0-1之间。那要怎样才能得到比较准确的值呢?
我也不知道哈哈,这个源码没看过,但是给个大概的倒是没问题。
我的尝试方法是,每次Map.setFitView();之后,不再手动添加数值,直接计算出来这个值,然后和1.196642比对,多比对几次,得出比较靠谱的系数。我自己用的是0.148.
于是代码:

		Map.setFitView();//在初始设置zoom后自适应一次(此时可能有地图偏小的情况发生)
        console.log("当前放大级别", Map.getZoom());
        setTimeout(() => {//这里为了获取左侧的经度值需要在第一次自适应之后获取,所以settimeout
          let leftValue = that.getLnglat();
          console.log("左侧容器的经纬度", leftValue.lng);
          console.log(
            "目标地图距离容器最左侧的经度:",
            89.84339 - leftValue.lng
          ); //青海省地图经度范围89.84339和103.123006
          const leftLngRange = ((89.84339 - leftValue.lng) / 1.196642) * 0.148;
          console.log("需要调整的系数:", leftLngRange);
          that.zoom = Map.getZoom() + leftLngRange;
          Map.setZoomAndCenter(that.zoom, [
            96.01906121185537,
            35.874643454131984
          ]);//处理好系数之后,再次变换地图
          console.log("当前级别", Map.getZoom());
        }, 0);

三,实现的效果

在这里插入图片描述

四,完整的vue组件代码

要实现自适应的,看上面的代码即可,下面这个代码,有很多是其他功能的,填充色块,描边,行政区高亮,点聚合等等一大堆。

<template>
  <div
    :id="idHash"
    class="container"
    style="z-index:1"
  />
</template>
<script>
import pin1 from "../assets/images/pin1.png";
import pin2 from "../assets/images/pin2.png";
import pin3 from "../assets/images/pin3.png";
import pin4 from "../assets/images/pin4.png";
import pin5 from "../assets/images/pin5.png";
import axios from "axios";
export default {
  name: "MapChart",
  props: {
    year: { type: String, default: "2021" },
    // zoom: { type: Number, default: 4 },
    showData: { type: Boolean, default: false },
    locationList: Array, //产业数据-面店分布的地图显示传入数据
    getLocation: { type: Boolean, default: false } //首页-面店分布的图片显示
  },
  data: () => ({
    loading: false,
    idHash: "MapContainer" + new Date().getTime(),
    disProvinces: " ",
    map: {}, //地图对象
    depFeatures: [], //地图标注内容
    lineArr: [],
    zoom: 7
  }),
  watch: {
    year() {
      this.refresh();
    },
    locationList() {
      this.refresh();
    }
  },
  mounted() {
    // eslint-disable-next-line no-undefined
    if (window.AMap == undefined) {
      const script = document.createElement("script");
      script.src =
        "https://webapi.amap.com/maps?v=1.4.15&plugin=AMap.MarkerClusterer,Map3D,AMap.DistrictLayer,AMap.DistrictSearch&callback=initAMap&key=de45c1a0e7ea44bea49388cea9cca2f7";
      document.head.appendChild(script);
      window.initAMap = () => {
        this.refresh();
      };
    } else {
      this.refresh();
    }
  },
  methods: {
    refresh() {
      let that = this;
      if (!window.AMap) {
        return;
      }
      const opts = {
        subdistrict: 0,
        extensions: "all",
        level: "province"
      };
      //直接通过经纬度构建mask路径
      // eslint-disable-next-line no-undef
      const district = new AMap.DistrictSearch(opts);
      district.search("青海省", function(status, result) {
        const bounds = result.districtList[0].boundaries;
        const mask = [];
        for (let i = 0; i < bounds.length; i += 1) {
          mask.push([bounds[i]]);
        }
        // eslint-disable-next-line no-undef
        const Map = new AMap.Map(that.idHash, {
          mask: mask, //只显示包裹起来的区域
          resizeEnable: true, //是否监控地图容器尺寸变化
          showIndoorMap: false, //关闭室内地图
          center: [96.01906121185537, 35.874643454131984],
          viewMode: "3D",
          dragEnable: false, //初始状态下不可移动
          pitch: 0,
          zoom: that.zoom - 0.1,
          features: that.depFeatures, //初始色块模式下,不显示标注等信息
          mapStyle: "amap://styles/021981e1781074e215441507a954df4b" //设置地图的显示样式
        });
        that.map = Map; //把这里面创建的地图对象存起来,让这个指针指向它,后续要使用

        //青海省描边--(原因是黄南中间有块地方,是属于海南自治区的。)
        for (let i = 0; i < bounds.length; i += 1) {
          // eslint-disable-next-line no-undef
          new AMap.Polyline({
            path: bounds[i],
            strokeColor: "#1a77aa",
            strokeWeight: 10,
            map: Map
          });
        }

        //点聚合数据处理
        if (that.showData) {
          // 地图的数据由父组件传入
          that.updateMark(Map, that.locationList);
        } else if (that.getLocation) {
          // 首页-面店分布的图片显示
          axios({
            url: "diagram/getShopDistribute2",
            method: "get", // default
            baseURL: "http://47.115.140.114:5001/api/report/",
            headers: {
              "x-user-token":
                "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJiYW5rZm9ydGVzdDAwMSIsInN1YiI6ImxvZ2luLmxvZ2luIiwiaWF0IjoxNjI0OTU2NjQ0LCJhdXRob3JpemF0aW9uIjp7fSwiZGVwdE5hbWUiOiLpnZLmtbfmi4npnaLkuqfkuJrnu7zlkIjmnI3liqHlubPlj7AiLCJsb2dpblRpbWUiOiIyMDIxLTA2LTI5IDE2OjUwOjQ0IiwidW5pdE5hbWUiOiLpnZLmtbfmi4npnaLkuqfkuJrnu7zlkIjmnI3liqHlubPlj7AiLCJwcm92aW5jZSI6IjQ0MDAwMCIsImNpdHkiOiI0NDAxMDAiLCJ1bml0Q29kZSI6ImxhbWlhbiIsInJlZGlzVG9rZW4iOiJkNTdmNDExOC0zYTVkLTQ2OWYtYTcxZC02MDY3NjIwNzg2ODMiLCJ0ZW5hbnRJZCI6ImxhbWlhbiIsInN0YWZmVHlwZTIiOiI0IiwiZGVwdENvZGUiOiJsYW1pYW4iLCJleHAiOjE2MjQ5NTg0NDQsInVzZXJuYW1lIjoiYmFua2ZvcnRlc3QwMDEifQ.WqCfDi6iSQnn8MYOSwnvNwy6oixiZPFdE4mEUSr0H0M"
            }
          }).then(res => {
            that.updateMark(Map, res.data.locationList);
          });
        }
        //按行政区填充色块
        that.initPro(Map);
        //也可以改用覆盖物填充的方式填充行政区
        // that.alldrawBounds(Map);

        //按行政区描边
        that.allborderLine(Map);
        Map.setFitView();
        console.log("当前放大级别", Map.getZoom());
        setTimeout(() => {
          let leftValue = that.getLnglat();
          console.log("左侧容器的经纬度", leftValue.lng);
          console.log(
            "目标地图距离容器最左侧的经度:",
            89.84339 - leftValue.lng
          ); //青海省地图经度范围89.84339和103.123006
          const leftLngRange = ((89.84339 - leftValue.lng) / 1.196642) * 0.148;
          console.log("目前跨度是目标值的倍数", leftLngRange);
          that.zoom = Map.getZoom() + leftLngRange;
          Map.setZoomAndCenter(that.zoom, [
            96.01906121185537,
            35.874643454131984
          ]);
          console.log("当前级别", Map.getZoom());
          //监听地图的缩放事件
          Map.on("zoomstart", function() {
            console.log("放大级别:", Map.getZoom());
            if (Map.getZoom() >= that.zoom) {
              that.zoomChange();
            } else {
              //重新显示行政区色块
              that.disProvinces.show();
              //且需要关闭街景模式
              that.depFeatures = [];
              that.setFeature(that.map);
              //重新显示描边
              for (let i = 0; i < that.lineArr.length; i++) {
                that.lineArr[i].show();
              }
            }
          });
        }, 0);
      });
    },
    //所有行政区填充色块-(注释掉不用)
    alldrawBounds(Map) {
      const that = this;
      that.drawBounds("西宁市", Map, "#2c54cf");
      that.drawBounds("海西蒙古族藏族自治州", Map, "#17307c");
      that.drawBounds("海东市", Map, "#17307c");
      that.drawBounds("海南藏族自治州", Map, "#2b47ac");
      that.drawBounds("海北藏族自治州", Map, "#204699");
      that.drawBounds("果洛藏族自治州", Map, "#17307c");
      that.drawBounds("黄南藏族自治州", Map, "#1c3077");
      that.drawBounds("玉树藏族自治州", Map, "#204699");
    },
    //使用覆盖物的方法,按行政区填充色块-(注释掉不用)
    drawBounds(city, Map, color) {
      //实例化DistrictSearch
      let opts = {
        subdistrict: 0, //获取边界不需要返回下级行政区
        extensions: "all", //返回行政区边界坐标组等具体信息
        level: "city" //查询行政级别为市
      };
      // eslint-disable-next-line no-undef
      const district = new AMap.DistrictSearch(opts);
      //行政区查询
      district.search(city, function(status, result) {
        const polygons = [];
        const bounds = result.districtList[0].boundaries;
        console.log(city, bounds);
        if (bounds) {
          for (let i = 0, l = bounds.length; i < l; i++) {
            //生成行政区划polygon
            // eslint-disable-next-line no-undef
            let polygon = new AMap.Polygon({
              strokeWeight: 0, //线宽
              path: bounds[i], //多边形边界路径
              fillOpacity: 0.7, //填充透明度
              fillColor: color, //填充颜色
              strokeColor: "#1a77aa" //线颜色
            });
            // 创建覆盖物的监听事件
            // polygon.on('mouseover', function(e) {
            //       polygon.setOptions({
            //         fillColor: '#114af8',//填充颜色
            //       })
            // });
            // polygon.on('mouseout', function(e) {
            //     console.log(e.lnglat);
            //     polygon.setOptions({
            //       fillColor: color,//填充颜色
            //     })
            // });
            polygons.push(polygon);
          }
        }
        Map.add(polygons);
      });
    },

    // 创建市区的颜色块
    initPro(map) {
      const that = this;
      const code = 630000; //青海省代码
      const dep = 1; //按市区划分
      let disProvince;
      disProvince && disProvince.setMap(null);
      // eslint-disable-next-line no-undef
      disProvince = new AMap.DistrictLayer.Province({
        zIndex: 12,
        adcode: [code],
        depth: dep,
        styles: {
          fill: function(properties) {
            // properties为可用于做样式映射的字段,包含
            // NAME_CHN:中文名称
            // adcode_pro
            // adcode_cit
            // adcode
            let adcode = properties.adcode;
            return that.getColorByAdcode(adcode);
          },
          // 'province-stroke': 'cornflowerblue',
          "city-stroke": "#3078AC" // 中国地级市边界
          // 'county-stroke': 'rgba(255,255,255,0.5)' // 中国区县边界
        }
      });
      disProvince.setMap(map);
      that.disProvinces = disProvince;
    },

    // 颜色辅助方法
    getColorByAdcode(adcode) {
      const colors = {
        630100: "#2c54cf", //西宁
        630200: "#17307c", //海东
        632200: "#204699", //海北
        632300: "#1c3077", //黄南
        632500: "#2b47ac", //海南
        632600: "#17307c", //果洛
        632700: "#204699", //玉树
        632800: "#17307c" //海西
      };
      return colors[adcode];
    },

    //更新标记点
    updateMark(Map, points) {
      // 位置标记
      const Markers = [];
      for (let i = 0; i < points.length; i += 1) {
        if (points[i]) {
          Markers.push(
            // eslint-disable-next-line no-undef
            new AMap.Marker({
              position: points[i].split(","),
              // eslint-disable-next-line no-undef
              offset: new AMap.Pixel(-15, -15)
            })
          );
        }
      }
      let str = [
        {
          url: pin5,
          // eslint-disable-next-line no-undef
          size: new AMap.Size(100, 100),
          // eslint-disable-next-line no-undef
          offset: new AMap.Pixel(-100, -100),
          textSize: 40,
          textColor: "#353535"
        },
        {
          url: pin4,
          // eslint-disable-next-line no-undef
          size: new AMap.Size(100, 100),
          // eslint-disable-next-line no-undef
          offset: new AMap.Pixel(-100, -100),
          textSize: 40,
          textColor: "#353535"
        },
        {
          url: pin3,
          // eslint-disable-next-line no-undef
          size: new AMap.Size(100, 100),
          // eslint-disable-next-line no-undef
          offset: new AMap.Pixel(-100, -100),
          textSize: 40,
          textColor: "#353535"
        },
        {
          url: pin2,
          // eslint-disable-next-line no-undef
          size: new AMap.Size(100, 100),
          // eslint-disable-next-line no-undef
          offset: new AMap.Pixel(-100, -100),
          textSize: 40,
          textColor: "#353535"
        },
        {
          url: pin1,
          // eslint-disable-next-line no-undef
          size: new AMap.Size(100, 100),
          // eslint-disable-next-line no-undef
          offset: new AMap.Pixel(-100, -100),
          textSize: 40,
          textColor: "#353535"
        }
      ];
      // eslint-disable-next-line no-undef
      new AMap.MarkerClusterer(Map, Markers, {
        styles: str,
        gridSize: 60,
        minClusterSize: 1
      });
    },
    //所有行政区描边
    allborderLine(Map) {
      const that = this;
      that.borderLine("海西蒙古族藏族自治州", Map);
      that.borderLine("海东市", Map);
      that.borderLine("海南藏族自治州", Map);
      that.borderLine("海北藏族自治州", Map);
      that.borderLine("果洛藏族自治州", Map);
      // that.borderLine('黄南藏族自治州',Map)//黄南中间有块地皮是海南自治区的,不能描边,采用省描边加邻区描边来作为它的边
      that.borderLine("玉树藏族自治州", Map);
      that.borderLine("西宁市", Map);
    },
    //行政区描边的功能
    borderLine(city, Map) {
      const that = this;
      const opts = {
        subdistrict: 0,
        extensions: "all",
        level: "city"
      };
      //直接通过经纬度构建mask路径
      // eslint-disable-next-line no-undef
      const district = new AMap.DistrictSearch(opts);
      district.search(city, function(status, result) {
        const bounds = result.districtList[0].boundaries;
        //添加描边
        for (let i = 0; i < bounds.length; i += 1) {
          // eslint-disable-next-line no-undef
          const myLine = new AMap.Polyline({
            path: bounds[i],
            strokeColor: "#1a77aa",
            strokeWeight: 5,
            strokeOpacity: 0.9,
            map: Map
          });
          // 创建线条的监听事件
          myLine.on("mouseover", function() {
            myLine.setOptions({
              strokeColor: "#114af8",
              strokeWeight: 10
            });
          });
          myLine.on("mouseout", function() {
            myLine.setOptions({
              strokeColor: "#1a77aa",
              strokeWeight: 5
            });
          });
          that.lineArr.push(myLine); //把行政区描边通过闭包给拿出来,后续需要显示和隐藏切换
        }
      });
    },
    //重新给地图增加标注信息
    setFeature(Map) {
      const _that = this;
      Map.setFeatures(_that.depFeatures);
    },
    //监听鼠标滚轮事件,一旦用户放大地图则切换成街景模式
    zoomChange() {
      if (this.depFeatures.length > 0) {
        console.log("已经开启街景地图,不做处理");
        return;
      } else {
        this.depFeatures = ["bg", "road", "building", "point"];
        this.map.setStatus({
          dragEnable: true //切换成街景模式需要开启可拖拽模式
        });
        this.setFeature(this.map);
        // this.map.clearMap(); //清除所有覆盖物
        // this.removePoly("polygon"); //清除选定的覆盖物
        // this.removePoly("polyline"); //清除选定的行政区边界
        this.disProvinces.hide(); //隐藏行政区色块图层
        //隐藏行政区描边
        for (let i = 0; i < this.lineArr.length; i++) {
          this.lineArr[i].hide();
        }
        console.log("开启街景地图");
      }
    },
    //清除行政区色块和边界线条--(已经注释掉采用隐藏的方案替代)
    removePoly(target) {
      let mapPolyArr = this.map.getAllOverlays(target);
      let arr = [];
      for (let i = 0; i < mapPolyArr.length; i++) {
        arr.push(mapPolyArr[i]);
      }
      this.map.remove(arr);
    },
    //获取当前缩放级别下,左侧容器的经度
    getLnglat() {
      // eslint-disable-next-line no-undef
      let pixel = new AMap.Pixel(0, 0);
      let lnglat = this.map.containerToLngLat(pixel);
      return lnglat;
    }
  }
};
</script>
<style lang="scss" scoped>
.container {
  height: 100%;
  background: #0e204f !important;
}
::v-deep .amap-logo {
  display: none !important;
}
::v-deep .amap-maps {
  background: #0e204f;
}
::v-deep .amap-drags {
  background: #0e204f;
}
::v-deep .amap-layers {
  background: #0e204f;
}
</style>

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值