7

Using the example GeoJSON tutorial code at leafletjs.com.
Change the myLines variable so that the two lines overlap, but run in opposite directions as follows:

var myLines = [{
    "type": "LineString",
    "coordinates": [[-100, 40], [-105, 45], [-110, 55]]
}, {
    "type": "LineString",
    "coordinates": [[-110, 55], [-105, 45], [-100, 40]]
}];

This overlapping is a common situation with lineString shapes, especially roads. In QGIS/ArcMap, one can apply an Offset = X to the layer such that a positive offset shifts each line feature X (pixels, map units) to the right, in the direction of travel (starting coordinate to ending coordinate), and a negative offset shifts the line to the left, in the direction of travel.

There does not appear to be an option in Leaflet which would allow one to apply a similar offset in the style to these lines so that they are not shown overlapping. Markers seem to have this option, but not lines. I was hoping the following code would work, but it doesn't since "offset" is not a valid option.

var myStyle = {
    "color": "#ff7800",
    "weight": 5,
    "opacity": 0.65,
    "offset": 1.5
};

L.geoJson(myLines, {
    style: myStyle
}).addTo(map);

Does this option exist or is it perhaps called something else?

  • One way of achieving this could be to make a Javascript function that takes in myLines and then returns a geojson object with the coordinates offset. You would need to loop through the coordinates and and the offset to the values. – djq Feb 4 '14 at 17:50
  • @djq Yes, but how to implement such a thing? The offset would depend on the zoom level, the angle between coordinates and the bearing of the segments between coordinates, no? – Brian D Feb 4 '14 at 22:08
  • 1
    This repo seems to hold most of the solution. However it applies to polyline and not specifically GeojJSON. Has anyone solved the problem above? If not, any suggestions on how to combine the PolylineOffset code efficiently? Matt – MattPil29 Feb 23 '16 at 13:09
  • Created Leaflet PR #4727 to add Leaflet Polyline Offset plugin to the list of Leaflet plugins. – ghybs Jul 14 '16 at 0:40
9
+200

According to Romain D on it1me.com, it can be done with the Leaflet.PolylineOffset as referenced in the comments by MattPil29 above.

I have adapted it for the data in your example. I turned off your original line by changing opacity to 0 in myStyle. There is probably a more elegant way to not add it.

The other key is flipping the x,y coordinate to make L.Polyline happy.

See a fiddle here, Leaflet Offset geojson

Main code

var myLines = [{
  "type": "LineString",
  "coordinates": [[-100, 40], [-105, 45], [-110, 55]]
}, {
  "type": "LineString",
  "coordinates": [[-110, 55], [-105, 45], [-100, 40]]
}];

var myStyle = {
  "color": "#ff7800",
  "weight": 5,
  "opacity": 0,
  "offset": 1.5
};

L.geoJson(myLines, {
  style: myStyle,
  onEachFeature: function(feature){
    var coords = feature.coordinates;
    var lengthOfCoords = feature.coordinates.length;

    //reverse x, y order for L.polyline
    for (i=0;i<lengthOfCoords;i++)
      {
      // swap x and y, save x in var holdLon then drop back into second position
        holdLon = coords[i][0];
        coords[i][0] = coords[i][1];
        coords[i][1] = holdLon;
     }

    var offset = L.polyline(coords, {offset: 5, color: 'black'}).addTo(map);
  }
}).addTo(map);

edit: If you don't want the original lines at all just remove the

.addTo(map)

in the last line, leave it as

)};

Then you can remove

style: myStyle,
  • Took the liberty to simplify the code in your JSFiddle: jsfiddle.net/rrq81rw9/23 so that it is easier to see the app code, rather than having to scroll down after the plugin code. – ghybs Jul 14 '16 at 0:36
  • Thanks, I had no idea how to call the plugin. Much better your way. – timlohnes Jul 14 '16 at 15:48
  • Is there a way to modify the original line geometry rather than adding a new one? – underdark Jul 18 '16 at 9:50
  • @underdark altering the above code you could swap the coordinates from lon, lat to lat, lon and create two separate L.polyline features, bypassing the L.geoJson creation step: jsfiddle.net/clhenrick/py2suokw/3 – clhenrick Jul 18 '16 at 22:33
  • 1
    @underdark if you'd like to attach event listeners you could store the L.polyline layers in a L.featureGroup. This would allow you to listen for events. That being said it is much easier to attach event listeners to an L.geoJson layer via passing the onEachFeature option. When I tried using the plug in above and then calling toGeoJSON() on the L.polyline layers the offset didn't seem to persist. If it did persist, I would run the offset on the polylines, convert them to GeoJSON, then add them to a L.geoJson layer. But alas... – clhenrick Jul 19 '16 at 15:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.