Emulate click on leaflet map item - javascript

Having the Leaflet Choropleth tutorial i have to emulate a click event on a specific map area. For example:
i have to have a function like clickOnMapItem(itemId) that will click on a map area which is defined by the following code
{"type":"Feature","id":"05","properties":{"name":"Arkansas","density":56.43},"geometry":{"type":"Polygon","coordinates":[...}
where "id":"05" is the id I need to click on
The rest of my code is as in the example:
state-data.js:
var statesData = {"type":"FeatureCollection","features":[
{"type":"Feature","id":"01","properties":{"name":"Alabama","density":94.65},"geometry":{"type":"Polygon","coordinates":[[[-87.359 and so on
html:
...header ommited
<!-- language:lang-html -->
<body>
<div id="map"></div>
<script src="dist/leaflet.js"></script>
<script type="text/javascript" src="us-states.js"></script>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
var map = L.map('map').setView([37.8, -96], 4);
var cloudmade = L.tileLayer('http://{s}.tile.cloudmade.com/{key}/{styleId}/256/{z}/{x}/{y}.png', {
attribution: 'Map data © 2011 OpenStreetMap contributors, Imagery © 2011 CloudMade',
key: 'BC9A493B41014CAABB98F0471D759707',
styleId: 22677
}).addTo(map);
// control that shows state info on hover
var info = L.control();
info.onAdd = function (map) {
this._div = L.DomUtil.create('div', 'info');
this.update();
return this._div;
};
info.update = function (props) {
this._div.innerHTML = '<h4>US Population Density</h4>' + (props ?
'<b>' + props.name + '</b><br />' + props.density + ' people / mi<sup>2</sup>'
: 'Hover over a state');
};
info.addTo(map);
// get color depending on population density value
function getColor(d) {
return d > 1000 ? '#800026' :
d > 500 ? '#BD0026' :
d > 200 ? '#E31A1C' :
d > 100 ? '#FC4E2A' :
d > 50 ? '#FD8D3C' :
d > 20 ? '#FEB24C' :
d > 10 ? '#FED976' :
'#FFEDA0';
}
function style(feature) {
return {
weight: 2,
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.7,
fillColor: getColor(feature.properties.density)
};
}
//ON HOVER HANDLER
function highlightFeature(e) {
var layer = e.target;
layer.setStyle({
weight: 5,
color: '#666',
dashArray: '',
fillOpacity: 0.7
});
if (!L.Browser.ie && !L.Browser.opera) {
layer.bringToFront();
}
info.update(layer.feature.properties);
}
var geojson;
function resetHighlight(e) {
geojson.resetStyle(e.target);
info.update();
}
function zoomToFeature(e) {
map.fitBounds(e.target.getBounds());
}
//setting click handlers
function onEachFeature(feature, layer) {
layer.on({
mouseover: highlightFeature,
mouseout: resetHighlight,
click: zoomToFeature
});
}
geojson = L.geoJson(statesData, {
style: style,
onEachFeature: onEachFeature
}).addTo(map);
map.attributionControl.addAttribution('Population data © US Census Bureau');
var legend = L.control({position: 'bottomright'});
legend.onAdd = function (map) {
var div = L.DomUtil.create('div', 'info legend'),
grades = [0, 10, 20, 50, 100, 200, 500, 1000],
labels = [],
from, to;
for (var i = 0; i < grades.length; i++) {
from = grades[i];
to = grades[i + 1];
labels.push(
'<i style="background:' + getColor(from + 1) + '"></i> ' +
from + (to ? '–' + to : '+'));
}
div.innerHTML = labels.join('<br>');
return div;
};
legend.addTo(map);
</script>
</body>
Thank you in advance!

Sorry, it's a 3 years old question, but I will try to answer it here:
First, update your code below:
//setting click handlers
function onEachFeature(feature, layer) {
layer.on({
mouseover: highlightFeature,
mouseout: resetHighlight,
click: zoomToFeature
});
//add this line
layer._leaflet_id = feature.id;
}
The new line above will 'assign' your geoJSON's 'id' as your layer's leaflet_id,
then make a new function like this :
function clickOnMapItem(itemId) {
var id = parseInt(itemId);
//get target layer by it's id
var layer = geojson.getLayer(id);
//fire event 'click' on target layer
layer.fireEvent('click');
}
So, there's no need to populate any coordinate at all!!!
Hope it helps!

To add to #snkashis: fireEvent will only work if you input the right Types.
That would mean doing this:
var latlngPoint = new L.LatLng(x, y);
map.fireEvent('click', {
latlng: latlngPoint,
layerPoint: map.latLngToLayerPoint(latlngPoint),
containerPoint: map.latLngToContainerPoint(latlngPoint)
});
You can also do this for a specific marker/layer whatever if it's added to the map.

So you want to emulate a click event? Why not use Leaflet's fireEvent like map.fireEvent('click',{latlng:[x,y]})
You probably need to fill in layerPoint and containerPoint into the object's parameters.
See http://leafletjs.com/reference.html#mouse-event

Related

Keep Getting this.callInitHooks error (Leaflet)

I'm trying to add markers and a search bar to my leaflet choropleth map. However, I keep running into an error that tells me: Uncaught TypeError: this.callInitHooks is not a function. It comes from my leaflet.js file, and am unsure how to fix it. Most of my error seems to come from the leaflet links I've copied into my body before my script, or because of me trying to add a search bar or markets onto my map. I pasted my code below:
<html>
<head>
<title>How to make a choropleth map with Leaflet.js</title>
<meta charset="utf-8">
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.0/dist/leaflet.css" />
<link rel="stylesheet" href="leaflet-search.css" />
<script src="censustracts.js"></script>
<style type="text/css">
html, body, #map{
height: 100%;
padding: 0;
margin: 0;
}
.info {
padding: 6px 8px;
font: 14px/16px Arial, Helvetica, sans-serif;
background: white;
background: rgba(255,255,255,0.8);
box-shadow: 0 0 15px rgba(0,0,0,0.2);
border-radius: 5px;
}
.info h4 {
margin: 0 0 5px;
color: #777;
}
.legend {
line-height: 18px;
color: #555;
}
.legend i {
width: 18px;
height: 18px;
float: left;
margin-right: 8px;
opacity: 0.7;
}
</style>
</head>
<body>
<div id="map"></map>
<script src="https://unpkg.com/leaflet#1.3.0/dist/leaflet.js"></script>
<script src="leaflet-search.js"></script>
<script type="text/javascript">
var map = L.map('map').setView([37.8, -96], 4);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {attribution: 'OSM'})
.addTo(map);
L.geoJson(statesData).addTo(map);
L.geoJson(statesData).addTo(map);
function getColor(d) {
return d > 1000 ? '#800026' :
d > 500 ? '#BD0026' :
d > 200 ? '#E31A1C' :
d > 100 ? '#FC4E2A' :
d > 50 ? '#FD8D3C' :
d > 20 ? '#FEB24C' :
d > 10 ? '#FED976' :
'#FFEDA0';
}
function style(feature) {
return {
fillColor: getColor(feature.properties.density),
weight: 2,
opacity: 1,
color: 'white',
dashArray: '3',
fillOpacity: 0.7
};
}
L.geoJson(statesData, {style: style}).addTo(map);
///Functionality
function highlightFeature(e) {
var layer = e.target;
layer.setStyle({
weight: 5,
color: '#666',
dashArray: '',
fillOpacity: 0.7
});
info.update(layer.feature.properties);
if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) {
layer.bringToFront();
}
}
function resetHighlight(e) {
geojson.resetStyle(e.target);
info.update();
}
function zoomToFeature(e) {
map.fitBounds(e.target.getBounds());
}
function onEachFeature(feature, layer) {
layer.on({
mouseover: highlightFeature,
mouseout: resetHighlight,
click: zoomToFeature
});
}
geojson = L.geoJson(statesData, {
style: style,
onEachFeature: onEachFeature
}).addTo(map);
//Add info
var info = L.control();
info.onAdd = function (map) {
this._div = L.DomUtil.create('div', 'info'); // create a div with a class "info"
this.update();
return this._div;
};
// method that we will use to update the control based on feature properties passed
info.update = function (props) {
this._div.innerHTML = '<h4>US Population Density</h4>' + (props ?
'<b>' + props.name + '</b><br />' + props.density + ' people / mi<sup>2</sup>'
: 'Hover over a state');
};
info.addTo(map);
//Add Legend
var legend = L.control({position: 'bottomright'});
legend.onAdd = function (map) {
var div = L.DomUtil.create('div', 'info legend'),
grades = [0, 10, 20, 50, 100, 200, 500, 1000],
labels = [];
// loop through our density intervals and generate a label with a colored square for each interval
for (var i = 0; i < grades.length; i++) {
div.innerHTML +=
'<i style="background:' + getColor(grades[i] + 1) + '"></i> ' +
grades[i] + (grades[i + 1] ? '–' + grades[i + 1] + '<br>' : '+');
}
return div;
};
legend.addTo(map);
///Bind Popups
var data = [
{"loc":[32,-86], "title":"aquamarine"},
{"loc":[41.575730,13.002411], "title":"black"},
{"loc":[41.807149,13.162994], "title":"blue"},
{"loc":[41.507149,13.172994], "title":"chocolate"},
{"loc":[41.847149,14.132994], "title":"coral"},
{"loc":[41.219190,13.062145], "title":"cyan"},
{"loc":[41.344190,13.242145], "title":"darkblue"},
{"loc":[41.679190,13.122145], "title":"Darkred"},
{"loc":[41.329190,13.192145], "title":"Darkgray"},
{"loc":[41.379290,13.122545], "title":"dodgerblue"},
{"loc":[41.409190,13.362145], "title":"gray"},
{"loc":[41.794008,12.583884], "title":"green"},
{"loc":[41.805008,12.982884], "title":"greenyellow"},
{"loc":[41.536175,13.273590], "title":"red"},
{"loc":[41.516175,13.373590], "title":"rosybrown"},
{"loc":[41.506175,13.273590], "title":"royalblue"},
{"loc":[41.836175,13.673590], "title":"salmon"},
{"loc":[41.796175,13.570590], "title":"seagreen"},
{"loc":[41.436175,13.573590], "title":"seashell"},
{"loc":[41.336175,13.973590], "title":"silver"},
{"loc":[41.236175,13.273590], "title":"skyblue"},
{"loc":[41.546175,13.473590], "title":"yellow"},
{"loc":[41.239190,13.032145], "title":"white"}
];
var markersLayer = new L.LayerGroup(); //layer contain searched elements
map.addLayer(markersLayer);
var controlSearch = L.Control.Search({
position:'topright',
layer: markersLayer,
initial: false,
zoom: 12,
marker: false
});
map.addControl( controlSearch );
for(i in data) {
var title = data[i].title, //value searched
loc = data[i].loc, //position found
marker = new L.Marker(new L.latLng(loc), {title: title} );//se property searched
marker.bindPopup('title: '+ title );
markersLayer.addLayer(marker);
}
</script>
</body>
</html>
Don't use new with lowercase function:
marker = new L.Marker(new L.latLng(loc), {title: title} );
Use new L.LatLng(loc) or L.latLng(loc) without new

How can I check if the marker is or isn't in the inside a specific circle

I need help to check if the marker is inside of a specifiq circle.
I have a array of circles and i have to check is the marker is inside and get information of the target circle.
I try calling distanceTo
Anyone can help me ?
...
export class PlacesPage {
map: Map;
placesList = [];
ionViewDidEnter() {
this.map = new Map("mapId2").setView([41.694941, -8.821054], 13);
tileLayer("http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png", {
attribution: "cityt3ip.com"
}).addTo(this.map);
fetch("./assets/data.json")
.then(res => res.json())
.then(json => {
this.placesList = json.places;
this.leafletMap();
});
}
leafletMap() {
for (const place of this.placesList) {
circle([place.latitude, place.longitude], {
color: "red",
fillColor: "#f03",
fillOpacity: 0.5,
radius: 100
}).addTo(this.map);
}
marker([41.692135, -8.831127], {
draggable: true,
autoPan: true
})
.addTo(this.map).on('drag', this.masterClick, this);
}
masterClick(e: any) {
console.log(e)
var d = this.map.distanceTo(e.latlng, circle.getLatLng());
var isInside = d < circle.getRadius();
console.log(isInside)
circle.setStyle({
fillColor: isInside ? "green" : "#f03"
});
}
ionViewWillLeave() {
this.map.remove();
}
}
```
It looks like you're trying to change the circle styling when you drag a marker over a circle.
I made a fiddle that shows this. My strategy was to store the current circle when the marker is moved over any of the circles.
function createCircles() {
circleCoords.forEach(circ => {
const ll = L.latLng(circ[0], circ[1]);
let curCirc = L.circle(ll, {
radius: 100
}).addTo(map);
curCirc.on('mouseover', (evt) => {
myCircle = evt.target;
})
})
}
Then I modified your masterClick function like this:
function masterClick(e) {
var d = e.latlng.distanceTo(myCircle.getLatLng());
var isInside = d < myCircle.getRadius();
myCircle.setStyle({
fillColor: isInside ? "green" : "#f03"
});
}
There's no function in Leaflet to detect whether a marker lies within a circle. Instead, you can use the distanceTo method to test whether a point is within a certain radius of the centre of a circle, which has the same outcome.
isMarkerInsideCircle(markerLatLng, circleCenterLatLng, circleRadius){
// markerLatLng and circleCenterLatLng must be instance of L.latlng class.
// you can create an instance like this L.latLng(lat, lng);
if (markerLatLng.distanceTo(circleCenterLatLng) <= circleRadius){
return true;
} else {
return false;
}
}
Here´s my solution! Thank you all!
async isMarkerInsideCircle() {
try {
this.currentLayer = null;
this.map.eachLayer(layer => {
if (layer instanceof L.Circle) {
this.circleCenterLatLng = layer.getLatLng();
this.circleRadius = layer.getRadius();
layer.setStyle({
color: 'red',
fillColor: '#f03'
});
if (
this.markerLatLng.distanceTo(this.circleCenterLatLng) <=
this.circleRadius
) {
this.currentLayer = layer;
} else {
}
}
});
} catch (e) {
console.log(e);
}
if (this.currentLayer !== null) {
console.log(this.currentLayer);
for (const pl of this.places) {
if (
pl.latitude == this.currentLayer.getLatLng().lat &&
pl.longitude == this.currentLayer.getLatLng().lng
) {
console.log(pl.title);
this.spotVisited = pl.id;
this.isLoading = true;
}
}
this.currentLayer.setStyle({
color: 'green',
fillColor: '#ddd'
});
}
}

Leaflet.js: Pass feature property to class constructor

I have quite a few used-defined svg markers (glyphs) (big thanks to the SO user with the name rioV8 for his help on this - and not only this -...) and ideally I would like these glyphs to get their shape from the feature properties structure.
//create feature properties
var p = {
"id": i,
"popup": "Dot_" + i,
"year": parseInt(data[i].year),
"glyphName": "square",
"size": 500 // Fixed size circle radius=~13
};
These user-defined glyphs extend L.circleMarker and for simplicity let's say that their shapes can be square or diamond. Currently, I am extending L.Class and am passing glyphName in the constructor: (feel free to criticise that, If it doesnt look nice to you)
var glyph = L.Class.extend({
initialize: function(glyphName) {
glyphName === "square"? this.type = MarkerSquare:
glyphName === "diamond"? this.type = MarkerDiamond:
this.type = L.circleMarker;
},
});
and when I need to plot the glyphs I have something like:
L.geoJson(myDots[i], {
pointToLayer: function(feature, latlng) {
var p = latlng;
var myGlyph = new glyph('diamond')
return new myGlyph.type(p, style(feature));
},
onEachFeature: onEachDot
}).addTo(map);
Can I have the shape determined by the feature properties please? Eventually, what i am trying to achieve is to merge these two lines
var myGlyph = new glyph('diamond')
return new myGlyph.type(p, style(feature));
to something like
return new myGlyph.type(p, style(feature));
That will enable me to plot different shapes, and those shapes will be determined by the input data used to populate features properties. In a similar manner that these properties are used for color or size they could now be used to set the shape.
Thanks! (Full code below)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Chart</title>
<style>
html,
body {
height: 100%;
margin: 0;
}
#map {
width: 600px;
height: 600px;
}
</style>
<script src='https://d3js.org/d3.v4.min.js' type='text/javascript'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.3/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.3.3/dist/leaflet.js"></script>
</head>
<body>
<div id="map"></div>
<script>
L.Canvas.include({
_updateMarkerDiamond: function(layer) {
if (!this._drawing || layer._empty()) {
return;
}
var p = layer._point,
ctx = this._ctx,
r = Math.max(Math.round(layer._radius), 6);
this._drawnLayers[layer._leaflet_id] = layer;
ctx.beginPath();
ctx.moveTo(p.x - r, p.y);
ctx.lineTo(p.x, p.y - r);
ctx.lineTo(p.x + r, p.y);
ctx.lineTo(p.x, p.y + r);
ctx.lineTo(p.x - r, p.y);
ctx.closePath();
this._fillStroke(ctx, layer);
}
});
var MarkerDiamond = L.CircleMarker.extend({
_updatePath: function() {
this._renderer._updateMarkerDiamond(this);
}
});
L.Canvas.include({
_updateMarkerSquare: function(layer) {
if (!this._drawing || layer._empty()) {
return;
}
var p = layer._point,
ctx = this._ctx,
r = Math.max(Math.round(layer._radius), 5);
this._drawnLayers[layer._leaflet_id] = layer;
ctx.beginPath();
ctx.moveTo(p.x - r, p.y - r);
ctx.lineTo(p.x + r, p.y - r);
ctx.lineTo(p.x + r, p.y + r);
ctx.lineTo(p.x - r, p.y + r);
ctx.lineTo(p.x - r, p.y - r);
ctx.closePath();
this._fillStroke(ctx, layer);
}
});
var MarkerSquare = L.CircleMarker.extend({
_updatePath: function() {
this._renderer._updateMarkerSquare(this);
}
});
var glyph = L.Class.extend({
initialize: function(glyphName) {
glyphName === "square"? this.type = MarkerSquare:
glyphName === "diamond"? this.type = MarkerDiamond:
this.type = L.circleMarker;
},
});
var data = [];
var NumOfPoints = 100;
for (let i = 0; i < NumOfPoints; i++) {
data.push({
num: i,
x: Math.random() * 60,
y: Math.random() * 60,
year: Math.floor(100 * Math.random())
})
}
renderChart(data);
function make_dots(data) {
var arr = [];
var nest = d3.nest()
.key(function(d) {
return Math.floor(d.year / 10);
})
.entries(data);
for (var k = 0; k < nest.length; ++k) {
arr[k] = helper(nest[k].values);
}
return arr;
}
function helper(data) {
dots = {
type: "FeatureCollection",
features: []
};
for (var i = 0; i < data.length; ++i) {
x = data[i].x;
y = data[i].y;
var g = {
"type": "Point",
"coordinates": [x, y]
};
//create feature properties
var p = {
"id": i,
"popup": "Dot_" + i,
"year": parseInt(data[i].year),
//"glyphName": "square",
"size": 500 // Fixed size circle radius=~13
};
//create features with proper geojson structure
dots.features.push({
"geometry": g,
"type": "Feature",
"properties": p
});
}
return dots;
}
//create color ramp
function getColor(y) {
return y > 90 ? '#6068F0' :
y > 80 ? '#6B64DC' :
y > 70 ? '#7660C9' :
y > 60 ? '#815CB6' :
y > 50 ? '#8C58A3' :
y > 40 ? '#985490' :
y > 30 ? '#A3507C' :
y > 20 ? '#AE4C69' :
y > 10 ? '#B94856' :
y > 0 ? '#C44443' :
'#D04030';
}
//calculate radius so that resulting circles will be proportional by area
function getRadius(y) {
r = Math.sqrt(y / Math.PI)
return r;
}
var myRenderer;
//create style, with fillColor picked from color ramp
function style(feature) {
return {
radius: getRadius(feature.properties.size),
fillColor: getColor(feature.properties.year),
color: "#000",
weight: 0,
opacity: 1,
fillOpacity: 0.9,
renderer: myRenderer
};
}
//create highlight style, with darker color and larger radius
function highlightStyle(feature) {
return {
radius: getRadius(feature.properties.size) + 1.5,
fillColor: "#FFCE00",
color: "#FFCE00",
weight: 1,
opacity: 1,
fillOpacity: 0.9,
};
}
//attach styles and popups to the marker layer
function highlightDot(e) {
var layer = e.target;
dotStyleHighlight = highlightStyle(layer.feature);
layer.setStyle(dotStyleHighlight);
if (!L.Browser.ie && !L.Browser.opera) {
layer.bringToFront();
}
}
function resetDotHighlight(e) {
var layer = e.target;
dotStyleDefault = style(layer.feature);
layer.setStyle(dotStyleDefault);
}
function onEachDot(feature, layer) {
layer.on({
mouseover: highlightDot,
mouseout: resetDotHighlight
});
var popup = '<table style="width:110px"><tbody><tr><td><div><b>Marker:</b></div></td><td><div>' + feature.properties.popup +
'</div></td></tr><tr class><td><div><b>Group:</b></div></td><td><div>' + feature.properties.glyphName +
'</div></td></tr><tr><td><div><b>X:</b></div></td><td><div>' + feature.geometry.coordinates[0] +
'</div></td></tr><tr><td><div><b>Y:</b></div></td><td><div>' + feature.geometry.coordinates[1] +
'</div></td></tr></tbody></table>'
layer.bindPopup(popup);
}
function renderChart(data) {
var myDots = make_dots(data);
var minZoom = 0,
maxZoom = 15;
var map = L.map('map', {
minZoom: minZoom,
maxZoom: maxZoom
}).setView([30, 30], 3);
L.tileLayer("http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
continuousWorld: false,
minZoom: 0,
noWrap: true
}).addTo(map);
myRenderer = L.canvas({
padding: 0.5
});
// Define an array to keep layerGroups
var dotlayer = [];
//create marker layer and display it on the map
for (var i = 0; i < myDots.length; i += 1) {
dotlayer[i] = L.geoJson(myDots[i], {
pointToLayer: function(feature, latlng) {
var p = latlng;
var myGlyph = new glyph('diamond')
return new myGlyph.type(p, style(feature));
},
onEachFeature: onEachDot
}).addTo(map);
}
var cl = L.control.layers(null, {}).addTo(map);
for (j = 0; j < dotlayer.length; j += 1) {
var name = "Group " + j + "0-" + j + "9";
cl.addOverlay(dotlayer[j], name);
}
}
</script>
</body>
</html>
You need to make the shape of the marker a property of the marker and merge the render parts of the MarkerDiamond and MarkerSquare into a different marker and decide which render part to draw with an if inside the _updateMarkerXX method based on the property shape.
layer.options.shape contains the shape inside the render routine.
Or do it in the Marker routine
var Marker = L.CircleMarker.extend({
_updatePath: function() {
if (this.options.shape === "square")
this._renderer._updateMarkerSquare(this);
if (this.options.shape === "diamond")
this._renderer._updateMarkerDiamond(this);
}
});
function style(feature) {
return {
radius: getRadius(feature.properties.size),
shape: feature.properties.shape,
fillColor: getColor(feature.properties.year),
color: "#000",
weight: 0,
opacity: 1,
fillOpacity: 0.9,
renderer: myRenderer
};
}
Edit
It might be useful to time the use of Magic Numbers (Enums) instead of strings, because the compare of a number is cheaper than string compare. And Aenaon has about 300K markers, but it might be negligible.

Disable scroll zoom on mapbox

I'm trying to disable scroll zoom on a mapbox map, but it is not working. Can anyone let me know what's wrong with my code? The error I get is "Uncaught TypeError: Cannot read property 'disable' of undefined"
<script>
L.mapbox.accessToken = 'pk.token';
var map = L.mapbox.map('map', 'mapbox.streets', {
legendControl: {
position: 'topright'
}
})
.setView([56.3, 11.5], 7);
var popup = new L.Popup({ autoPan: false });
// statesData comes from the 'us-states.js' script included above
var statesLayer = L.geoJson(statesData, {
style: getStyle,
onEachFeature: onEachFeature
}).addTo(map);
function getStyle(feature) {
return {
weight: 2,
opacity: 0.1,
color: 'black',
fillOpacity: 0.7,
fillColor: getColor(feature.properties.density)
};
}
// get color depending on population density value
function getColor(d) {
return d > 1000 ? '#512b00' :
d > 500 ? '#8E4C01' :
d > 200 ? '#cc4c02' :
d > 100 ? '#ec7014' :
d > 50 ? '#fe9929' :
d > 20 ? '#fec44f' :
d > 10 ? '#fee391' :
d > 5 ? '#fff7bc' :
'#ffffe5';
}
function onEachFeature(feature, layer) {
layer.on({
mousemove: mousemove,
mouseout: mouseout,
click: zoomToFeature
});
}
var closeTooltip;
function mousemove(e) {
var layer = e.target;
popup.setLatLng(e.latlng);
popup.setContent('<div class="marker-title">' + layer.feature.properties.name + '</div>' +
layer.feature.properties.density + ' feriehuse');
if (!popup._map) popup.openOn(map);
window.clearTimeout(closeTooltip);
// highlight feature
layer.setStyle({
weight: 3,
opacity: 0.3,
fillOpacity: 0.9
});
if (!L.Browser.ie && !L.Browser.opera) {
layer.bringToFront();
}
}
function mouseout(e) {
statesLayer.resetStyle(e.target);
closeTooltip = window.setTimeout(function() {
map.closePopup();
}, 100);
}
function zoomToFeature(e) {
map.fitBounds(e.target.getBounds());
}
map.legendControl.addLegend(getLegendHTML());
function getLegendHTML() {
var grades = [0, 5, 10, 20, 50, 100, 200, 500, 1000],
labels = [],
from, to;
for (var i = 0; i < grades.length; i++) {
from = grades[i];
to = grades[i + 1];
labels.push(
'<li><span class="swatch" style="background:' + getColor(from + 1) + '"></span> ' +
from + (to ? '–' + to : '+')) + '</li>';
}
return '<span>Antal feriehuse</span><ul>' + labels.join('') + '</ul>';
}
// disable map zoom when using scroll
map.scrollZoom.disable();
</script>
This is a mapbox.js / leaflet map, not mapbox-gl-js, so the difference is in Leaflet the scroll zoom control is called scrollWheelZoom not scrollZoom. If you replace the last line of your script with the following it should work. http://jsfiddle.net/x5j669zj/
if (map.scrollWheelZoom) {
map.scrollWheelZoom.disable();
}

Many google map listeners existing at the same time

At the moment I have a map with lots of regions defined by polygons, and each polygon has a different fillColor.
Then, I have the following effects when I hover over each polygon area:
google.maps.event.addListener(MapArea, "mouseover", function () {
this.setOptions({ fillColor: 'rgb(0,255,255)' });
});
google.maps.event.addListener(MapArea, "mouseout", function () {
this.setOptions({ fillColor: 'rgb(255,0,0)' });
});
In other words, when I mouse over, the area turns cyan, when I remove the mouse, the area turns red. However, since my areas are all different colours, I would like to return to their colours when the mouse is removed.
The different colours are achieved by:
for (var t=0; t< lAll_Areas.length; t++) {
var n = //arbitrary number 0<n<255;
var m = (255-cd).toString();
var col = 'rgb(' + n + ',' + m + ',0)';
lAll_Areas[t].setOptions({ fillColor: col });
}
So, in there I would like to have something like:
google.maps.event.addListener(MapArea, "mouseout", function () {
this.setOptions({ fillColor: col });
});
How do I attach the mouseout event to each individual polygon?
One option: set the default and highlight colors as properties of the polygon.
for (var t=0; t< lAll_Areas.length; t++) {
var n = //arbitrary number 0<n<255;
var m = (255-cd).toString();
var col = 'rgb(' + n + ',' + m + ',0)';
lAll_Areas[t].defaultColor = col;
lAll_Areas[t].highlightColor = 'rgb(0,255,255)';
lAll_Areas[t].setOptions({ fillColor: col });
}
Then:
google.maps.event.addListener(MapArea, "mouseover", function () {
this.setOptions({ fillColor: this.highlightColor });
});
google.maps.event.addListener(MapArea, "mouseout", function () {
this.setOptions({ fillColor: this.defaultColor });
});
Have your mouseover event listener store the current color in a global variable that your mouseout listener can refer to.
var color;
google.maps.event.addListener(MapArea, "mouseover", function () {
color = this.fillColor;
this.setOptions({ fillColor: 'rgb(0,255,255)' });
});
google.maps.event.addListener(MapArea, "mouseout", function () {
this.setOptions({ fillColor: color });
});

Categories