【问题标题】:Leaflet - tooltips for overlapping polylinesLeaflet - 重叠折线的工具提示
【发布时间】:2017-02-15 14:00:31
【问题描述】:

背景:
我正在开发一个基于网络的远足地图应用程序。因此,基于传单的地图提供了带有标签的远足径路线。由于任何远足路径都可以是多条路线的一部分,因此路线(分别代表路线的相应折线)可以重叠。

问题:
每条路线都有其工具提示(由鼠标悬停触发,{sticky:true})显示其标签,该标签对非重叠折线按预期工作,但只要两条或更多路线重叠,只有“顶部”的折线会打开其工具提示。这种行为本身并不坏,但由于所有路线都同样重要,我想在指针位置显示路线的所有标签(或最多 5 个标签 + x 更多)。我找不到与此主题相关的任何问题。

我尝试了什么:
- 为所有路线创建一个特征组,将工具提示绑定到该组,希望工具提示功能提供一个包含所有穿过指针位置的折线的数组。事实证明,我只得到顶部折线的信息
- 我在地图上尝试了 mousemove 事件,但没有成功
- 将指针的 layerPoint 坐标与所有路线的 _rings & _parts layoutPoint 数组进行比较以找到匹配的 layerPoints,但成功率仅为 5% 左右,因为这些 layerPoints 仅覆盖折线的实际点,而不是两点之间的连接。此外,每条折线周围都有一个边距,会在指针甚至接触折线之前触发提示(我猜这也改善了触摸操作)
- 边距问题的解决方案是在将每个折线点与指针坐标进行比较之前为每个折线点添加正边距和负边距,这可以改善结果但不能解决主要问题。

旁注:
- 所有路线都被绘制到一个画布中

长话短说,我需要外部帮助来实现目标。也许你们中的一些人有一个想法或可以提供一个解决方案。任何意见表示赞赏。

** 更新: **
一个有效但效率很低的解决方案如下

方法:
计算从指针到视口中所有路线的最短距离。如果指针到路线的距离低于某个阈值,则将它们添加到应显示的路线标签数组中。

步骤:
1.) 将空白工具提示绑定到包含所有路线的功能组
2.) 使用以下函数将 mousemove 事件绑定到特征组

var routesFeatureGroup = L.featureGroup(routesGroup)
    .bindTooltip('', {sticky: true})
    .on('mousemove', function(e){
        var routeLabels   = [e.layer.options.label]; // add triggering route's label by default
        var mouseCoordAbs = el.$map.project(e.latlng);

        $.each(vars.objectsInViewport.routes, function(i, v){
            if (e.layer.options.id != el.$routes[i].options.id && el.$routes[i]._pxBounds.contains(e.layerPoint)){
                var nearestLatlngOnPolyline = getNearestPolylinePoint(e.latlng, el.$routes[i]);
                var polyPointCoordAbs = el.$map.project(nearestLatlngOnPolyline);

                var distToMouseX = polyPointCoordAbs.x - mouseCoordAbs.x;
                var distToMouseY = polyPointCoordAbs.y - mouseCoordAbs.y;
                var distToMouse  = Math.sqrt(distToMouseX*distToMouseX + distToMouseY*distToMouseY);

                if (distToMouse < 15) {
                    routeLabels.push(el.$routes[i].options.label);
                }
             }
        })

        var routesFeatureGroup.setTooltipContent(routeLabels.join('<br>'));
    })

说明:
我已经为应用程序的另一部分收集了当前视口中的所有对象(路线和标记)。当前可见的所有路由都存储在 vars.objectsInViewport.routes (分别是它们的 id)中,所以我不必遍历所有路由。默认添加触发 mousemove 事件的图层。然后,如果出现以下情况,我会检查当前可见的每条路线:
- 它们的 id 与触发 mousemove 事件的层不同(因为默认添加了此标签) - 如果它们的边界(在笛卡尔坐标中:“_pxBounds”)包含 mousemove 事件的笛卡尔 layerPoint(用于排除不相交的路线的粗略方法)

如果路线满足这些条件,则计算从指针到路线的最近纬度点。我使用自定义函数执行此操作,在此上下文中发布它有点长。 (如果有人要求,我会这样做)

然后使用map-project方法将折线/路线上的鼠标位置和纬度点转换为绝对坐标 http://leafletjs.com/reference.html#map-project

最后,使用毕达哥拉斯计算这些到点之间的距离。它是基于像素的,因此缩放级别不是一个因素。如果距离低于某个阈值 (15px),则它们与指针足够接近以被视为悬停(折线周围有默认边距),因此路线的标签将添加到标签数组中。

最后,特征组的工具提示被所有标签填充。

即使手术成本很高,结果也很有希望。我添加了 50ms 的超时来减少函数调用:

var tooltipTimeout;
var routesFeatureGroup = L.featureGroup(routesGroup)
    .bindTooltip('', {sticky: true})
    .on('mousemove', function(e){
        clearTimeout(tooltipTimeout);

        tooltipTimeout = setTimeout(function(){
            // collect labels
            // ...
        },50);
    .on('mouseout', function(){
        clearTimeout(tooltipTimeout);
    })

【问题讨论】:

    标签: leaflet tooltip polyline overlapping


    【解决方案1】:

    我可以告诉你如何做到这一点,但我不能 100% 确定它会完成这项工作。有一个plugin for Leaflet (Mapbox) 可以告诉您一个点是否在多边形内,它会返回包含该点的所有多边形。

    如果此插件不适用于折线,您可以从折线创建多边形,只需从最后一点返回到第一点并关闭线(我不确定这是否适合您的解决方案)。例如,如果您有一条由 [0, 1, 2, .... n-1, n] 连接的点组成的折线,那么您将返回将 [n 与 n-1, n-1 与 n-2, 连接起来。 .. 1 与 0]。这样,您将拥有相同形状的折线,但它将是一个多边形。这不是最优化的解决方案,它是使用已知可用插件的快速修复。

    获得所有工具提示后,您可以为每个多边形/多段线一次性打开所有工具提示。或者可能打开一些帮助工具提示,用户可以在其中选择他想要打开的工具提示。

    我希望这会有所帮助!如果您找到更好的解决方案(或找到可以完成这项工作的插件),请在此处发布。

    【讨论】:

    • 我看到了传单 pip-plugin(多边形中的点),但我预计这种方法会出现以下问题:通过将最后一个点与第一个点连接起来,多边形覆盖的区域比带有“权重”的折线。想象一条长的圆形路线(开始 = 结束),在这种情况下,路线内的所有点都将匹配正数,无论光标是距离该路线 2 像素还是 400 像素。我为正在运行的原始帖子添加了一个可能但昂贵的解决方案。
    • 不,我并不是说你将最后一个点与第一个点连接起来,但例如,如果你有 [0,1,2,3,4...n-1,n] 点代表你的折线,然后你向后走并连接 [n 与 n-1,n-1 与 n-2,... 1 与 0]。我知道这不是一个优化的解决方案,但它是使用已知插件的快速修复。
    • 啊,感谢您的澄清。这可能会起作用,除了这个方法没有考虑多段线的边距/重量会触发工具提示以使该功能更可用的“问题”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2014-08-03
    • 1970-01-01
    • 2017-06-24
    • 2016-03-19
    • 1970-01-01
    • 2015-07-11
    相关资源
    最近更新 更多