When I use GeoJSON inside the HTML it works, but when I try to load externally it doesn't.
My HTML file and GeoJSON file are in the same folder in site.
I try to open picture popups with markers.
Thanks a lot!
L.mapbox.accessToken = 'lalalalala';
var southWest = L.latLng(40.875557, 29.235992),
northEast = L.latLng(41.277226, 28.749847),
bounds = L.latLngBounds(southWest, northEast);
var map = L.mapbox.map('map', 'mapbox.light', {
maxBounds: bounds,
maxZoom: 19,
minZoom: 11
});
var myLayer = L.mapbox.featureLayer()
.loadURL('http://terkedilmisarabalar.mudurlugu.org/geojson/terkedilmisarabalar.geojson')
.on('ready', function() {
myLayer.eachLayer(function(layer) {
map.fitBounds(myLayer.getBounds());
layer.bindPopup(layer.features.properties.name);
});
})
.addTo(map);
myLayer.setGeoJSON(geojson);
myLayer.on('onclick', function(e) {
e.layer.openPopup();
});
myLayer.on('onrelease', function(e) {
e.layer.closePopup();
});
Here is an example GeoJSON file:
{
type: 'FeatureCollection',
features: [
{
"type": "Feature",
"properties": {
"name": "Acıbadem Cd. No:117",
"description": "<img src=\"https://lh3.googleusercontent.com/DkEl65k9kZAtvPdf9HuE22aIAJKUKBDtiL0m5vZBRqn9nVsgcQIQYdi03gt5yhOKcrEvTQpctu_xnLVfhzzt6Tr3fGtsxuIJSqPrf7R9p-0faSL-YRxTzyn44B8KVB8\" height=\"200\" width=\"auto\" /><br><br>",
"gx_media_links": "https://lh6.googleusercontent.com/fmIjm4ynkTWSkmzcOfoMCoVgnm6h9pQ8KINgHqhjx-ZNQMrT05NqsZo2Lv5d6FwFFakmqOzl_ruRKvu34jbC96U3nKaxlu0sul6W4qXU1ily4PNbLCQTsR2BGKOxervb"
},
"geometry": {
"coordinates": [
29.045881,
41.005992,
0
],
"type": "Point"
}
}
Related
I have a variable list of geoJson layers (that I'm naming as sectors) on my map. I need to center the view to fit all geometries.
I'm using Vue2Leaflet (v2.5.2) and Leaflet (v1.6.0).
Each geoJson object is like this:
{
"type": "FeatureCollection",
"features":
[
{
"type": "Feature",
"properties":
{
"id": "4200051",
"name": "Abdon Batista",
"description": "Abdon Batista"
},
"geometry":
{
"type": "Polygon",
"coordinates": [[[-51.0378352721, -27.5044338231], ...]]
}
}
]
}
And it's stored directly in geoSectors: [ geoJson1, geoJson2, ... ].
Here's the code:
<template>
<div class="home">
<l-map ref="mapControl" :zoom="zoom" :center="center" :options="mapOptions">
<l-tile-layer :url="url" :attribution="attribution"/>
<l-control-zoom position="bottomright"/>
<!-- Sectors-->
<l-geo-json v-for="sector in geoSectors" :key="sector.id" :geojson="sector" :options="options"/>
</l-map>
</div>
</template>
<script>
import { latLng, latLngBounds } from "leaflet";
export default {
data() {
return {
zoom: 6,
center: latLng(-25.005973, -50.537109),
url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
attribution: '© OpenStreetMap contributors',
mapOptions: {
zoomSnap: 0.1,
zoomControl: false
},
geoSectors: []
}
},
mounted(){
let list = [];
//Gets the list from a file.
this.geoSectors = list;
var bounds = this.geoSectors; //HERE: Get bounds of the list.
this.$refs.mapControl.mapObject.fitBounds(bounds);
},
computed: {
options() {
return {
onEachFeature: this.onEachFeatureFunction
};
},
onEachFeatureFunction() {
return (feature, layer) => {
layer.on('click', function (e) {
//Shows sector details.
});
//Tooltips.
layer.bindTooltip("<div><p>Sector: "feature.properties.name +"</p></div>", {
permanent: false,
sticky: true
});
};
}
},
}
</script>
How can I fit the map view to display all geoJson layers, with the maximum zoom level possible?
I managed to solve it. Here's the code:
//You need to import featureGroup from leaflet:
import { latLng, featureGroup } from "leaflet";
//After building your geoJson layers, just call this:
this.$nextTick().then(() => {
var group = new featureGroup();
this.$refs.mapControl.mapObject.eachLayer(function(layer) {
if (layer.feature != undefined)
group.addLayer(layer);
});
this.$refs.mapControl.mapObject.fitBounds(group.getBounds(), { padding: [20, 20] });
});
I have a .js file with coordinates for internships:
var internships = [{
"features": [
{"type":"Feature","properties":{"category":"entretient","Name":"green"},"geometry":{"type":"Point","coordinates":[50.807149, 3.162994]}},
{"type":"Feature","properties":{"category":"securité","Name":"blue"},"geometry":{"type":"Point","coordinates":[50.334421, 3.290146]}},
{"type":"Feature","properties":{"category":"secretaria","Name":"red"},"geometry":{"type":"Point","coordinates":[50.744787, 2.256216]}}
]
}];
I've found this bit of code allowing me to create layers depending on a property and here what my JS looks like:
$.getScript("CoordinatesPdC.js");
function mapLoad() {
var sécuritéLayer = new L.LayerGroup();
var secrétariatLayer = new L.LayerGroup();
var entretientLayer = new L.LayerGroup();
var map = L.map('map').setView([50.2910, 2.7775], 8);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, ' +
'CC-BY-SA, '
}).addTo(map);
var marker = L.marker([50.2910, 2.7775]).addTo(map);
var entretientLayer = L.geoJson(internships, {
filter: function (feature, layer) {
return (feature.properties.category === "entretient");
}
}).addTo(map);
var sécuritéLayer = L.geoJson(internships, {
filter: function (feature, layer) {
return (feature.properties.category === "sécurité");
}
}).addTo(map);
var secrétariatLayer = L.geoJson(internships, {
filter: function (feature, layer) {
return (feature.properties.category === "secrétariat");
}
}).addTo(map);
}
window.onload = mapLoad;
But now I have to create the markes assigned to these layers, how can I achieve that?
Your markers are already assigned to each later. In your example, you create a layer (with all of its markers) and immediately add it to the map using .addTo(map); Here's the code responsible for it.
var sécurité = L.geoJson(internships, {
filter: function (feature, layer) {
return (feature.properties.category === "sécurité");
}
}).addTo(map);
Now, you probably want to only display a certain layer based on user input. If so, I suggest adding the related layer to the map on a click event. Then when the event is triggered a layer is added. Here's the code for doing that. sécurité.addTo(map)
A layer is removed using map.removeLayer(sécurité);
Below is a working example based on your initial code. (I did write it in jQuery as my vanilla JavaScript could be better) You can also view it on jsFiddle here.
I left some comments in the code to explain what each part does. I hope that helps you with your understanding.
var internships = [{
"features": [{
"type": "Feature",
"properties": {
"category": "entretient",
"Name": "green"
},
"geometry": {
"type": "Point",
"coordinates": [3.162994, 50.807149]
}
},
{
"type": "Feature",
"properties": {
"category": "securité",
"Name": "blue"
},
"geometry": {
"type": "Point",
"coordinates": [3.290146, 50.334421]
}
},
{
"type": "Feature",
"properties": {
"category": "secretaria",
"Name": "red"
},
"geometry": {
"type": "Point",
"coordinates": [2.256216, 50.744787]
}
}
]
}];
$(document).ready(function() {
// Create an object to keep track of active layers and each layer with its markers
const layers = {
active: [],
entretientLayer: new L.LayerGroup(),
sécuritéLayer: new L.LayerGroup(),
secrétariatLayer: new L.LayerGroup(),
};
// create the map
var map = L.map('map').setView([50.8010, 3.1675], 6,5);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, ' +
'CC-BY-SA, '
}).addTo(map);
// based on the category assign a marker to the layer
layers.entretientLayer = L.geoJson(internships, {
filter: function(feature, layer) {
return (feature.properties.category === "entretient");
}
})
layers.sécuritéLayer = L.geoJson(internships, {
filter: function(feature, layer) {
return (feature.properties.category === "securité");
}
})
layers.secrétariatLayer = L.geoJson(internships, {
filter: function(feature, layer) {
return (feature.properties.category === "secretaria");
}
})
// register click event
$('button').on('click', function(e) {
const layerName = e.target.name;
// if a layer is already active, remove it from the map and the active array
if (layers.active.includes(layerName)) {
layers.active = layers.active.filter(layer => layer !== layerName);
map.removeLayer(layers[layerName]);
} else {
// add the layer to the map and to the active array
layers.active.push(layerName);
layers[layerName].addTo(map);
}
});
});
#map {
height: 140px;
width: 100%;
}
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.3/leaflet.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.3/leaflet.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.3/leaflet-src.js"></script>
<div class="button-group">
<button name="entretientLayer">entretient</button>
<button name="sécuritéLayer">sécurité</button>
<button name="secrétariatLayer">secrétariat</button>
</div>
<p></p>
<div id="map"></div>
UPDATE: updated leaflet.js to version 1.3.3.
The difference with the update is that each layer needs to be initialised using the new key word. Code is updated to reflect the change.
I have this simple Google map in a Web2py application.
I would like to apply something like a switch for choosing the feature icon and also setting an infoWindow from json text.
Someone knows how I can do it?
var map;
function initMap() {
map = new google.maps.Map(document.getElementById("events_map"), {
center: {lat: 45.070309, lng: 7.686580999999933},
zoom: 13,
mapTypeControl: false
});
var largeInfowindow = new google.maps.InfoWindow();
google.maps.event.addListener(map, 'idle', function() {
var ne = map.getBounds().getNorthEast();
var north = ne.lat();
var east = ne.lng();
var sw = map.getBounds().getSouthWest();
var south = sw.lat();
var west = sw.lng();
var queryString = '?east=' + east + '&west=' + west + '&south=' + south + '&north=' + north + '&zoom=8'
map.data.loadGeoJson('{{=URL('f_ajax', 'get_locations_g')}}' + queryString);
});
}
json data has a category field that can have 1, 2, 3, or 4 as value.
So with a switch I would like to set the icon in this way:
var icon;
switch (feature.properties.category) {
case '1':
icon = greenIcon;
break;
case '2':
icon = bluIcon;
break;
case '3':
icon = redIcon;
break;
case '4':
icon = blackIcon;
break;
}
But I don't know how.
For the infowindow, can I use this function and how for displaying the json field 'description'?
Thanks.
function populateInfoWindow(marker, infowindow) {
// Check to make sure the infowindow is not already opened on this marker.
if (infowindow.marker != marker) {
infowindow.marker = marker;
infowindow.setContent("<div><a href='" + marker.link + "'>" + marker.title + '</a></div>');
infowindow.open(map, marker);
// Make sure the marker property is cleared if the infowindow is closed.
infowindow.addListener('closeclick', function() {
infowindow.marker = null;
});
}
}
For the icon you have to use the setStyle-function.
A object with the icons should be the easiest approach here
map.data.setStyle(function(feature) {
return {
icon:({1:greenIcon,
2:redIcon,
3:blueIcon,
4:blackIcon})[feature.getProperty('category')]
};
});
The function for the InfoWindow may not be used, because there is no marker available in the click-handler, you have to set the options of the InfoWindow based on the clicked feature
map.data.addListener('click', function(event) {
largeInfowindow.setOptions({
map : map,
position: event.feature.getGeometry().get(),
content : '<strong>'+event.feature.getProperty('description')+'</strong>'
})
});
Demo:
function initMap() {
var greenIcon = 'http://maps.gstatic.com/mapfiles/markers2/icon_green.png',
redIcon = 'http://maps.gstatic.com/mapfiles/markers2/marker.png',
blueIcon = 'http://maps.gstatic.com/mapfiles/markers2/boost-marker-mapview.png',
blackIcon = 'http://maps.gstatic.com/mapfiles/markers2/drag_cross_67_16.png',
map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: {lat:52.41, lng: 9.74}
}),
largeInfowindow = new google.maps.InfoWindow({pixelOffset:new google.maps.Size(0,-30)});
map.data.setStyle(function(feature) {
return {
icon:({1:greenIcon,
2:redIcon,
3:blueIcon,
4:blackIcon})[feature.getProperty('category')]
};
});
map.data.addListener('click', function(event) {
largeInfowindow.setOptions({
map : map,
position: event.feature.getGeometry().get(),
content : '<strong>'+event.feature.getProperty('description')+'</strong>'
})
});
map.data.addGeoJson(json);
}
var json={
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {category:1,description:'Berlin'},
"geometry": {
"type": "Point",
"coordinates": [
13.392333984375,
52.53627304145948
]
}
},
{
"type": "Feature",
"properties": {category:2,description:'Hamburg'},
"geometry": {
"type": "Point",
"coordinates": [
10.008544921875,
53.57293832648609
]
}
},
{
"type": "Feature",
"properties": {category:3,description:'Cologne'},
"geometry": {
"type": "Point",
"coordinates": [
6.954345703125,
50.951506094481545
]
}
}
]
};
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
<script async defer
src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>
<div id="map"></div>
I'm triying to display on my map specific value ( data.geojson) of my geojson file with buttons. (for exemple to plot a map with only value "domaine":"violences ")
I am loocking for a way to rely my data ("domaine":"violences" or other)with a buttons on my map ?
Thanks so much in advance for your time.
my js:
<script type="text/javascript">
var map = L.map('map');
var terrainTiles = L.tileLayer('http://stamen-tiles-{s}.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}.{ext}', {
attribution: 'Map tiles by Stamen Design, CC BY 3.0 — Map data © OpenStreetMap',
subdomains: 'abcd',
minZoom: 0,
maxZoom: 20,
ext: 'png'
});
terrainTiles.addTo(map);
map.setView([46.5160000, 6.6328200], 10);
L.control.locate(location).addTo(map);
function addDataToMap(data, map) {
var dataLayer = L.geoJson(data, {
onEachFeature: function(feature, layer) {
var popupText = "<b>" + feature.properties.nom
+ "<br>"
+ "<small>" + feature.properties.localite
+ "<br>Rue: " + feature.properties.rue + + feature.properties.num
+ "<br>Téléphone: " + feature.properties.tel
+ "<br><a href= '" + feature.properties.url + "'>Internet</a>";
layer.bindPopup(popupText); }
});
dataLayer.addTo(map);
}
$.getJSON("data.geojson", function(data) { addDataToMap(data, map); });
</script>
</body>
</html>
the data.geojson
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [ 6.1200622,46.2106091 ]
},
"properties": {
"nom":"Centre d'entraînement aux méthodes d'éducation active - Genève",
"rue":"Route des Franchises",
"num":"11",
"npa":1203,
"localite":"Genève",
"canton":"GE",
"tel":"022 940 17 57",
"url":"www.formation-cemea.ch",
"domaine":"formation "
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [ 6.1243056,46.2120426 ]
},
"properties": {
"nom":"VIRES",
"rue":"Rue Ernest-Pictet ",
"num":"10",
"npa":1203,
"localite":"Genève",
"canton":"GE",
"tel":"022 328 44 33",
"url":"www.vires.ch",
"domaine":"violences "
}
}
As for toggling ON / OFF your categories, you could use Leaflet Layers Control L.control.layers.
As for grouping your features by category ("domaine" in your case), see the post I linked in my comment: Leaflet: How to toggle GeoJSON feature properties from a single collection?
You could even slightly simplify it by directly using Layer Groups L.layerGroup instead of using intermediate arrays.
var categories = {},
category;
var layersControl = L.control.layers(null, null).addTo(map);
function addDataToMap(data, map) {
L.geoJson(data, {
onEachFeature: function(feature, layer) {
category = feature.properties.domaine;
// Initialize the category layer group if not already set.
if (typeof categories[category] === "undefined") {
categories[category] = L.layerGroup().addTo(map);
layersControl.addOverlay(categories[category], category);
}
categories[category].addLayer(layer);
}
});
//dataLayer.addTo(map); // no longer add the GeoJSON layer group to the map.
}
$.getJSON("data.geojson", function(data) {
addDataToMap(data, map);
});
Demo: https://plnkr.co/edit/H6E6q0vKwb3RPOZBWs27?p=preview
Considering a custom floor plan been showed with leaflet with markers loaded from a geojson file. Each of the markers have a related page and those pages have hyperlinks aiming to the map. I would like to add #id to those hyperlinks.
If for example, the map url was domain.com/map, the "Marker 1" page (domain.com/marker-1) would have a link (domain.com/map#maker-1) that would open the map with the actual marker for "marker 1" on the center of the map with it's popup open.
My question is how do I open the map with a certain marker on the center and with it popups open when I add a hash to the url (domain.com/map#maker-1)?
Here goes my code:
index.php
<head>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js" />
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css" />
<script src="geojson.js" type="text/javascript"></script>
</head>
<body>
<div id="map"></div>
<script src="map.js"></script>
</body>
geojson.js
var groupsGeoJson = {
"type": "FeatureCollection",
"features":[
{
"geometry": {
"type": "Point",
"coordinates": [-120,60]
},
"type": "Feature",
"properties": {
"popupContent": "<h1>Maker 1</h1>"
},
"id": 1
},
{
"geometry": {
"type": "Point",
"coordinates": [-80,40]
},
"type": "Feature",
"properties": {
"popupContent": "<h1>Maker 2</h1>"
},
"id": 2
}
]
};
map.js
var mapMinZoom = 2;
var mapMaxZoom = 6;
var mapIniZoom = 2;
var mapCenterLat = 20;
var mapCenterLng = -75;
var groupsIcon = L.icon({
iconUrl: 'images/silver_coin.gif',
iconSize: [32, 32],
iconAnchor: [16, 32],
popupAnchor: [0, -28]
});
var baseLayer = new L.TileLayer('layers/baseLayer/{z}/{x}/{y}.png', {
minZoom: mapMinZoom,
maxZoom: mapMaxZoom,
noWrap: true
});
var groups= L.geoJson(groupsGeoJson, {
pointToLayer: function (feature, latlng) {
return L.marker(latlng, {icon: groupsIcon});
}, onEachFeature: onEachFeature
});
var map = new L.Map('map', {
layers: [baseLayer, groups],
center: new L.LatLng(mapCenterLat, mapCenterLng),
zoom: mapIniZoom
});
var southWest = map.unproject([0, 16384], map.getMaxZoom());
var northEast = map.unproject([16384, 0], map.getMaxZoom());
var mapBounds = new L.LatLngBounds(southWest,northEast);
map.setMaxBounds(mapBounds);
function onEachFeature(feature, layer) {
var popupContent = "<p>Test</p>"
if (feature.properties && feature.properties.popupContent) {
popupContent += feature.properties.popupContent;
}
layer.bindPopup(popupContent);
}