Using leaflet 7.3 and polygon data in GeoJSON, how can I add labels from field: NAME?
Here is example of current GeoJSON polygon data. I would like to enable fixed labels in center of polygon, overlap OK.
var districts = L.geoJson(null, {
style: function (feature) {
return {
color: "green",
fill: true,
opacity: 0.8
};
},
onEachFeature(feature, layer) {
layer.on('mouseover', function () {
this.setStyle({
'fillColor': '#0000ff'
});
});
layer.on('mouseout', function () {
this.setStyle({
'fillColor': '#ff0000'
});
});
layer.on('click', function () {
window.location = feature.properties.URL;
});
}
});
$.getJSON("data/districts.geojson", function (data) {
districts.addData(data);
});
In onEachFeature callback, you can get the center of the L.Polygon created by GeoJSON layer and bind a label to it.
var polygonCenter = layer.getBounds().getCenter();
// e.g. using Leaflet.label plugin
L.marker(polygonCenter)
.bindLabel(feature.properties['NAME'], { noHide: true })
.addTo(map);
Here is an example: http://jsfiddle.net/FranceImage/ro54bqbz/ using Leaflet.label
Related
I have the following code that I call to create a copy object of map, and initialize the Leaflet map. This works and loads properly. However, the onEachFeature and/or the clickFeature functions are not working properly.
var map = {
mapUrl: "",
maxZoom: 18,
minZoom: 2,
map: L.map('worldMap').setView([51.505, -0.09], 2),
create: function(values) {
var instance = Object.create(this);
Object.keys(values).forEach(function(key) {
instance[key] = values[key];
});
return instance;
},
initLeafletMap: function() {
L.tileLayer(this.mapUrl, {
attribution: '',
maxZoom: this.maxZoom,
minZoom: this.minZoom,
id: 'mapbox.streets'
}).addTo(this.map);
//add continents' outlines
$.getJSON("/static/continents.json",
(function(style, onEachFeature, map) {
return function(continents) {
console.log(typeof(continents));
L.geoJson(continents, {
style: style,
onEachFeature: onEachFeature
}).addTo(map);
};
}(this.style, this.onEachFeature, this.map))
);
},
style: function() {
return {
weight: 2,
opacity: 1,
color: 'beige',
dashArray: '3',
fillOpacity: 0
};
},
onEachFeature: function(feature, layer) {
layer.on({
click: this.clickFeature
});
},
clickFeature: function(e) {
do something here();
},
So when I click on the map, I know the onEachFeature function is called, but it does not call clickFeature. Instead I get this error in the console:
leaflet.js:5 Uncaught TypeError: Cannot read property 'call' of undefined
at e.fire (leaflet.js:5)
at e._fireDOMEvent (leaflet.js:5)
at e._handleDOMEvent (leaflet.js:5)
at HTMLDivElement.r (leaflet.js:5)
Much probably simply need to bind the this context when you pass your onEachFeature method as argument of your IIFE to build the callback to your AJAX call:
this.onEachFeature.bind(this)
See also Leaflet- marker click event works fine but methods of the class are undefined in the callback function
BTW you could also attach your click event listener directly on the Leaflet GeoJSON Layer Group instead of doing it for each child layer.
How to get the mouseover event to work with google maps Api V3 on Polygon shapes ?
I cannot get the event to fire on mouseover.
var data_layer25 = new google.maps.Data({ map: map });
data_layer25.loadGeoJson('http://example.com/Assets/GeoJson/USA-MO.GeoJson');
data_layer25.setStyle({
fillColor: ' #808000 ',
strokeWeight: 1
});
google.maps.event.addListener((data_layer25), "click", function () { window.location = "/RepTerritory/index/9" });
google.maps.event.addListener((data_layer25), "mouseover", function () {
this.setOptions({ fillColor: "#00FF00" });
});
google.maps.event.addListener((data_layer25), "mouseout", function () {
this.setOptions({ fillColor: "#FF0000" });
});
data_layer25.setMap(map);
Try to use this to change the style of Data Layers on mouse events:
data_layer25.addListener('mouseover', function(e) {
data_layer25.setStyle({
fillColor: "#00FF00"
});
});
data_layer25.addListener('mouseout', function(e) {
data_layer25.setStyle({
fillColor: "#FF0000"
});
});
I have created a map with cartodb which shows the train connection between cities. For this I have created two databases: The first one (cities) contains the information about the cities, route, order. Eg city: hamburg route: 1 order:1, city:lübeck route:1 order:2. In the second database (verbindungen) I have made a line between cities with the same route number. In my map I have added each database as a layer.
When I load the map only the cities are shown. Now I want to be able to click on one city and only the connection from/to this city are supposed to be shown.
This is my code so far:
var sql = new cartodb.SQL({ user: 'docu', format: 'geojson' });
function showFeature(route) {
sql.execute("select*from verbindungen where route = {{route}}", {route: route} ).done(function(geojson) {
if (route) {
map.removeLayer(route);
}
route = L.geoJson(geojson, {
style: {
color: "#000",
opacity: 0.65
}
}).addTo(map);
});
}
cartodb.createLayer(map, layerUrl)
.addTo(map)
.on('done', function(layer) {
layer.setInteraction(true);
var sublayerVerbindungen = layer.getSubLayer(1);
sublayerVerbindungen.hide()
var sublayerCities = layer.getSubLayer(0);
sublayerCities.show();
sublayerTerminals.on('featureClick', function(e, latlng, pos, data) {
showFeature(data.route)
});
})
.on('error', function() {
//log the error
});
I have tried to use this example: http://bl.ocks.org/javisantana/d20063afd2c96a733002
I have solved my problem:
cartodb.createLayer(map, layerUrl,
{https: true,
legends: false,
cartodb_logo:false,
layerIndex: 1
})
.addTo(map)
.on('done', function(layer) {
var sublayerVerbindungen = layer.getSubLayer(1);
sublayerVerbindungen.hide();
sublayerVerbindungen.setInteractivity('cartodb_id, a_route, the_geom, informationen_zur_route');
sublayerVerbindungen.setInteraction(true);
var sublayerCities = layer.getSubLayer(0);
sublayerCities.show();
sublayerCities.setInteractivity('cartodb_id, a_route, the_geom');
sublayerCities.setInteraction(true);
sublayerCities.on('featureClick', function(e, latlng, pos, data) {
console.log(data.a_route);
var newSql = "SELECT * FROM verbindungen WHERE a_route=" + data.a_route;
console.log(newSql);
sublayerVerbindungen.setSQL(newSql);
sublayerVerbindungen.show();
});
})
.on('error', function() {
//log the error
});
I am labeling 6 polygons in a GeoJson file. I am using the circleMarker on the each polygon centroid then calling .bindLabel, but I get this error: "circleMarker.bindLabel is not a function". Leaflet.label.js is called.
The map.
Code for GeoJSON:
var districts = L.geoJson(null, {
style: function (feature) {
return {
weight: 1,
opacity: 1,
color: 'blueviolet',
fillColor: 'plum',
fillOpacity: 0.5
};
},
onEachFeature: function (feature, layer) {
layer.on('mouseover', function () {
this.setStyle({
'fillColor': '#0000ff'
});
});
layer.on('mouseout', function () {
this.setStyle({
'fillColor': 'plum'
});
});
layer.on('click', function () {
window.location = feature.properties.URL;
});
var circleMarker = L.circleMarker(layer.getBounds().getCenter());
// e.g. using Leaflet.label plugin
circleMarker.bindLabel(feature.properties['NAME'], { noHide: true })
.circleMarker.addTo(map);
}
});
$.getJSON("data/districts.geojson", function (data) {
districts.addData(data);
});
You're calling a circleMarker method on your circleMarker object instance. That will never work. L.CircleMarker doesn't have a circleMarker method. This won't work:
circleMarker.bindLabel(feature.properties['NAME'], { noHide: true }).circleMarker.addTo(map);
This will:
circleMarker.bindLabel(feature.properties['NAME'], { noHide: true }).addTo(map);
And this will too:
circleMarker.bindLabel(feature.properties['NAME'], { noHide: true });
circleMarker.addTo(map);
But if you want to add a label without using L.CircleMarker you can simply do:
onEachFeature: function (feature, layer) {
layer.bindLabel(feature.properties['NAME'], { 'noHide': true });
}
You're also loading your scripts in the incorrect order:
<script src="assets/leaflet-label/leaflet.label.js"></script>
<script src="assets/leaflet-0.7.2/leaflet.js"></script>
Leaflet.label wants to extend classes from Leaflet, but it can't because Leaflet itself isn't loaded yet. So yes, you've loaded Leaflet.label, just not at the correct time. You could see this in your console, because Leaflet.label should throw an error when it doesn't find Leaflet. The correct way:
<script src="assets/leaflet-0.7.2/leaflet.js"></script>
<script src="assets/leaflet-label/leaflet.label.js"></script>
I am trying to reuse the region selection feature of JVectorMap. I am using a custom map (js) file. I have tested it in and it works fine for region selection.
Now I need to pass the regions which are selected by the user to the back end vb code. In this case maps.getSelectedRegions() gives an array of the user selected regions. I am not clear on how to pass a javascript array to back end vb code. The window.localstorage as how it is given in the example don't seem to work out here. Can somebody help me out on how this an be done?
This is the link of JVectorMap Region Selection - http://jvectormap.com/examples/regions-selection/
Following is the code I have used so far.
<script>
$(function(){ var maps; maps = new jvm.WorldMap({
container: $('#map'),
map: 'xyz_map',
regionsSelectable: true,
regionStyle: {
initial: {
fill: '#B8E186'
},
selected: {
fill: '#F4A582'
}
},
series: {
},
onRegionSelected: function(){
if (window.localStorage) {
window.localStorage.setItem(
'jvectormap-selected-regions',
JSON.stringify(maps.getSelectedRegions())
);
}
}
}); maps.setSelectedRegions( JSON.parse( window.localStorage.getItem('jvectormap-selected-regions') || '[]' )
); });
</script>
Thanks in advance
Sina
Managed to get a solution for this myself. You can add a hidden control in your asp code and assign the variable to this control.
$(function(){ var maps,temp; var hiddenControl = '<%=
inpHide.ClientID %>'; maps = new jvm.WorldMap({
container: $('#map'),
map: 'xyz_map',
regionsSelectable: true,
regionStyle: {
initial: {
fill: '#B8E186'
},
selected: {
fill: '#F4A582'
}
},
series: {
},
onRegionSelected: function(){
document.getElementById(hiddenControl).value=maps.getSelectedRegions();
} });
});