Reputation: 43
I simply can't use polyline decorator with GeoJSON line string. I've followed a tutorial only with one line and direct coordinate, it works properly, but when I try GeoJSON, it doesn't work.
Here is my GeoJSON line string declare:
var geoJsonLie = {
"type": "FeatureCollection",
"features": [{
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 150
},
"geometry": {
"type": "LineString",
"coordinates": [
[
108.28, -2.86
],
[
108.168, -2.97
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 200
},
"geometry": {
"type": "LineString",
"coordinates": [
[
108.168, -2.97
],
[
108.06399, -3.23
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 100
},
"geometry": {
"type": "LineString",
"coordinates": [
[
108.06399, -3.23
],
[
107.899, -3.09
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 200
},
"geometry": {
"type": "LineString",
"coordinates": [
[
107.899, -3.09
],
[
107.65099, -3.13039
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 200
},
"geometry": {
"type": "LineString",
"coordinates": [
[
107.65099, -3.13039
],
[
107.58299, -3.04692
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 350
},
"geometry": {
"type": "LineString",
"coordinates": [
[
107.58299, -3.04692
],
[
107.63576, -2.72322
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 200
},
"geometry": {
"type": "LineString",
"coordinates": [
[
107.63576, -2.72322
],
[
107.65699, -2.7366
]
]
}
}
]
}]
};
And here my code to call line string:
var arrow = L.geoJSON(geoJsonLie, {
style: function(feature) {
return {
stroke: true,
weight: 5
};
},
onEachFeature: function(feature, layer) {
layer.bindPopup("owner: " + feature.properties.owner + "<br>Bandwidth: " + feature.properties.bandwidth);
}
}).addTo(map);
var arrowHead = L.polylineDecorator(arrow, {
patterns: [{
offset: '50%',
repeat: 0,
symbol: L.Symbol.arrowHead({
pixelSize: 10
})
}]
}).addTo(map);
It works fine if I use direct coordinate in variable arrow
, when I use L.geoJSON
, it doesn't work. I'm using GeoJSON because I want to display the properties
attribute on my popup.
Upvotes: 1
Views: 3917
Reputation: 38171
It appears as though the library requires a polyline or polygon layer, not a geojson layer. This is confirmed if we look at the comments in the decorator source:
/**
* Deals with all the different cases. input can be one of these types:
* array of LatLng, array of 2-number arrays, Polyline, Polygon,
* array of one of the previous.
*/
I haven't looked the source too closely so I'm not sure how easily it is to add geojson support. However, you could convert your geojson into polyline layers with a bit of manipulation (and still keep data for popups, see below):
var lines = geojson.features
.filter(function(feature) { return feature.geometry.type == "LineString" })
.map(function(feature) {
var coordinates = feature.geometry.coordinates;
coordinates.forEach(function(coordinate) { coordinate.reverse(); })
return L.polyline(coordinates);
})
Your geojson has feature collection nested in another nested feature collection, in my example below I've removed the nesting, if you don't, you'll need to scan geojson.features
for feature collections as well as polylines. By removing the nested feature collection the code is a bit simpler
The above code looks for polylines in the geojson, reverses the coordinate order (geojson is [long,lat], leaflet wants [lat,long]), and returns an array of layers. The layers could be added to the map here if you want: return L.polyline(coordinates).addTo(map)
Now we can apply the polyline decorator as documented and as you had (I've applied two decorations below):
Here's a demo:
var geojson = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 150
},
"geometry": {
"type": "LineString",
"coordinates": [
[
108.28, -2.86
],
[
108.168, -2.97
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 200
},
"geometry": {
"type": "LineString",
"coordinates": [
[
108.168, -2.97
],
[
108.06399, -3.23
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 100
},
"geometry": {
"type": "LineString",
"coordinates": [
[
108.06399, -3.23
],
[
107.899, -3.09
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 200
},
"geometry": {
"type": "LineString",
"coordinates": [
[
107.899, -3.09
],
[
107.65099, -3.13039
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 200
},
"geometry": {
"type": "LineString",
"coordinates": [
[
107.65099, -3.13039
],
[
107.58299, -3.04692
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 350
},
"geometry": {
"type": "LineString",
"coordinates": [
[
107.58299, -3.04692
],
[
107.63576, -2.72322
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 200
},
"geometry": {
"type": "LineString",
"coordinates": [
[
107.63576, -2.72322
],
[
107.65699, -2.7366
]
]
}
}
]
};
var mymap = L.map('mapid').setView([ -2.8,108], 9);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
id: 'mapbox.streets'
}).addTo(mymap);
var lines = geojson.features
.filter(function(feature) { return feature.geometry.type == "LineString" })
.map(function(feature) {
var coordinates = feature.geometry.coordinates;
coordinates.forEach(function(coordinate) { coordinate.reverse(); })
return L.polyline(coordinates);
})
var decorator = L.polylineDecorator(lines, {
patterns: [
{offset: 0, repeat: 20, symbol: L.Symbol.dash({pixelSize: 5})}
]
}).addTo(mymap);
var arrowHead = L.polylineDecorator(lines, {
patterns: [{
offset: 0,
repeat: 40,
symbol: L.Symbol.arrowHead({
pixelSize: 10,
pathOptions: {fillOpacity: 1, weight: 0}
})
}]
}).addTo(mymap);
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin=""/>
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-tAGcCfR4Sc5ZP5ZoVz0quoZDYX5aCtEm/eu1KhSLj2c9eFrylXZknQYmxUssFaVJKvvc0dJQixhGjG2yXWiV9Q==" crossorigin=""></script>
<script src="http://bbecquet.github.io/Leaflet.PolylineDecorator/dist/leaflet.polylineDecorator.js"></script>
<div id="mapid" style="width: 600px; height: 400px;"></div>
Ok, well what about accessing the properties for a popup? If we have a solid line with some markers spaced on it (as I believe you have), then we can just add a popup when we create the line string, we just add it to the map as we do so:
var lines = geojson.features
.filter(function(feature) { return feature.geometry.type == "LineString" })
.map(function(feature) {
var coordinates = feature.geometry.coordinates;
coordinates.forEach(function(coordinate) { coordinate.reverse(); })
return L.polyline(coordinates)
.addTo(mymap)
.bindPopup("<b>" + feature.properties.owner + "</b><br />" + feature.properties.bandwidth)
})
var geojson = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 150
},
"geometry": {
"type": "LineString",
"coordinates": [
[
108.28, -2.86
],
[
108.168, -2.97
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 200
},
"geometry": {
"type": "LineString",
"coordinates": [
[
108.168, -2.97
],
[
108.06399, -3.23
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 100
},
"geometry": {
"type": "LineString",
"coordinates": [
[
108.06399, -3.23
],
[
107.899, -3.09
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 200
},
"geometry": {
"type": "LineString",
"coordinates": [
[
107.899, -3.09
],
[
107.65099, -3.13039
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 200
},
"geometry": {
"type": "LineString",
"coordinates": [
[
107.65099, -3.13039
],
[
107.58299, -3.04692
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 350
},
"geometry": {
"type": "LineString",
"coordinates": [
[
107.58299, -3.04692
],
[
107.63576, -2.72322
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 200
},
"geometry": {
"type": "LineString",
"coordinates": [
[
107.63576, -2.72322
],
[
107.65699, -2.7366
]
]
}
}
]
};
var mymap = L.map('mapid').setView([ -2.8,108], 9);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
id: 'mapbox.streets'
}).addTo(mymap);
var lines = geojson.features
.filter(function(feature) { return feature.geometry.type == "LineString" })
.map(function(feature) {
var coordinates = feature.geometry.coordinates;
coordinates.forEach(function(coordinate) { coordinate.reverse(); })
return L.polyline(coordinates)
.addTo(mymap)
.bindPopup("<b>" + feature.properties.owner + "</b><br />" + feature.properties.bandwidth)
})
var arrowHead = L.polylineDecorator(lines, {
patterns: [{
offset: 0,
repeat: 40,
symbol: L.Symbol.arrowHead({
pixelSize: 10,
pathOptions: {fillOpacity: 1, weight: 0}
})
}]
}).addTo(mymap);
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin=""/>
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-tAGcCfR4Sc5ZP5ZoVz0quoZDYX5aCtEm/eu1KhSLj2c9eFrylXZknQYmxUssFaVJKvvc0dJQixhGjG2yXWiV9Q==" crossorigin=""></script>
<script src="http://bbecquet.github.io/Leaflet.PolylineDecorator/dist/leaflet.polylineDecorator.js"></script>
<div id="mapid" style="width: 600px; height: 400px;"></div>
The downside of this is that the markers themselves don't have popups, but we could add popups to them too, just by adding the markers to the map as we iterate through each geojson line:
var geojson = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 150
},
"geometry": {
"type": "LineString",
"coordinates": [
[
108.28, -2.86
],
[
108.168, -2.97
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 200
},
"geometry": {
"type": "LineString",
"coordinates": [
[
108.168, -2.97
],
[
108.06399, -3.23
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 100
},
"geometry": {
"type": "LineString",
"coordinates": [
[
108.06399, -3.23
],
[
107.899, -3.09
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 200
},
"geometry": {
"type": "LineString",
"coordinates": [
[
107.899, -3.09
],
[
107.65099, -3.13039
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 200
},
"geometry": {
"type": "LineString",
"coordinates": [
[
107.65099, -3.13039
],
[
107.58299, -3.04692
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 350
},
"geometry": {
"type": "LineString",
"coordinates": [
[
107.58299, -3.04692
],
[
107.63576, -2.72322
]
]
}
},
{
"type": "Feature",
"properties": {
"owner": "TSEL",
"bandwidth": 200
},
"geometry": {
"type": "LineString",
"coordinates": [
[
107.63576, -2.72322
],
[
107.65699, -2.7366
]
]
}
}
]
};
var mymap = L.map('mapid').setView([ -2.8,108], 9);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
id: 'mapbox.streets'
}).addTo(mymap);
geojson.features
.filter(function(feature) { return feature.geometry.type == "LineString" })
.map(function(feature) {
var coordinates = feature.geometry.coordinates;
coordinates.forEach(function(coordinate) { coordinate.reverse(); })
var line = L.polyline(coordinates).addTo(mymap).bindPopup("<b>" + feature.properties.owner + "</b><br />" + feature.properties.bandwidth);
arrowify(line,feature);
})
function arrowify(line,feature) {
L.polylineDecorator(line, {
patterns: [{
offset: 0,
repeat: 30,
symbol: L.Symbol.arrowHead({
pixelSize: 10,
pathOptions: {fillOpacity: 1, weight: 0}
})
}]
}).addTo(mymap).addTo(mymap).bindPopup("<b>" + feature.properties.owner + "</b><br />" + feature.properties.bandwidth);
}
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin=""/>
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-tAGcCfR4Sc5ZP5ZoVz0quoZDYX5aCtEm/eu1KhSLj2c9eFrylXZknQYmxUssFaVJKvvc0dJQixhGjG2yXWiV9Q==" crossorigin=""></script>
<script src="http://bbecquet.github.io/Leaflet.PolylineDecorator/dist/leaflet.polylineDecorator.js"></script>
<div id="mapid" style="width: 600px; height: 400px;"></div>
Upvotes: 1