How to use this JSON Data on my Leaflet Map - leaflet

How can I use this type of json data in my leaflet map? I have lot of area datasets and there co-ordinates array is somewhat confusing. I want to know how can I use this data set to show polygons on my map.
{
"Locality": "Andrews Ganj",
"Loc_Id": 1006613,
"City": "New Delhi",
"City_Id": 10397,
"State": "Delhi",
"HH": 1713,
"T_Pop": 7418,
"T_mPop": 3842,
"T_fPop": 3576,
"CGT10L": 20.26,
"C5_10L": 31.23,
"C1o5_5L": 36.37,
"CLT1o5L": 12.14,
"Coordinates": "28.561508|77.220098$28.561776|77.220469$28.562004|77.220674$28.561748|77.221049$28.561635|77.221411$28.562657|77.221943$28.562881|77.221555$28.562955|77.221624$28.563224|77.221846$28.564101|77.222571$28.564359|77.222735$28.564582|77.222899$28.565257|77.22327$28.565302|77.223305$28.565317|77.223356$28.56528|77.22352$28.565568|77.223684$28.565617|77.223663$28.565647|77.223663$28.565681|77.223667$28.565886|77.223844$28.565997|77.22403$28.566084|77.224073$28.566611|77.22444$28.56707|77.224663$28.567374|77.224804$28.567752|77.224983$28.567935|77.22501$28.567964|77.225012$28.56778|77.22547$28.567577|77.225968$28.567507|77.226139$28.566662|77.228219$28.566539|77.228578$28.566479|77.228722$28.566147|77.229518$28.56609|77.229666$28.565992|77.229919$28.565964|77.229999$28.5659|77.230175$28.565791|77.230598$28.565746|77.230792$28.5657|77.231073$28.565646|77.2317$28.565643|77.231748$28.565602|77.232306$28.565532|77.233377$28.565492|77.23383$28.565472|77.23409$28.565177|77.233967$28.564747|77.23376$28.56397|77.233318$28.563079|77.232797$28.562897|77.232657$28.560578|77.231256$28.560877|77.231066$28.56154|77.230979$28.561895|77.231141$28.562254|77.230363$28.562874|77.228948$28.563081|77.228477$28.563377|77.227801$28.563269|77.227589$28.563478|77.227399$28.563565|77.227283$28.564525|77.224997$28.564815|77.224312$28.564827|77.224284$28.564441|77.224069$28.564275|77.223981$28.563897|77.223919$28.563211|77.223555$28.562788|77.223312$28.562583|77.223192$28.562223|77.222981$28.561837|77.222605$28.561175|77.22209$28.560751|77.22165$28.560386|77.221168$28.561018|77.22056$28.561508|77.220098"
},

We can split the Coordinates string into a usable array with String.split and then display it in a map:
//for the demo
var defaultCoords = [28.561508, 77.220098];
//set up our map
var map = L.map('map').setView(defaultCoords, 12);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{}).addTo(map);
var sampleData = {
"Locality": "Andrews Ganj",
"Loc_Id": 1006613,
"City": "New Delhi",
"City_Id": 10397,
"State": "Delhi",
"HH": 1713,
"T_Pop": 7418,
"T_mPop": 3842,
"T_fPop": 3576,
"CGT10L": 20.26,
"C5_10L": 31.23,
"C1o5_5L": 36.37,
"CLT1o5L": 12.14,
"Coordinates": "28.561508|77.220098$28.561776|77.220469$28.562004|77.220674$28.561748|77.221049$28.561635|77.221411$28.562657|77.221943$28.562881|77.221555$28.562955|77.221624$28.563224|77.221846$28.564101|77.222571$28.564359|77.222735$28.564582|77.222899$28.565257|77.22327$28.565302|77.223305$28.565317|77.223356$28.56528|77.22352$28.565568|77.223684$28.565617|77.223663$28.565647|77.223663$28.565681|77.223667$28.565886|77.223844$28.565997|77.22403$28.566084|77.224073$28.566611|77.22444$28.56707|77.224663$28.567374|77.224804$28.567752|77.224983$28.567935|77.22501$28.567964|77.225012$28.56778|77.22547$28.567577|77.225968$28.567507|77.226139$28.566662|77.228219$28.566539|77.228578$28.566479|77.228722$28.566147|77.229518$28.56609|77.229666$28.565992|77.229919$28.565964|77.229999$28.5659|77.230175$28.565791|77.230598$28.565746|77.230792$28.5657|77.231073$28.565646|77.2317$28.565643|77.231748$28.565602|77.232306$28.565532|77.233377$28.565492|77.23383$28.565472|77.23409$28.565177|77.233967$28.564747|77.23376$28.56397|77.233318$28.563079|77.232797$28.562897|77.232657$28.560578|77.231256$28.560877|77.231066$28.56154|77.230979$28.561895|77.231141$28.562254|77.230363$28.562874|77.228948$28.563081|77.228477$28.563377|77.227801$28.563269|77.227589$28.563478|77.227399$28.563565|77.227283$28.564525|77.224997$28.564815|77.224312$28.564827|77.224284$28.564441|77.224069$28.564275|77.223981$28.563897|77.223919$28.563211|77.223555$28.562788|77.223312$28.562583|77.223192$28.562223|77.222981$28.561837|77.222605$28.561175|77.22209$28.560751|77.22165$28.560386|77.221168$28.561018|77.22056$28.561508|77.220098"
};
//first take the coords string and split into an array by the $
var coords = sampleData.Coordinates.split('$')
//next, take that array of strings that looks like' 28.561508|77.220098' and split again by the |
coords = coords.map(function (pair) {
return pair.split('|');
});
//show it on a map.
var polygon = L.polygon(coords, { color: 'red' }).addTo(map);
// zoom the map to the polyline
map.fitBounds(polygon.getBounds());

Related

In Mapbox GL JS, can you pass coordinates to an external GeoJSON data source?

Can you pass coordinate values as variables when trying to retreive an external GeoJSON data source? Ideally I'd like to pass something like this, but it doesn't work for me.
map.addSource('geojsonpoints', {
type: "geojson",
data: 'http://myexample.com/pins?lat={lat}&lon={long}'
});
I am able to pass Z, X, Y coordinates if I use Map Vector Tiles (mvt) as a source. i.e. This works:
map.addSource('mapvectortiles', {
'type': 'vector',
'tiles': ['http://myexample.com/{z}/{x}/{y}'],
But I haven't figured out how to do it for a GeoJSON source. Anyone have any ideas if it is possible in n Mapbox GL JS?
FYI, I am able to generate the URL using the method below, but the problem is it doesn't refresh when I move the map, unlike vector tiles.
var lng = map.getCenter().lng
var lat = map.getCenter().lat
var url = 'http://myexample.com/pins?lat='+lat+'&lon='+lng
map.addSource('EPC', {
type: "geojson",
data: url
});
I use GeoJSON to draw Tiles on the map
this is a sample GeoJSON:
{ "type": "FeatureCollection",
"features": [
{ "type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[4.342254780676343, 50.89533552689166],
[4.342254780676343, 50.89443721160754],
[4.340830581474948, 50.89443721160754],
[4.340830581474948, 50.89533552689166],
[4.342254780676343, 50.89533552689166]
]
]
},
"properties": {}
}
]
}
after all you have to add the source and add the layer
add Source:
const sourceJson: GeoJSONSourceRaw = {
type: 'geojson',
data: data as FeatureCollection
};
map.addSource(sourceId, sourceJson)
data is your json file
add Layer:
const layer: FillLayer = {
id: sourceId,
source: sourceId,
type: 'fill',
paint: {
'fill-color': color,
'fill-opacity': opacity
}
}
this.map.addLayer(layer);
There are two parts to your question:
Update the data source when the map is moved
Use the map's extent as part of the GeoJSON source's URL.
You have part 2 under control, so:
Update the data source when the map is moved
Use map.on('moveend', ...
Use map.getSource(...).setData(...)

Add Layer Groups and Markers in a loop ( from json)

I just started working with Leaflet. I want to create a map for a game, so this is a map created with L.CRS.Simple.
I have been able to set the map image, and add marker manually.
Now, I want to create markers and layers groups dynamicly from a json file that I generate in PHP from a sqlite database.
My json is this one for now : https://grounded.dubebenjamin.com/api/markers.json
My json is a list of type(layergroup) inside which I have put another object containing all the markers for the type(layergroup) :
Structure :
{
"landmarks": {
"id": 1,
"slug": "landmark",
"type": "Landmarks",
"markers": [
{"id": 1, "title": "Title of marker 1 of layergroup1"},
{"id": 2, "title": "Title of marker 2 of layergroup1"}
]
},
"science": {
"id": 2,
"slug": "science",
"type": "Science Points",
"markers": [
{"id": 1, "title": "Title of marker 1 of layergroup2"}
]
}
}
= Where landmarks and science are layergroup.
From this json, my plan was to have a first loop, where for each type I want to create a layer group, then create the markers for this layer group and assign the markers to the layer groups.
Manually, I understand the usage of L.marker and L.layerGroup, but where I am stuck, is how to do that in a loop, and defined the layoutgroup name from the json data.
From now, I have just been able to create the marker, but not the layer group. You can see my progress here: https://grounded.dubebenjamin.com/
If you need more precision, just ask me.
Use this code:
var layergroups = {};
fetch('https://grounded.dubebenjamin.com/api/markers.json').then(response => response.json())
.then((data)=>{
layergroups = {};
for(type in data){
var lg = L.layerGroup().addTo(map)
layergroups[type] = lg;
if(data[type].markers){
var markers = data[type].markers;
markers.forEach((marker)=>{
L.marker([marker.x,marker.y]).bindPopup(marker.desc).addTo(lg);
})
}
}
})
First fetch the data from the server, then loop through the layergroups and add them to the map and then to the Object/Array.
Then you create the markers and add them to the layergroup.
You can get the layergroups over the Object layergroups but keep in mind that the request is async.

Leaflet with markers and line

I'm using leafletjs with geojson, but i can't draw a polyline with the markers at the same time, so my solution is draw first a polyline then add the markers.
I don't think it's a good ways, so is there any other solution?
there is my code
function DrawLine(mymap,topo){
var line={
"type": "Feature",
"geometry": {
"type": "LineString",
"coordinates" : topo.pointsForJson
// topo.pointsForJson is my data source like : [[5.58611,43.296665], [5.614466,43.190604], [5.565922,43.254726], [5.376992,43.302967]]
},
"properties": {
"ID": topo['OMS_IDTOPO'],
"color" : "blue"
}
};
var points=[];
for(var i in topo.pointsForJson){
var point = {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates" : topo.pointsForJson[i]
}
};
points.push(point);
}
//add markers
L.geoJSON(points).addTo(mymap);
// add polyline
var polyline = L.geoJSON(line,{
style:function (feature) {
return {color: feature.properties.color}
}
}).bindPopup(function (layer) {
return layer.feature.properties.ID;
}).addTo(mymap);
mymap.fitBounds(polyline.getBounds());
}
Thanks a lot
You really do not need to build a GeoJSON object first at runtime in order to display something on your Leaflet map.
Simply loop through your coordinates and build a marker at each pair.
Then build a polyline out of the coordinates array.
You will need to revert your coordinates in the process, since they are recorded as Longitude / Latitude (compliant with GeoJSON format), whereas Leaflet expects Latitude / Longitude when directly building Markers and Polylines (instead of using L.geoJSON factory).
var pointsForJson = [
[5.58611, 43.296665],
[5.614466, 43.190604],
[5.565922, 43.254726],
[5.376992, 43.302967]
];
var map = L.map('map');
pointsForJson.forEach(function(lngLat) {
L.marker(lngLatToLatLng(lngLat)).addTo(map);
});
var polyline = L.polyline(lngLatArrayToLatLng(pointsForJson)).addTo(map);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
map.fitBounds(polyline.getBounds());
function lngLatArrayToLatLng(lngLatArray) {
return lngLatArray.map(lngLatToLatLng);
}
function lngLatToLatLng(lngLat) {
return [lngLat[1], lngLat[0]];
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.2.0/dist/leaflet.css">
<script src="https://unpkg.com/leaflet#1.2.0/dist/leaflet-src.js"></script>
<div id="map" style="height: 200px"></div>

Show geojson featureCollection with Leaflet

with QGIS I´ve exported a polygon layer as geojson which I´d like to publish with leaflet. This is how the geojson looks like [exluded due to SO character limits]:
https://gist.github.com/t-book/88806d12d7f05024b147715be82e6844
This is what I´ve tried:
Wrapped geojson as var:
var states = [{
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:EPSG::31468" } },
"features": [
{ "type": "Feature", "properties": ...
}];
Added as new Layer:
L.geoJSON(states, {
style: function(feature) {
switch (feature.properties.party) {
case 'Euerbach': return {color: "#ff0000"};
case 'Werneck': return {color: "#0000ff"};
}
}
}).addTo(map);
Unfortunately nothing is rendered. How do I correctly add this geojson featureCollection to my map?
The problem is that your data is projected - Leaflet is expecting your data to be unprojected (composed of long/lat pairs, or "projected" in WGS84/EPSG 4326). There are a few solutions, two come to mind here:
In QGIS, export your data so that it is composed of long/lat coordinate pairs
Use proj4.js to reproject your coordinates when displaying the geojson.
For number two, you'll need to set the coordsToLatLng option when adding the geojson as a layer:
var geojson = L.geoJSON(states, {
coordsToLatLng: function (p) {
// return get lat/lng point here.
})
The body of this function will take a coordinate in the geojson's coordinate reference system (CRS) and return it in WGS84 using proj4.
Also, coordsToLatLng function expects you to return lat/long pairs. As your geojson and proj4 represent data that is [x,y], we need to swap our values before returning the new point.
This could look like:
var geojson = L.geoJSON(states, {
coordsToLatLng: function (p) {
p = proj4(fromProjection,toProjection,p); // reproject each point
p = [p[1],p[0]] // swap the values
return p; // return the lat/lng pair
}
}).addTo(map);
Of course, we need to define our CRSs. I looked up your CRS (it is specified in the geojson itself) on spatialreference.org and used the provided description for that CRS and EPSG4326 (WGS84) to set my fromProjection and toPojection:
var fromProjection = '+proj=tmerc +lat_0=0 +lon_0=12 +k=1 +x_0=4500000 +y_0=0 +ellps=bessel +datum=potsdam +units=m +no_defs ';
var toProjection = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs ";
Altogether that gives us something like this.
Keep in mind, that if you have large files, reprojecting them in javascript will take longer than if you export them in the proper CRS.

add image to rect polygon in leaflet

Here is the working JSFiddle
what I need is to add image to rect polygon and also don't want it to repeat itself as when zooming in or out and want it to be fixed. any suggestions will be appreciated and if there is any other way to achieve so.
If it can be placed in geojson that will be great as I have to give some properties to each polygon. And create all the rect polygon dynamically.
code is below
var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
osmAttrib = '© OpenStreetMap contributors',
osm = L.tileLayer(osmUrl, {maxZoom: 18, attribution: osmAttrib});
var map = new L.Map('map', {layers: [osm], center: new L.LatLng(24, 121), zoom: 9});
var states = [{
"type": "Feature",
"properties": {"party": "Republican"},
"geometry": {
"type": "Polygon",
"coordinates": [[
[-104.05, 48.99],
[-96.58, 45.94],
[-104.03, 45.94],
[-104.05, 48.99]
]]
}
}, {
"type": "Feature",
"properties": {"party": "Democrat"},
"geometry": {
"type": "Polygon",
"coordinates": [[
[-109.05, 41.00],
[-102.03, 36.99],
[-109.04, 36.99],
[-109.05, 41.00]
]]
}
}];
var poly1 = [
[24, 121],
[24.5, 121],
[24.5, 121.9],
[24, 121.9]
];
L.polygon(poly1, {fill:'url(http://i.imgur.com/ktPFJKC.jpg)'}).addTo(map);
L.geoJson(states, {
style: function(feature) {
switch (feature.properties.party) {
case 'Republican': return {color:'#ff0000'};
case 'Democrat': return {color: "#0000ff"};
}
}
}).addTo(map);
The best thing to do here is use an ImageOverlay, which is designed for precisely this case. You can use the coordinates of your polygon object to create both the image overlay and an invisible GeoJSON layer that sits on top of it. If you are dynamically creating the polygon objects in the same format as your example poly1, then you can reference the indices of the corner points like this when creating the image overlay:
var imageUrl = 'http://i.imgur.com/ktPFJKC.jpg';
var imageBounds = L.latLngBounds([
poly1[0],
poly1[2]
]);
var imageLayer = L.imageOverlay(imageUrl, imageBounds).addTo(map).bringToBack();
The .bringToBack may be unnecessary if you always create the image before the GeoJSON polygon, but it does ensure that the image overlay doesn't interfere with other layer interactions. You can create a temporary GeoJSON object from the polygon object using .toGeoJSON, and set any GeoJSON properties you like:
var polyTemp = L.polygon(poly1).toGeoJSON();
polyTemp.properties.name = 'pineapple';
Then create an invisible L.GeoJSON layer to handle the interactions:
var boxOptions = {fillOpacity:0, opacity:0, onEachFeature: onEachBox};
var imageBox = L.geoJson(polyTemp, boxOptions).addTo(map);
function onEachBox(feature, layer) {
layer.bindPopup("Hello, I'm a " + polyTemp.properties.name);
}
The onEachBox function here is of course just an example to illustrate that you can access the GeoJSON properties. Here is an updated fiddle:
https://jsfiddle.net/17Ld98fv/