2017-02-15 58 views
1

背景:
我正在開發一個基於Web的遠程地圖應用程序。因此,基於傳單的地圖提供了標有遠足路線的路線。由於任何遠足路線都可以是多條路線的一部分,路線(分別代表路線的相應多段線)可以重疊。小冊子 - 重疊多段線的工具提示

問題:
每個路由具有其工具提示(通過鼠標懸停觸發,{粘性:真})表示它的標籤如預期的非重疊多段線,但只要兩個或多個的路由路徑的工作重疊僅折線「在上面」打開它的工具提示。這種行爲本身並不差,但是所有的路由都同樣重要我想在指針的位置顯示路由的所有標籤(或者最多5個標籤+ x以上的內容)。我無法找到與此主題相關的任何問題。

我試了一下:
- 適用於所有航線創建一個功能組,工具提示綁定到組,希望提示功能提供了跨越指針的位置都折線的數組。事實證明,我只能得到頂部折線的信息
- 我試圖在地圖上的鼠標移動事件相同,沒有成功
- 比較指針的layerPoint座標與所有路線'_rings & _parts layPoint數組以找到匹配layerPoints,但成功率只有5%左右,因爲這些layerPoints只覆蓋折線的實際點,而不是兩點之間的連接。此外,每條折線周圍都有一個邊距,可在指針甚至觸及折線之前觸發收費點(我猜也可以改善觸摸動作)
- 邊緣問題的解決方案是在每個折線點之前添加正面和負面邊距將其與指標座標進行比較,從而改善結果,但不能解決主要問題。

旁註:
- 所有路線都畫成一個單一的帆布​​

長話短說,我需要外部幫助,以實現目標。也許你們中的一些人有想法或可以提供解決方案。任何輸入讚賞。

** UPDATE: **
一個工作,但相當低效的解決方案如下

方法:
計算在視口中的所有路由從指針的最短距離。如果指針到路徑的距離低於某個閾值,請將它們添加到應顯示的路由標籤數組中。

步驟:
1)空白提示結合到包含一個特徵組的所有路由
2.)結合mousemove事件給特徵組與follwing功能

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事件的笛卡爾層pointPoint(用於粗略排除以排除不相交的路線)

如果路線符合這些條件,請計算指向路線的指針的最接近的latlng點。我用一個自定義函數來做到這一點,在這種情況下有點長。 (我將如果某人要求它)

鼠標位置和折線/路由然後使用地圖項目方法 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); 
    }) 

回答

0

我可以給你如何做到這一點的想法,但我不是100%肯定它會做的工作。有一個plugin for Leaflet(Mapbox)可以告訴你一個點是否在一個Polygon中,並且它返回包含該點的所有Polygons。

如果此插件不適用於多段線,您可以從最後一點返回到第一條線並關閉線(我不確定這是否適合您的解決方案),從多段線創建多邊形。例如,如果連接點的折線爲[0,1,2,... n-1,n],則返回連接[n和n-1,n-1和n-2,...]。 .. 1與0]。這樣你就會有相同形狀的多段線,但它將是一個多邊形。這不是最優化的解決方案,它是使用已知和可用插件的快速解決方案。

獲得所有工具提示後,可以爲每個多邊形/多段線一次打開所有工具提示。或者可以打開一些幫助工具提示,用戶可以選擇他想打開哪一個。

我希望這有助於!如果你找出一個更好的解決方案(或找到一個能完成這項工作的插件),請在這裏發佈。

+0

我看到了傳單pip-plugin(指向多邊形),但我期望這種方法存在以下問題: 通過將最後一個點與第一個點連接起來,該多邊形覆蓋的區域比具有「重量」。設想一個漫長的路線(開始=結束),在這種情況下,路線內的所有點都將匹配爲正值,無論光標距離該路線是2px還是400px都無關緊要。 我添加了一個可能的但昂貴的解決方案,正在工作的原始帖子。 –

+0

不,我不是說你把最後一點與第一點連接起來,但是例如,如果你有[0,1,2,3,4 ... n-1,n]個點代表你的多段線,向後並連接[n與n-1,n-1與n-2,... 1與0]。我知道這不是一個優化的解決方案,但它是一個使用已知插件的快速解決方案。 –

+1

啊,謝謝澄清。這可能會起作用,除了這個問題沒有考慮多邊形的邊距/重量,這會觸發工具提示來使該特性更加可用。 –