29

I'm trying to insert lines between markers (which are generated from JSON data) in leaflet. I saw an example, but it doesn't work with JSON data. I can see the markers, but no lines appear.

var style = {
  color: 'red',
  fillColor: "#ff7800",
  opacity: 1.0,
  fillOpacity: 0.8,
  weight: 2
};

$.getJSON('./server?id_dispositivo=' + id_device + '', function(data) {
  window.geojson = L.geoJson(data, {
    onEachFeature: function (feature, layer) {
      var Icon = L.icon({
        iconUrl: './images/mymarker.png',
        iconSize: [18, 28], // size of the icon
        style: style,
      });
      layer.setIcon(Icon);
      layer.bindPopup(feature.properties.date + '<br />' + feature.properties.id);
    }
  });
});
map.addLayer(geojson);

enter image description here

My JSON data:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [
          -70.219841,
          8.6310997
        ]
      },
      "properties": {
        "id": 336,
        "id_user": 1,
        "id_device": 1,
        "timestamp": 1446571154,
        "date": "12:49PM 03-11-2015",
        "Latitude": 8.6310997,
        "Longitude": -70.219841,
        "speedKPH": 0,
        "heading": "",
        "Name": "N\/D",
        "City": "N\/D",
        "estatus": "Stop"
      }
    }
  ]
}
Dan Lowe
  • 51,713
  • 20
  • 123
  • 112
user4131013
  • 425
  • 1
  • 7
  • 14
  • 1
    How about formatting that code so it is readable. If it's too much effort for you to do it, then it's probably too much effort for anyone to try to help you make it work. A proper problem description will help also , one that includes errors and description of what is happening – charlietfl Nov 02 '15 at 01:10
  • sorry you are right, my english is not good, I tried to explain better what happen, thank you. – user4131013 Nov 02 '15 at 02:11
  • Your json appears to have problems. When I plug it into http://jsonlint.com/ it indicates there are errors with it. – Bruce P Nov 05 '15 at 19:34
  • I have edited the question to try to improve readability. A bit of the first code snippet, but mostly the English text. One note, in the future if you are posting JSON data or anything else that is a single very long line, it is really helpful if you reformat it into a readable form first. It is very hard for people to read minified JSON and make sense of it, and helping people read your question helps get you an answer more quickly. I've done that, but it's better if you do it. – Dan Lowe Nov 05 '15 at 19:50
  • @BruceP The original JSON was invalid because the closing `]}` was missing. Leaving off a closing brace is a common paste error, so I added them. The OP will have to edit the question if the JSON data is still incomplete. As it is written now, it validates. – Dan Lowe Nov 05 '15 at 19:53
  • Thank you Dan Lowe apreciate your help – user4131013 Nov 10 '15 at 21:13

2 Answers2

22

There are many ways you could do this by iterating over either the original GeoJSON or the resulting L.GeoJson layer to produce a polyline geometry. Here is one simple function that will turn a L.geoJson layer of points into an array of coordinates that can be passed to L.polyline:

function connectTheDots(data){
    var c = [];
    for(i in data._layers) {
        var x = data._layers[i]._latlng.lat;
        var y = data._layers[i]._latlng.lng;
        c.push([x, y]);
    }
    return c;
}

and here is a fiddle showing it at work on some synthetic GeoJSON data:

http://jsfiddle.net/nathansnider/36twhxux/

Assuming that your GeoJSON data contains only point geometry, you should be able to use it after you define window.geojson within your $.getJSON success function like so:

pathCoords = connectTheDots(window.geojson);
var pathLine = L.polyline(pathCoords).addTo(map)

If your GeoJSON data are more complex, you might need to add some conditionals to check for geometry type, etc., but this should at least give you a general idea of how to proceed.

nathansnider
  • 2,773
  • 1
  • 14
  • 17
  • 1
    Be cautious with iterating `data._layers` object properties: the order of iteration is not guaranteed as per JS spec. The resulting polyline could connect points in any order then… Even though all tests I had the opportunity to do give consistent order. – ghybs Nov 08 '15 at 17:39
  • Thank you for your response if I want Adding this options What I need you to do. Thank you again { color: 'red', weight: 10, opacity: .7, dashArray: '20,15', lineJoin: 'round' } – user4131013 Nov 10 '15 at 04:08
  • Whe use this code pathCoords = connectTheDots(window.geojson); var pathLine = L.polyline(pathCoords).addTo(map) I get a error connectTheDots is not defined – user4131013 Nov 10 '15 at 20:40
  • Thank you so much I understood how, apreciate your help, another question how hide the lines, thank you again – user4131013 Nov 12 '15 at 23:41
  • @nathansnider can I join the points based on specific geojson property? For example based on the status. If status is yes then the points having same status should get connected. – Bruce Aug 29 '16 at 11:46
7

EDIT:

Nathan's idea is correct in the sense that you will have to build a polyline (the lines between your markers) yourself.

To be rigorous, you have to use your data when the list of points is still an array (and assuming the array order is the order of line connections you want to get). Which means you have to work on your GeoJSON data directly.

For example, you would do:

function connectDots(data) {
    var features = data.features,
        feature,
        c = [],
        i;

    for (i = 0; i < features.length; i += 1) {
        feature = features[i];
        // Make sure this feature is a point.
        if (feature.geometry === "Point") {
            c.push(feature.geometry.coordinates);
        }
    }
    return c;
}

L.polyline(connectDots(data)).addTo(map);

The GeoJSON data will be converted by Leaflet into vectors for polylines, polygons, etc., and markers for point features. Please refer to Leaflet tutorial and reference.

When you want to specify how Leaflet should style the vectors, you should indeed make up an object that holds path options (like your style variable on first line), but you should give it as the style option of your L.geoJson layer, not inside an icon.

When you want to specify how Leaflet should style the markers, you can indeed set a specific icon, which will be applicable only to point features. You should better use the pointToLayer option, as the code will be really applied only on points, instead of trying to apply it to vectors (which do not have a method setIcon for example).

Finally, when you want to perform some action which applies to both vectors and markers, you use the onEachFeature option, for example to bind your popup.

So you would end up with something like:

var myIcon = L.icon({
    iconUrl: './images/mymarker.png',
    iconSize: [18, 28]
});

var geojson = L.geoJson(data, {

    style: style, // only applies to vectors.

    // only applies to point features
    pointToLayer: function(feature, latlng) {
        return L.marker(latlng, {icon: myIcon});
    },

    // will be run for each feature (vectors and points)
    onEachFeature: function(feature, layer) {
        layer.bindPopup(feature.properties.date + '<br />' + feature.properties.id);
    }

});

As pointed out in the comments, whenever you seek for help from other people, you would make their task easier (hence you would get better and faster support) if you take the time to properly state your issue, with description / screenshots of what is going wrong and post some clean code. A very good practice for client side code is to reproduce the issue on jsFiddle for example.

ghybs
  • 47,565
  • 6
  • 74
  • 99
  • Thank you so much I put a image that explains better my question – user4131013 Nov 02 '15 at 12:59
  • Wow that is very different from what I understood originally indeed! It looks to me that you have missing data in your GeoJSON (but you do not show it, so I cannot be sure). You seem to have only point data, but no polylines. So you would have to build the path yourself, probably assuming that the points order is correct… – ghybs Nov 02 '15 at 13:12
  • Thank you for your response if I want Adding this options What I need you to do thank you again { color: 'red', weight: 10, opacity: .7, dashArray: '20,15', lineJoin: 'round' } – user4131013 Nov 10 '15 at 04:06
  • Please refer to Leaflet [Polyline API](http://leafletjs.com/reference.html#polyline), which accepts [Path options](http://leafletjs.com/reference.html#path). You would simply add your style definition object after the coordinates: `L.polyline(connectDots(data), { color: "red" /* etc. */ })` – ghybs Nov 10 '15 at 05:37
  • When I test your code I get TypeError: features is undefined – user4131013 Nov 10 '15 at 19:52
  • I am Trying to call a function for this way :$.getJSON('data.php', function(data) { connectDots(data); window.geojson = L.geoJson(data, { – user4131013 Nov 10 '15 at 20:32