I'm working with leaflets and I've noticed that many examples use a separate js file where a variable is set to a JSON stream.
How would I be able to modify the following example so that it can read off a json file with the geojson and not have the variable declaration in the javascript?
The code looks like this:
<script type="text/javascript">
var geoJsonData = {
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "id":"1", "properties": { "address": "2" }, "geometry": { "type": "Point", "coordinates": [175.2209316333,-37.8210922667 ] } },
{ "type": "Feature", "id":"2", "properties": { "address": "151" }, "geometry": { "type": "Point", "coordinates": [175.2238417833,-37.80975435 ] } },
{ "type": "Feature", "id":"3", "properties": { "address": "21" }, "geometry": { "type": "Point", "coordinates": [175.2169955667,-37.818193 ] } },
{ "type": "Feature", "id":"4", "properties": { "address": "14" }, "geometry": { "type": "Point", "coordinates": [175.2240856667,-37.8216963 ] } },
{ "type": "Feature", "id":"5", "properties": { "address": "38B" }, "geometry": { "type": "Point", "coordinates": [175.2196982333,-37.8188702167 ] } },
{ "type": "Feature", "id":"6", "properties": { "address": "38" }, "geometry": { "type": "Point", "coordinates": [175.2209942 ,-37.8192782833 ] } }
]
};
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: '© OpenStreetMap contributors'
});
var map = L.map('map')
.addLayer(tiles);
var markers = L.markerClusterGroup();
var geoJsonLayer = L.geoJson(geoJsonData, {
onEachFeature: function (feature, layer) {
layer.bindPopup(feature.properties.address);
}
});
markers.addLayer(geoJsonLayer);
map.addLayer(markers);
map.fitBounds(markers.getBounds());
</script>
I know it can be done with $.getJSON, but I would prefer using L.geoJson, if possible.
To read JSON data from a file you can use the fetch function (read more).
Here is an example:
fetch('http://example.com/movies.json')
.then(function(response) {
return response.json();
})
.then(function(myJson) {
// Do something with the JSON data
console.table(myJson);
});
In your case:
function doSomething(geoJsonData) {
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: '© OpenStreetMap contributors'
});
var map = L.map('map')
.addLayer(tiles);
var markers = L.markerClusterGroup();
var geoJsonLayer = L.geoJson(geoJsonData, {
onEachFeature: function (feature, layer) {
layer.bindPopup(feature.properties.address);
}
});
markers.addLayer(geoJsonLayer);
map.addLayer(markers);
map.fitBounds(markers.getBounds());
}
fetch('http://myserver.com/myfile.json')
.then(function(response) {
return response.json();
})
.then(doSomething)
.catch(function(err) {
// In case of error, display the error message
console.error(err);
});
Notice that I put your code inside a callback function, as the fetch function is asynchronous.
You can store the geoJSON variable in a separate .js file and import it into the main logic .js file. Try pasting your var geoJsonData in a file called geoJsonData.js, then at the bottom of that file add "module.exports = geoJsonData;". Then on your logic file (ie scripts.js), you can import the variable as is by adding "var geoJsonData = require("./geoJsonData.js"); at the top. Then your call to add the points to the map would be
function geoJsonMarkers() {
$.getJSON(geoJsonData, function (data) {
// this adds the GeoJSON layer to the map once the file is loaded
L.geoJson(data).addTo(mymap);
}
}
I know it can be done with $.getJSON, but I would prefer using L.geoJson, if possible.
You seem to not realize that these 2 functions provide different steps of your workflow, as illustrated by the 2 other answers.
You may be misled by other libraries that provide utility functions which perform both steps for you.
jQuery's $.getJSON is to fetch / retrieve data from your server.
Once you have the resulting JS object, you feed it into Leaflet's L.geoJSON factory to have it converted into Leaflet layers.
Related
I am totally stuck with my WGS 84 / EPSG:3857 coordinates and display them on Leaflet.
I have Geojson with coordinates.
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
"6690861",
"682187"
]
},
"properties": {
"id": "908",
"message": "105",
"date": "",
"place": "",
"shape": ""
}
}
Now i want it display on Leaflet. But nothing show up. I search already 5 hours and find something about Proj4. Also no errors showing up.
My script code:
var map = L.map('map').setView([52.2129919, 5.2793703], 8);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {attribution: 'Map data © OpenStreetMap'}).addTo(map);
// GeoJSON layer (UTM15)
proj4.defs('EPSG:3857');
async function addGeoJson() {
const response = await fetch("geojs.php");
const data = await response.json();
L.geoJson(data).addTo(map);
var layerGroup = L.geoJSON(data, {
onEachFeature: function (feature, layer) {
layer.bindPopup('<h1>'+feature.properties.message+'</h1><p>Datum: '+feature.properties.date+'</p>');
}
}).addTo(map);
}
addGeoJson();
It's for my the first time i work with this coordinates. With lat/long coordinates was don't have problems. And just started with javascript.
Kind regards,
I might be a bit late, but following the documentation of Proj4, I would say that you need to add the crs to your geojson, like so :
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
"6690861",
"682187"
]
},
"properties": {
"id": "908",
"message": "105",
"date": "",
"place": "",
"shape": ""
},
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:EPSG::3857"
}
}
}
Also, I think it's
L.Proj.geoJson(data).addTo(map);
instead of
L.geoJson(data).addTo(map);
I tried L.geoJson on my code and it didn't show anything contrary to L.Proj.geoJson so it might be your problem here.
I've created a map using mapbox and plotted multiple custom points that you can interact with. I am also using Wordpress and want to use advanced custom fields to create each point so they can easily be managed from a non-technical person. The fields are all setup, but I am having trouble passing them into the javascript in my php template.
I've tried using a loop but I can't use the loop inside javascript. Here is my Mapbox code that I am using to plot the points and want to use advanced custom fields with:
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/coptmarketing/cjvi7hc4602dk1cpgqul6mz0b',
center: [-76.615573, 39.285685],
zoom: 16 // starting zoom
});
var geojson = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"title": "Shake Shack",
"id": "shake-shack"
},
"geometry": {
"type": "Point",
"coordinates": [-76.609844, 39.286894]
}
},
{
"type": "Feature",
"properties": {
"title": "Starbucks",
"id": "starbucks"
},
"geometry": {
"type": "Point",
"coordinates": [-76.619071, 39.286649]
}
}
]
};
I've stored the data in a JSON array:
[{"title":"Shake Shack","slug":"shake-shack","latitude":"-76.609844","longitude":"39.286894"},{"title":"Starbucks","slug":"starbucks","latitude":"-76.619071","longitude":"39.286649"}]
How do I insert this into the geoJSON?
Figured it out:
First I created a plugin that stored the custom post data in a JSON array and stored it on the server. This also updated every time I updated, saved or deleted a post. Here is the example JSON:
data = {"placeList": [{"title":"Shake Shack","slug":"shake-shack","latitude":"-76.609844","longitude":"39.286894"},{"title":"Starbucks","slug":"starbucks","latitude":"-76.619071","longitude":"39.286649"}]}
Then in the php file, I called the .json file and in my javascript, inserted the array into the GeoJSON:
var placeJson = data;
var geojson = {
type: "FeatureCollection",
features: [],
};
for (i = 0; i < placeJson.placeList.length; i++) {
geojson.features.push({
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [placeJson.placeList[i].latitude, placeJson.placeList[i].longitude]
},
"properties": {
"id": placeJson.placeList[i].slug,
"title": placeJson.placeList[i].title
}
});
}
Created some markers using an array of GeoJSON data:
$.getJSON("GetLocationsServlet", function(data) {
L.geoJSON(data, {
onEachFeature: onEachFeature
}).addTo(mymap);
});
The GeoJSON data is like this:
[
{ "type": "Feature", "properties": { "name": "Riverway Sport Complex", "amenity": "GYM", "popupContent": "Riverway Sport Complex" }, "geometry": { "type": "Point", "coordinates": [-123.002846, 49.205036] },"id" : "1"} ,
{ "type": "Feature", "properties": { "name": "Imperial#Patterson", "amenity": "GYM", "popupContent": "Imperial#Patterson" }, "geometry": { "type": "Point", "coordinates": [-123.01249, 49.22193] },"id" : "2"}
]
The markers were successfully created and showed on the map. At some point later, I needed to iterate through all Markers, so I used eachLayer function:
var mymap = L.map('mapid').locate({setView: true, maxZoom: 15});
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png? '
access_token=..., {
maxZoom: 25,
attribution:
id: 'mapbox.streets',
}).addTo(mymap);
.......
$.getJSON( L.geoJSON()... )
.......
mymap.eachLayer(function(layer) {
alert (layer.options.id);
// Above alert successfully print out the tileLayer ID
if (layer instanceof L.Marker) {
alert("Marker [" + layer.options.title + "]");
}
});
However, it only looped through the main map tileLayer and stopped.
Am I using the eachLayer method correctly? Marker is also a subclass of Layer?
Thanks,
I am trying to show clusters using markerclustergroups with Polygons. Right now the polygons are shown but the clusters aren't. I have been trying to use center of mass for the polygons because it seems like markerclustergroup doesn't like polygons but that doesn't really work since the animation of markerclustergroup will be set on the centroids and not the actual polygon.
My polygons all vary in amount of coordinates. Some have +10 sets others have 3.
How would I use markerclustergroup for polygons?
Below my code can be seen:
// Create variable to hold map element, give initial settings to map
var map = L.map('map', {
center: [23.70489, 43.90137],
zoom: 5
});
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
}).addTo(map);
var ojStyle = {
"color": "#ff7800",
"weight": 5,
"opacity": 0.65
};
// Hardcoded polygons as GeoJSON
var polygons = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[37.99896240234376, 21.55017532555692],
[39.39422607421876, 21.476073444092435],
[38.88336181640626, 22.56582956966297],
[38.023681640625, 22.611475436593366],
[37.43591308593751, 21.99908185836153],
[37.28485107421876, 21.624239377938288],
[37.28485107421876, 21.624239377938288],
[37.99896240234376, 21.55017532555692]
]
]
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[38.50708007812501, 21.453068633086783],
[39.20745849609376, 21.37124437061832],
[39.10858154296876, 20.876776727727016],
[38.80920410156251, 20.912700155617568],
[38.49884033203126, 20.94604992010052],
[38.50708007812501, 21.453068633086783]
]
]
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[50.57830810546875, 25.980268007469803],
[50.77606201171876, 25.956809920555312],
[50.780181884765625, 25.69970044378398],
[50.56457519531251, 25.822144306879686],
[50.56182861328126, 25.945696562830516],
[50.57830810546875, 25.980268007469803]
]
]
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[54.37408447265626, 24.51963836811676],
[54.29443359375001, 24.40963901896311],
[54.25872802734375, 24.449649897759667],
[54.32739257812501, 24.539627918861232],
[54.37133789062501, 24.559614286039903],
[54.37408447265626, 24.51963836811676]
]
]
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[54.40155029296876, 24.463400705082282],
[54.41940307617188, 24.489648077028683],
[54.45785522460938, 24.462150693715266],
[54.43450927734376, 24.43839812102505],
[54.40155029296876, 24.463400705082282]
]
]
}
}]
}
var polygonArray = []
for (i = 0; i < polygons.features.length; i++) {
polygonArray.push(polygons.features[i]);
}
var markers = L.markerClusterGroup().addTo(map);
var geoJsonLayer = L.geoJson(polygonArray);
markers.addLayer(geoJsonLayer);
map.fitBounds(markers.getBounds());
http://js.do/code/165930 - Shows how clustering doesn't work for the polygons
I am looking for a solution like this: http://jsfiddle.net/ve2huzxw/237/
You can do it very much like in this GIS post: Is it possible to cluster polygons in Leaflet?
// Compute a polygon "center", use your favourite algorithm (centroid, etc.)
L.Polygon.addInitHook(function() {
this._latlng = this._bounds.getCenter();
});
// Provide getLatLng and setLatLng methods for
// Leaflet.markercluster to be able to cluster polygons.
L.Polygon.include({
getLatLng: function() {
return this._latlng;
},
setLatLng: function() {} // Dummy method.
});
Updated live example: http://js.do/code/166021
i am implementing real time markers using leaflet.js version 0.7.7 and leaflet-realtime - v1.3.0. its working fine. But on map load i need to open popup for all markers.
i used .openPopup() and openOn() but not working for me.
My fiddle is:
https://jsfiddle.net/chk1/hmyxb6ur/
var map = L.map('map').setView([48.517,18.255], 5);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
var shipLayer = L.layerGroup();
var ships = L.icon({
iconUrl: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/97/Emoji_u1f6a2.svg/30px-Emoji_u1f6a2.svg.png',
iconSize: [30, 30]
});
var realtime = L.realtime(
/*
I'm providing a function to simulate a GeoJSON service,
instead of an URL
{
url: 'jsonServlet/ships.json',
crossOrigin: true,
type: 'json'
}*/
function(success, error){
var ship = mockShip();
success(ship);
}, {
interval: 5 * 1000,
getFeatureId: function(featureData){
return featureData.properties.mmsi;
},
pointToLayer: function (feature, latlng) {
marker = L.marker(latlng, {icon: ships});
marker.bindPopup('mmsi: ' + feature.properties.mmsi +
'<br/> course:' + feature.properties.hdg+
'<br/> speed:' + feature.properties.sog);
marker.addTo(shipLayer);
return marker;
}
}).addTo(map);
//controlLayers.addOverlay(geojson, 'Ships');
realtime.on('update', function() {
map.fitBounds(realtime.getBounds(), {maxZoom: 5});
});
function mockShip() {
return {
"type": "FeatureCollection",
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
},
"features": [
{
"geometry": {
"coordinates": [
48.517+Math.sin((new Date).getTime())*2,
18.255
],
"type": "Point"
},
"type": "Feature",
"properties": {
"geometry/coordinates/longitude": "48.517708",
"geometry/type": "Point",
"mmsi": "512131345",
"geometry/coordinates/latitude": "18.255447",
"hdg": "108",
"cog": "108",
"sog": "30.0",
"type": "Feature"
}
},
{
"geometry": {
"coordinates": [
48.415,
18.151+Math.sin((new Date).getTime())*2
],
"type": "Point"
},
"type": "Feature",
"properties": {
"geometry/coordinates/longitude": "48.417708",
"geometry/type": "Point",
"mmsi": "612131346",
"geometry/coordinates/latitude": "18.155447",
"hdg": "108",
"cog": "108",
"sog": "30.0",
"type": "Feature"
}
}
]
};
}
I'll quote the Leaflet API documentation:
Use Map#openPopup to open popups while making sure that only one popup is open at one time (recommended for usability), or use Map#addLayer to open as many as you want.