Google Maps Api - map.panto(latlng) 何时平滑

发布于 2025-01-18 20:58:02 字数 2106 浏览 0 评论 0原文

编辑: 我正在尝试计算 Google Maps API map.panTo(Lat, Lng) 何时决定行程对于“平滑”平移来说太远(像素)。

这就是手册所说的: -

将地图的中心更改为给定的 LatLng。如果变化小于地图的宽度和高度,过渡将平滑地进行动画处理。

我已经确定,如果只有 x 或 y 顶点移动(只有 Lat 或 Lng 值发生变化,但不是两者都发生变化),那么检查的只是地图视口宽度或高度的三分之二 0.6666。但如果 Lat 和 Lng 值都发生变化,那么我不确定公式。

我们所知道的一个例子: -

如果我们从珀斯前往耶蓬附近的某个地方: -

珀斯:纬度:-31.9523 经度:115.8613 x像素:13465 y像素:9728 Yeppoon:纬度:-22.9523 经度:150.2093 xPixel 15028,yPixel:9265

X/垂直移动:15028 - 13465 = 1563 Y/水平移动:9265 - 9728 = -463

然后,对于同一行程,以下视口尺寸会产生平滑的平移;宽度或高度小于 1 像素会强制进行硬平移: -

视口

宽度:1337 1435 1236 高度:492 448 574

视口平移边界线的公式是什么?

它应该是显而易见的,但我只是看不到它

我拥有的唯一其他信息是: -

零缩放时的 Google 标题大小 = 256 我使用的缩放是 6 = 乘数 64

X 像素公式 = 256 * (0.5 + 经度 / 360) * 64

let siny = Math.sin((Latitude * Math.PI) / 180); // 截断为 0.9999 有效地将纬度限制为 89.189。这是 // 大约超过世界图块边缘三分之一的图块。 siny = Math.min(Math.max(siny, -0.9999), 0.9999);

Y 像素公式 = 256 * (0.5 - Math.log((1 + siny) / (1 - siny)) / (4 * Math.PI))

有道理吗?

编辑

请复制 https://richardmaher.github.io/Brotkrumen/testmap.html如果它使生活更轻松(由于 API 密钥必须在本地运行)

请参阅控制台以获取调试信息。

将浏览器缩小到宽度 615 像素,您将平滑滚动/平移停止。

准备好回答任何其他问题

另请参阅 https://issuetracker.google.com/issues/228349799

有人可以用伪代码或至少不太含糊的语言解释 panTo() 方法平滑过渡要求的 API 参考手册定义:-

平移平移(latLng) 参数: latLng: LatLng|LatLngLiteral 地图的新中心纬度/经度。 返回值:无 将地图的中心更改为给定的 LatLng。 如果变化较小 比地图的宽度和高度都大,过渡会很平滑 动画。

具体而言,在这种情况下“变化”是什么?

示例: -

Zoom Level = 6
LatLng1 = lat: -31.9523, lng: 115.8613 Pixel X = 13464 Pixel Y = 9728
LatLng2 = lat: -33.8688, lng: 151.2093 Pixel X = 15073 Pixel Y = 9831
Current Map Center is LatLng1 and panning to LatLng2
I make the "change" to be horizontal 1609px and vertical 103px

如果地图的 DIV 容器至少有 616 像素宽和 344 像素高,则平移是平滑的,否则会跳跃。

有人可以帮我启发式地将这些数字与算法结合起来吗?

EDITED:
I'm trying to work out when Google Maps API map.panTo(Lat, Lng) decides the trip is too far (pixels) for a "smooth" pan.

This is what the manual has to say: -

Changes the center of the map to the given LatLng. If the change is less than both the width and height of the map, the transition will be smoothly animated.

I've established that if there is only x or y vertex movement (only either Lat or Lng value changes but not both) then the check is a simple two-thirds .6666 of the map's viewport width or height. But if both Lat and Lng values change then I'm not sure of the formula.

An example of what we know: -

If we travel from Perth to somewhere up near Yeppoon: -

Perth: Lat: -31.9523 Lng: 115.8613 xPixel: 13465 yPixel: 9728
Yeppoon: Lat: -22.9523 Lng: 150.2093 xPixel 15028, yPixel: 9265

X/vertical movement: 15028 - 13465 = 1563
Y/horizontal movement: 9265 - 9728 = -463

Then, for that same trip, the following viewport sizes yield smooth pans; 1 pixel width or height less forces a hard pan: -

Viewport

Width: 1337 1435 1236
Height: 492 448 574

What is the formula for viewport pan borderline?

It should be obvious but I just can't see it

The only other information I have is: -

Google Title size at zero zoom = 256
The zoom I'm using is 6 = multiplier 64

X Pixel Formula = 256 * (0.5 + Longitude / 360) * 64

let siny = Math.sin((Latitude * Math.PI) / 180);
// Truncating to 0.9999 effectively limits latitude to 89.189. This is
// about a third of a tile past the edge of the world tile.
siny = Math.min(Math.max(siny, -0.9999), 0.9999);

Y Pixel Formula = 256 * (0.5 - Math.log((1 + siny) / (1 - siny)) / (4 * Math.PI))

Make any sense?

EDITEND

Please copy https://richardmaher.github.io/Brotkrumen/testmap.html if it makes life easier (has to be run locally due to API key)

See console for debugging info.

Shrink browser to Width 615px and you'll smooth scrolling/panning stop.

Ready to answer any other questions

See also https://issuetracker.google.com/issues/228349799

Can someone please explain in pseudocode, or at least less ambiguous language, the API Refence Manual definition for smooth transition requirements of the panTo() method: -

panTo panTo(latLng)
Parameters: latLng: LatLng|LatLngLiteral The
new center latitude/longitude of the map.
Return Value: None
Changes the center of the map to the given LatLng. If the change is less
than both the width and height of the map, the transition will be smoothly
animated.

Specifically, what is "the change" in this context?

Example: -

Zoom Level = 6
LatLng1 = lat: -31.9523, lng: 115.8613 Pixel X = 13464 Pixel Y = 9728
LatLng2 = lat: -33.8688, lng: 151.2093 Pixel X = 15073 Pixel Y = 9831
Current Map Center is LatLng1 and panning to LatLng2
I make the "change" to be horizontal 1609px and vertical 103px

If the map's DIV container is at least 616px wide and 344px high the pan is smooth if not it jumps.

Can someone please help me heuristicly marry up those figures with an algoithm?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

五里雾 2025-01-25 20:58:02

panTo() 更改地图的中点,如果中点的坐标在视口内发生变化,过渡将呈现平滑的动画效果。

视口包含用于显示返回结果的推荐视口,指定为定义视口边界框的西南角和东北角的两个纬度、经度值。通常,视口用于在向用户显示结果时构建结果。

panTo() changes the map's midpoint and if the coordinates of the midpoint changes within the viewport, the transition will be smoothly animated.

Viewport contains the recommended viewport for displaying the returned result, specified as two latitude, longitude values defining the southwest and northeast corner of the viewport bounding box. Generally the viewport is used to frame a result when displaying it to a user.

岁月苍老的讽刺 2025-01-25 20:58:02

好吧,我认为具体问题的答案只是四舍五入,但我不需要追逐这个问题,因为在上个月左右的时间里,谷歌已经将标记的重新归位与平滑泛测试脱钩了。现在,在停止维护标记的 DOM 之前,它是任意 100000px 限制。

完整的故事可以在此处找到(请记住,由于 API 密钥硬编码,您需要在尝试运行之前将 testmap.html 复制到本地文件系统。)

TL;DR 版本和核心逻辑在此函数中:-

    function makeDestCenter(){
        console.log("Panning to new Center " + map.getZoom());
        var home = map.getCenter();
        var zoom = map.getZoom();
        var scale = 1 << zoom;  
        var proj = map.getProjection();
        
        var homePoint =  proj.fromLatLngToPoint(home);  
        var startPixelX = Math.round(homePoint.x * scale);
        var startPixelY = Math.round(homePoint.y * scale);

        var destPoint =  proj.fromLatLngToPoint(dest[destIndex]);
        var destPixelX = Math.round(destPoint.x * scale);
        var destPixelY = Math.round(destPoint.y * scale);
        var xTrip = Math.abs(destPixelX - startPixelX);
        var yTrip = Math.abs(destPixelY - startPixelY);

        console.log("sX " + startPixelX + " dX " + destPixelX + " sY " + startPixelY + " dY " + destPixelY);

        if ((xTrip > MAX_TRIP) || (yTrip > MAX_TRIP)) {
            google.maps.event.addListenerOnce(map, 'idle', makeDestCenter);
            map.setZoom(--zoom);
        } else {
            if (xTrip == TOO_SMALL && yTrip == TOO_SMALL) {
                google.maps.event.addListenerOnce(map, 'idle', makeDestCenter);
                map.setZoom(++zoom);
            } else {
                map.panTo(dest[destIndex]);
            }
        }
    }

Ok I think the answer to the specific question is just down to rounding but I don't need to chase that one as, in the last month or so, Google has decouple its rehoming of the markers from the smooth pan test. It is now an arbitrary 100000px limit before it stops maintaing the DOM for markers.

The complete story can be found here (remember due to the API key hard-coding you need to copy testmap.html to your local file system before trying to run it.)

The TL;DR version and core logic is in this function: -

    function makeDestCenter(){
        console.log("Panning to new Center " + map.getZoom());
        var home = map.getCenter();
        var zoom = map.getZoom();
        var scale = 1 << zoom;  
        var proj = map.getProjection();
        
        var homePoint =  proj.fromLatLngToPoint(home);  
        var startPixelX = Math.round(homePoint.x * scale);
        var startPixelY = Math.round(homePoint.y * scale);

        var destPoint =  proj.fromLatLngToPoint(dest[destIndex]);
        var destPixelX = Math.round(destPoint.x * scale);
        var destPixelY = Math.round(destPoint.y * scale);
        var xTrip = Math.abs(destPixelX - startPixelX);
        var yTrip = Math.abs(destPixelY - startPixelY);

        console.log("sX " + startPixelX + " dX " + destPixelX + " sY " + startPixelY + " dY " + destPixelY);

        if ((xTrip > MAX_TRIP) || (yTrip > MAX_TRIP)) {
            google.maps.event.addListenerOnce(map, 'idle', makeDestCenter);
            map.setZoom(--zoom);
        } else {
            if (xTrip == TOO_SMALL && yTrip == TOO_SMALL) {
                google.maps.event.addListenerOnce(map, 'idle', makeDestCenter);
                map.setZoom(++zoom);
            } else {
                map.panTo(dest[destIndex]);
            }
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文