In my app I have:
<MapContainer {...opts} scrollWheelZoom>
<>..</>
<Polyline eventHandlers={{ click: e => { console.log('line clicked', e.sourceTarget) }, }} positions={positonArrat}/>}
</MapContainer>
Each polyline consists of N straight line sections.
How can I get the segment of polyline which was clicked without using rocket science?
Another option would be to replace a single polyline with mulitple lines, so that each click would get a single result, but a out-of-box solution would be nice...
I ended up using simple math and the onClick-function looks like:
const TOLERANCE = 3
onPolylineClick = e => {
const { x, y } = e.layerPoint
const parts = e.target._parts[ 0 ] // some undocumented shit
let prev = parts[ 0 ]
const section = parts.slice( 1, parts.length ).findIndex( p => {
try{
// check if in bounds
if( !( Math.min( prev.x, p.x ) <= x <= Math.max( prev.x, p.x ) &&
Math.min( prev.y, p.y ) <= y <= Math.max( prev.y, p.y ) ) ) return false
const yCalc = ( x - prev.x ) * ( p.y - prev.y ) / ( p.x - prev.x ) + prev.y
return Math.abs( y - yCalc ) < TOLERANCE
}finally{
prev = p
}
})
this.setState( { selectedSection:section } )
}
It sets the index of the 1st point of the matching section in state
.
Then to visualize the selected section I show an orange polyline of 2 points on top:
<MapContainer {...opts} scrollWheelZoom>
<Polyline eventHandlers={{ click:this.onPolylineClick }} positions={points} />}
{-1 !== selectedSection &&
<Polyline color="orange" positions={points.slice( selectedSection, selectedSection + 2 )}/>}
</MapContainer>
Is this working for you? You have to be careful using
._parts
, as it may change with every zoom level ifsmoothFactor
is set, or when part of the polyline is out of frame, unless you specifynoClip
. I had started my answer with using the._parts
prop, but ran into problems because of thisyeah, it works. As I understood, the
_parts
as well aslayerPoint
contain coords in pixels rather than latlng, so the zoom level and the rest do not have any influenceyes they do contain the associated pixel coordinates, but what's not documented is that the
_parts
prop is updated with every zoom / pan event to include only what's in frame, or to smooth out the polyline with lower zoom levels. I learned that the hard way. if you end up getting wierd or inconsistent results, keep that in mind@SethLutske the only thing I noticed is, that on map's boundaries the x and y are turning negative and that can produce wrong results for zoomed-in partially visible sections, which is actually not critical and in this case I just display a warning