谷歌地图缩小时卡顿

4
我在我的项目中使用谷歌地图。我有一个选择字段,包括一个国家和它的县。更改选择后,我会缩放到该位置并在地图上绘制多边形。当我为一个位置绘制多边形时,一切正常。 但是,如果我选择一个有20个多边形需要绘制的国家,并从地图上缩小以使其可见,整个动画过程就会变得卡顿。我尝试将缩放包装成Promise对象,并等待直到完成,然后居中地图并绘制多边形,希望这样能使动画更加平滑。下面是我的选择 onchange 事件,在其中根据所选值缩放地图并绘制多边形。如果所选值是某个县,我会缩放地图并仅绘制该县的多边形。如果选择了整个国家,我就会缩小地图并绘制该国所有县的多边形:
        let regions = geodata;
        let center = MAP_CENTER;
        let zoomLevel = 7;

        if (select.value !== country) {
            const location = geodata.find(({ Name }) => Name.includes(select.value));
            regions = [location];
            center = { lat: Number(location.Lat), lng: Number(location.Lng) };
            zoomLevel = 9;
        }

        smoothZoomPromise(map, zoomLevel, map.getZoom()).then((googleMap) => {
            googleMap.panTo(center);
            if (!(select.value === country && polygons.state.arrayOfPolygons.length === geodata.length)) {
                drawRegions(googleMap, regions);
            }
        });

这是 smoothZoomPromise 函数:
const smoothZoomPromise = (map, wantedLevel, startingLevel) => {
    return new Promise((resolve) => {
        if (wantedLevel === startingLevel) {
            return resolve(map);
        }
        const smoothZoom = (googleMap, finishLevel, startLevel) => {
            if (finishLevel === startLevel) {
                return;
            }
            const current = startLevel > finishLevel ? startLevel - 1 : startLevel + 1;
            const z = google.maps.event.addListener(googleMap, 'zoom_changed', event => {
                google.maps.event.removeListener(z);
                smoothZoom(googleMap, finishLevel, current);
            })

            doZoom(googleMap, current, resolve, current === finishLevel);
        }

        smoothZoom(map, wantedLevel, startingLevel);
    });
}

const doZoom = (map, cnt, resolve, last) => {
    setTimeout(() => {
        map.setZoom(cnt);
        if(last) {resolve(map)}
    }, 80);
}

这就是我如何绘制多边形的方法:

export const polygons = {
    state: {
        arrayOfPolygons: []
    },
    clearState: function () {
        this.state.arrayOfPolygons.forEach(polygon => polygon.setMap(null));
        this.state.arrayOfPolygons = []
    }
};

export const drawRegions = (map, regions) => {
    polygons.clearState();
    regions.forEach(region => {
        const coords = region.Coordinates.map(item => ({
            lat: item[1], lng: item[0],
        }))

        // Construct the polygon.
        const color = colorMapper(getStatsData(region.Name));
        const polygon = new google.maps.Polygon({
            paths: coords,
            strokeColor: color,
            strokeOpacity: 0.8,
            strokeWeight: 2,
            fillColor: color,
            fillOpacity: 0.35
        });
        polygon.setMap(map);
        polygons.state.arrayOfPolygons.push(polygon)
    })
}

但是,正如我之前提到的,我的问题是当我选择一个国家并将地图从9级缩放到7级并为其绘制20个多边形时,地图的缩小会出现故障。有没有办法让它更加平滑,并修复它?

我做了一个示例codesanbox。唯一需要的就是在index.js中使用有效的API_KEY

if (document.querySelector(".js-map")) {
  gmap.GMap(".js-map", "YOUR_API_KEY");
}

我希望实现与Google地图这里相同的过渡效果。当您将地图缩放到最大并更改选择位置时,地图不会被呈现出来,直到它被缩小。我该如何实现这种效果?


@MrUpsidown,我已经将它们移除了,希望现在更易读了。 - Leff
1
样本数据和一个 [mcve] 可能是您现在所缺少的。 - MrUpsidown
@Leff 我正在调查这个问题,很快就会回复你的。 :) - evan
1
同时,看起来你提供的covid网站是这样实现的:首先,将这些动作绑定到onZoomChanged事件上:使用250毫秒的防抖延迟,并根据初始和目标缩放级别应用不同的地图样式。然后,将setCenter()设置为新位置,最后将setZoom()设置为目标缩放级别,而不使用中间级别。 - evan
1
@evan非常感谢您的努力,解释了covid地图的工作方式。 - Leff
显示剩余5条评论
1个回答

1

关键是将多边形绘制包装在一次性的idle监听器内,即:

smoothZoomPromise(map, zoomLevel, map.getZoom()).then((googleMap) => {
  googleMap.panTo(center);
  if (
    !(
      select.value === "Croatia" &&
      polygons.state.arrayOfPolygons.length === geodata.length
    )
  ) {

    //  ----|
    //      |
    //      v
    google.maps.event.addListenerOnce(googleMap, "idle", () => {
      drawRegions(googleMap, regions);
    });

  }
});

沙盒在这里这里 - 你需要放入自己的API密钥。

我认为这就是谷歌的做法 - 这是标准做法。您可以在此处检查不同类型的gmap事件此处


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接