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();
}
Related
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
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.
I have created a chart using HighCharts and I want to disable any dataLabel if its width is more than height of its bar(bar cannot accomodate the dataLabel). I set the property 'enabled : false' of dataLabel of particular points but the effect is not being reflected in the chart.
<html>
<body>
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="min-width: 100px; max-width: 400px; height: 400px; margin: 0 auto"></div>
<script language="javascript">
var pointSelected = {};
var pointHovered = {};
//Highcharts.chart('container',
var chartObject = {
chart: {
type: 'bar',
events : {
render : function(){
var ch = this;
var series = this.series;
ch.series.forEach(function(s){
s.points.forEach(function(point){
var barHeight = point.graphic.element.height.animVal.value;
var dataLabelWidth = point.dataLabel.width;
var plotBoxWidth = ch.plotBox.width;
console.log(plotBoxWidth);
if(barHeight + dataLabelWidth < plotBoxWidth) {
// console.log(barHeight + dataLabelWidth);
// console.log("point will lie inside");
}
//else{
if(dataLabelWidth > barHeight){
//USING JQUERY IT CAN BE DONE BUT I WANT TO AVOID JQUERY AS MUCH AS POSSIBLE $(point.dataLabel.element).fadeOut("fast");
point.dataLabel.alignOptions.enabled = false; //THIS IS WHERE I'M DISABLING POINT
console.log(point)
// point.update({dataLabels : {enabled : false}});
//ch.options.plotOptions.series.dataLabels.enabled = false;
}
if(barHeight + dataLabelWidth > plotBoxWidth){
// console.log(barHeight + dataLabelWidth);
var diff = barHeight + dataLabelWidth - plotBoxWidth;
// console.log(diff);
// var x = point.dataLabel.translateX;
// var y = point.dataLabel.translateY;
// console.log(x);
// console.log(point);
//// diff +=15;
var diff2 = barHeight - dataLabelWidth;
// console.log("diff2" + diff2);
point.dataLabel.translate( diff2 , point.dataLabel.alignAttr.y );
// console.log( point.dataLabel.text);
//point.dataLabel.stork("black");
// point.dataLabel.text.styles.fill = "black";
var elem = $(point.dataLabel.element).children();
$(elem).eq(0).css("fill" , "black");
// console.log(elem);
// $(textElem).attr("style" , "fill : black");
// console.log(textElem);
// $(point.dataLabel.element.innerHTML).eq(0).children().eq(0).text();
// console.log("point will lie outside");
}
// }
})
})
console.log(this);
}
}
},
title: {
text: 'Historic World Population by Region'
},
subtitle: {
text: 'Source: Wikipedia.org'
},
xAxis: {
categories: ['Africa', 'America', 'Asia', 'Europe', 'Oceania'],
title: {
text: null
}
},
yAxis: {
min: 0,
title: {
text: 'Population (millions)',
align: 'high'
}
},
tooltip: {
formatter : function(){
return '<b>' +this.series.name + '<br/>' +this.x + '<br/>' + this.y+ '000000</b>'
}
},
plotOptions: {
series : {
allowPointSelect : true,
dataLabels: {
enabled : true,
color : "blue",
crop : true,
overflow: "none"
},
point:{
events : {
select :function() {
//get the selected object
pointSelected.categories = this.category;
pointSelected.y = this.y;
console.log(this);
changeOpacity(pointSelected);
},
mouseOver : function(){
//get the hovered object
pointHovered.categories = this.category;
pointHovered.y = this.y;
changeOpacityOnHover(pointHovered);
},
mouseOut : function(){
//event handler when mouse moves out
changeOpacityOnOut(pointHovered);
}
}
}
}
},
legend: {
align: 'right',
verticalAlign: 'top',
layout: 'vertical',
x: -150,
y: 100,
},
credits: {
enabled: false
},
series: [{
name: 'Year 1800',
data: [10700, 45000, 45000, 20300, 20000],
zones : [{value : 100 , color : 'orange'} , {value : 500 , color : 'black'} , { color : 'blue'}]
}]
}
//debugger
var barChart = new Highcharts.chart('container', chartObject);
//function on mouseOver
function changeOpacityOnHover(pointHovered){
//get the current chart object
var chart = $("#container").highcharts();
//get the points and check each point whether it is the hovered one
chart.series.forEach(function(obj){
obj.data.forEach(function(datum){
//if hovered one then get its graphic element(rect) and change its opacity to 1
if(datum.category == pointHovered.categories && datum.y == pointHovered.y ){
// console.log(datum) ;
// console.log(datum.graphic.element);
var tag = datum.graphic.element;
var x = $(tag).attr("x");
// console.log(x);
$(tag).css("opacity" , "1");
}
});
})
}
function changeOpacityOnOut(pointHovered){
//get the current chart object
var chart = $("#container").highcharts();
//get the points and check each point whether it is the hovered one from which mouse is over
chart.series.forEach(function(obj){
obj.data.forEach(function(datum){
//get its graphic element(rect)
if(datum.category == pointHovered.categories && datum.y == pointHovered.y ){
// console.log(datum) ;
// console.log(datum.graphic.element);
var tag = datum.graphic.element;
var x = $(tag).attr("x");
// console.log(x);
//if the current point(hovered) is selected one OR no point is yet selected , opacity will be 1
if((pointHovered.categories == pointSelected.categories && pointHovered.y== pointSelected.y) || Object.keys(pointSelected).length == 0 )
{
$(tag).css("opacity" , "1");
}
//else change opacity to 0.1
else{
$(tag).css("opacity" , "0.1");
}
}
});
})
}
// if point is selected
function changeOpacity(pointSelected){
//get the current chart object
var chart = $("#container").highcharts();
//get the selected point by comparing each point to pointSelected
chart.series.forEach(function(obj){
obj.data.forEach(function(datum){
// if current point is selected point then change opacity to 1 and its color to the color of its rect tag fill attribute
if(datum.category == pointSelected.categories && datum.y == pointSelected.y){
console.log(datum) ;
// console.log(datum.graphic.element);
var tag = datum.graphic.element;
//var xVal = datum.graphic.element.x.animVal.value;
//var yVal = datum.graphic.element.y.animVal.value
//console.log(xVal);
//console.log(yVal);
var x = $(tag).attr("x");
//console.log(x);
// var x2 = xVal -1;
// console.log(datum.dataLabel.translate(xVal , yVal - 1));
//console.log("after");
// console.log(x2);
//console.log(yVal-1);
$(tag).css("opacity" , "1");
var color = $(tag).attr("fill");
$(tag).css("fill" , color);
// console.log(color + "when clicked");
}
//else let its opacity be 0.1
else{
var tag = datum.graphic.element;
$(tag).css("opacity" , "0.1");
}
});
})
}
</script>
</body>
</html>
I have solved the problem using jQuery but if it can be done simply by setting property that will be great. Also , why the effect is not being reflected if the property is set??
Thanks.
It should work with your configuration, this is how dataLabels should be configured:
plotOptions: {
bar: {
dataLabels: {
enabled: true,
crop: true,
overflow: 'none',
// inside: true // by default it's outside the bar
}
}
},
Demo: http://jsfiddle.net/pbjpr47t/
I want to get lat/lon of marker on the openlayers map:
...
var dragVectorC = new OpenLayers.Control.DragFeature(vectorLayer, {
onComplete: function (feature) {
var lonlat = new OpenLayers.LonLat(feature.geometry.x, feature.geometry.y);
alert(lonlat.lat + ', ' + lonlat.lon);
But value that I get is:
5466016.2318036, 2328941.4188153
I have tried different ways to transform it but I always missing something.
What am I doing wrong?
var map = new OpenLayers.Map('map');
var layer = new OpenLayers.Layer.OSM("Simple OSM Map");
var vector = new OpenLayers.Layer.Vector('vector');
map.addLayers([layer, vector]);
map.setCenter(
new OpenLayers.LonLat(-71.147, 42.472).transform(
new OpenLayers.Projection("EPSG:4326"),
map.getProjectionObject()
), 12
);
var pulsate = function (feature) {
var point = feature.geometry.getCentroid(),
bounds = feature.geometry.getBounds(),
radius = Math.abs((bounds.right - bounds.left) / 2),
count = 0,
grow = 'up';
var resize = function () {
if (count > 16) {
clearInterval(window.resizeInterval);
}
var interval = radius * 0.03;
var ratio = interval / radius;
switch (count) {
case 4:
case 12:
grow = 'down'; break;
case 8:
grow = 'up'; break;
}
if (grow !== 'up') {
ratio = -Math.abs(ratio);
}
feature.geometry.resize(1 + ratio, point);
vector.drawFeature(feature);
count++;
};
window.resizeInterval = window.setInterval(resize, 50, point, radius);
};
var geolocate = new OpenLayers.Control.Geolocate({
bind: false,
geolocationOptions: {
enableHighAccuracy: false,
maximumAge: 0,
timeout: 7000
}
});
map.addControl(geolocate);
var firstGeolocation = true;
geolocate.events.register("locationupdated", geolocate, function (e) {
vector.removeAllFeatures();
var circle = new OpenLayers.Feature.Vector(
OpenLayers.Geometry.Polygon.createRegularPolygon(
new OpenLayers.Geometry.Point(e.point.x, e.point.y),
e.position.coords.accuracy / 2,
40,
0
),
{},
style
);
vector.addFeatures([
new OpenLayers.Feature.Vector(
e.point,
{},
{
graphicName: '', // cross
strokeColor: '', // #f00
strokeWidth: 2,
fillOpacity: 0,
pointRadius: 10
}
),
circle
]);
if (firstGeolocation) {
map.zoomToExtent(vector.getDataExtent());
pulsate(circle);
firstGeolocation = false;
this.bind = true;
}
// create marker
var vectorLayer = new OpenLayers.Layer.Vector("Overlay");
var feature = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Point(e.point.x, e.point.y),
{ some: 'data' },
{ externalGraphic: 'http://opportunitycollaboration.net/wp-content/uploads/2013/12/icon-map-pin.png', graphicHeight: 48, graphicWidth: 48 });
vectorLayer.addFeatures(feature);
map.addLayer(vectorLayer);
var dragVectorC = new OpenLayers.Control.DragFeature(vectorLayer, {
onComplete: function (feature) {
alert('x=' + feature.geometry.x + ', y=' + feature.geometry.y);
}
});
map.addControl(dragVectorC);
dragVectorC.activate();
});
geolocate.events.register("locationfailed", this, function () {
OpenLayers.Console.log('Location detection failed');
});
var style = {
fillColor: '#000',
fillOpacity: 0,
strokeWidth: 0
};
$(window).load(function () {
initMap();
});
function initMap() {
vector.removeAllFeatures();
geolocate.deactivate();
geolocate.watch = false;
firstGeolocation = true;
geolocate.activate();
}
You need to turn the point geometry's X,Y into a LonLat then transform it from your map's projection into WGS84 aka EPSG:4326 to get a 'conventional' lon/lat:
var dragVectorC = new OpenLayers.Control.DragFeature(vectorLayer, {
onComplete: function (feature) {
var lonlat = new OpenLayers.LonLat(feature.geometry.x, feature.geometry.y).transform(
map.getProjectionObject(),
new OpenLayers.Projection("EPSG:4326")
))
alert(lonlat.lat + ', ' + lonlat.lon)
2022 update:
import { toLonLat } from 'ol/proj'
let lonLat = toLonLat(coordinates)
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