Google 地图 MaxZoomService 报告最大缩放不正确,希望禁用内置控件等自定义缩放按钮

问题描述 投票:0回答:1

我正在尝试根据该位置可用的最大缩放禁用自定义谷歌地图缩放按钮。但是,MaxZoomService 的值与实际可用的最大缩放不匹配。这使我无法像内置按钮一样禁用放大按钮。

在下面的演示中,您将看到 maxZoom 报告为 19,然后在 2 秒后缩放到 20。然后,如果您使用控件缩小,则无法使用控件返回到 20,因为 maxZoom 已报告 19,并且我无法假设最大缩放实际上是 20 还是 21 作为解决方法。

<html>
  <head>
    <script>
      (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
        key: "REDACTED",
        v: "weekly",
      });
    </script>
    <style>
      .google-maps-control {
        background: #3C69BE;
        color: white;
        padding: 10px;
        border: solid 1px #45C6EF;
        margin: 10px 0 0 10px;
        cursor: pointer;
      }

      .google-maps-control[disabled] {
        opacity: 0.6;
        cursor: not-allowed;
      }
    </style>
  </head>
  <body>
    <h1>Test Google Maps Max Zoom</h1>
    <div id="map" style="width: 600px; height: 400px"></div>

    <script>
      init();

      let map;
      let zoomInButton;
      let zoomOutButton;
      let maxZoom;

      const center = {
        lat: 45.4633341,
        lng: -98.4512069,
      };

      async function init() {
        await createMap();
        await setAndDemonstrateMaxZoom();
        createCustomControls();
        handleDisabledButtons();
      }

      async function createMap() {
        const { Map, MaxZoomService } = await google.maps.importLibrary("maps");

        map = new Map(document.getElementById("map"), {
          center,
          zoom: 18,
          mapTypeId: "satellite",

          // if I comment this out, the built-in buttons are disabled as expected
          disableDefaultUI: true,

          // isFractionalZoomEnabled: true,
          gestureHandling: 'greedy',
        });

        // use `map` global to assert that map.setZoom(20) surpasses maxZoom 19
        window.map = map;
      }

      async function setAndDemonstrateMaxZoom() {
        const { MaxZoomService } = await google.maps.importLibrary("maps");
        const maxZoomService = new MaxZoomService();

        const result = await maxZoomService.getMaxZoomAtLatLng({
          lat: center.lat,
          lng: center.lng,
        });

        if (result) {
          maxZoom = result.zoom;

          console.warn("getMaxZoomAtLatLng reports 19", maxZoom);

          map.setZoom(maxZoom);

          setTimeout(() => {
            map.setZoom(20);
            console.warn("but maxZoom is actually 20", map.getZoom());
          }, 2000);
        }
      }

      function createCustomControls() {
        zoomInButton = createZoomInControl();
        zoomOutButton = createZoomOutControl();

        zoomWrapper = document.createElement('div');
        zoomWrapper.appendChild(zoomInButton);
        zoomWrapper.appendChild(zoomOutButton);

        map.controls[google.maps.ControlPosition.TOP_LEFT].push(zoomWrapper);
      }

      function createZoomInControl() {
        const button = document.createElement('button');
        button.classList.add(...['google-maps-control']);
        button.innerText = '+';
        button.addEventListener('click', () => {
          const zoom = map.getZoom();
          map.setZoom(zoom + 1);
        });

        return button;
      }

      function createZoomOutControl() {
        const button = document.createElement('button');
        button.classList.add(...['google-maps-control']);
        button.innerText = '-';
        button.addEventListener('click', () => {
          const zoom = map.getZoom();
          map.setZoom(zoom - 1);
        });

        return button;
      }

      function handleDisabledButtons() {
        google.maps.event.addListener(map, 'zoom_changed', () => {
          console.log('zoom_changed', map.getZoom());

          const zoom = map.getZoom();

          // disabling the zoom-in button does not replicate the built-in controls here
          zoomInButton.disabled = zoom >= maxZoom ? true : false;

          zoomOutButton.disabled = zoom <= 17 ? true : false;
        });
      }
    </script>
  </body>
</html>
javascript google-maps-api-3
1个回答
0
投票

作为一种巧妙的解决方法,我能够隐藏和嗅探 Google 地图缩放按钮,并使用突变观察器为我的自定义缩放按钮创建相同的启用/禁用状态。

<html>
  <head>
    <script>
      (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
        key: "REDACTED",
        v: "weekly",
      });
    </script>
    <style>
      .google-maps-control {
        background: #3c69be;
        color: white;
        padding: 10px;
        border: solid 1px #45c6ef;
        margin: 10px 0 0 10px;
        cursor: pointer;
      }

      .google-maps-control[disabled] {
        opacity: 0.6;
        cursor: not-allowed;
      }

      .gm-bundled-control {
        display: none;
      }
    </style>
  </head>
  <body>
    <h1>Test Google Maps Max Zoom</h1>
    <div id="map" style="width: 600px; height: 400px"></div>

    <script>
      init();

      let map;
      let zoomInButton;
      let zoomOutButton;

      const center = {
        lat: 45.4633341,
        lng: -98.4512069,
      };

      async function init() {
        await createMap();
        createCustomControls();
        handleMaxZoom();
      }

      async function createMap() {
        const { Map } = await google.maps.importLibrary("maps");

        map = new Map(document.getElementById("map"), {
          center,
          zoom: 18,
          mapTypeId: "satellite",
          disableDefaultUI: true,
          zoomControl: true,
        });
      }

      async function handleMaxZoom() {
        const pollForZoomButton = () => {
          const element = document.querySelector(
            '#map button[title="Zoom in"]'
          );

          if (!element) {
            setTimeout(pollForZoomButton, 100);
          } else {
            if (element.disabled) {
              zoomInButton.disabled = true;
            }

            const observer = new MutationObserver((mutations) => {
              mutations.forEach((mutation) => {
                if (mutation.type === "attributes") {
                  const { cursor } = mutation.target.style;
                  zoomInButton.disabled = cursor === "default";
                }
              });
            });

            observer.observe(element, {
              attributes: true,
            });
          }
        };

        pollForZoomButton();
      }

      function createCustomControls() {
        zoomInButton = createZoomInControl();
        zoomOutButton = createZoomOutControl();

        zoomWrapper = document.createElement("div");
        zoomWrapper.appendChild(zoomInButton);
        zoomWrapper.appendChild(zoomOutButton);

        map.controls[google.maps.ControlPosition.TOP_LEFT].push(zoomWrapper);
      }

      function createZoomInControl() {
        const button = document.createElement("button");
        button.classList.add(...["google-maps-control"]);
        button.innerText = "+";
        button.addEventListener("click", () => {
          const zoom = map.getZoom();
          map.setZoom(zoom + 1);
        });

        return button;
      }

      function createZoomOutControl() {
        const button = document.createElement("button");
        button.classList.add(...["google-maps-control"]);
        button.innerText = "-";
        button.addEventListener("click", () => {
          const zoom = map.getZoom();
          map.setZoom(zoom - 1);
        });

        return button;
      }
    </script>
  </body>
</html>
© www.soinside.com 2019 - 2024. All rights reserved.