I have one single map displayed on different pages. I want to have the same map centered and zoomed differently depending on the page which displays the map.
I've tried to edit the code but it seems only one "L.map" is admitted:
var map = L.map('single-map', {
center: [20, 20],
minZoom: 2,
zoom: 5,
scrollWheelZoom: false
});
anyone has an idea? Thank you very much for any help!
You can set on each php page a global javascript variable to know on which page you are and change so the map settings
page1.php
<script>
var page = 'page1'; // change between homepage and page1
</script>
<div id="page1" class="map"></div>
homepage.php
<script>
var page = 'homepage'; // change between homepage and page1
</script>
<div id="homepage" class="map"></div>
And then you can switch between the settings depanding on the page:
var id, center, zoom;
switch(page){
case 'page1':
id = 'page1';
center = [45, 15];
zoom = 8;
break;
case 'hompage':
// fall through
default:
id = 'homepage';
center = [46, 15];
zoom = 5;
break;
}
var map = L.map(id, {
center: center,
minZoom: 2,
zoom: zoom,
scrollWheelZoom: false}
);
https://jsfiddle.net/falkedesign/nLbp8d17/
Related
I have a codepen at https://codepen.io/ericg_off/pen/qBoPQGX which demonstrates the issue.
I would like the marker to be drawn underneath the line.
How can I change the z-index of the layers to accomplish this?
Searching has suggested several potential solutions, but nothing appears to work.
HTML
<div id="map"></div>
CSS
#map {
height: 100vh;
}
#map >>> .my-icons {
background-color: rgba(0, 255, 0, 0);
}
JS
var map = L.map("map", {
// Set latitude and longitude of the map center (required)
center: [38, -77],
// Set the initial zoom level, values 0-18, where 0 is most zoomed-out (required)
zoom: 5
});
// Create a Tile Layer and add it to the map
var tiles = new L.tileLayer(
"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
{
attribution:
'© OpenStreetMap contributors',
minZoom: 3,
maxZoom: 8
}
).addTo(map);
divIcon = L.divIcon({
//html: '<i class="fa fa-map-marker fa-1x"></i>',
html: '<i class="fa fa-star fa-1x"></i>',
className: 'my-icons'
})
const markerLayer = L.layerGroup().addTo(map);
const lineLayer = L.layerGroup().addTo(map);
// markerLayer.setZIndex(-1000)
// markerLayer.bringToBack();
const from = [38, -77];
const to = [38, -100];
const fromMarker = L.marker(from, { icon: divIcon } ).addTo(lineLayer);
const line = L.polyline([from, to], { color: "green", weight: 1 }).addTo(markerLayer);
The tutorial on panes explains how to change the zIndex of a pane.
After reading the documentation on Panes and learning that the marker pane has a zindex of 600 and the overlay pane (where the lines are drawn) has a index of 400, I just needed to change the marker pane to a index of 300.
map.getPane('markerPane').style.zIndex = 300;
Updated the codepen with the answer.
i was use leaflet.js to draw about 10000 icon markers,because it is icon marker,so i cannot use circleMarker. I find a leaflet plugin Leaflet.Canvas-Markers,it can help me draw 10000 icon markers fast, but this plugin caused the click event to fail.
This is my code
var ciLayer = L.canvasIconLayer({}).addTo(leafletMap)
var icon = L.icon({
iconUrl: 'StructWell.png',
iconSize: [20, 18],
iconAnchor: [10, 9]
});
function markerClickHandler (e) {
console.log(e)
console.log()
}
let markers = []
SiteList.results.forEach((site, i) => {
var marker = L.marker([site.latitude, site.longitude], {icon: icon, title: JSON.stringify(site)})
marker.on('click', markerClickHandler)
// ciLayer.addMarker(marker)
markers.push(marker);
})
ciLayer.addLayers(markers);
function markerClickHandler do not work when i click the marker.
was I do some bug,or are there any more solutions. The key is large number of icon markers with click event.
thanks
Listener should be added like below:
ciLayer.addOnClickListener(function (e,data) {
console.log(data)
});
var map = L.map('map').setView([59.9578,30.2987], 10);
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors',
preferCanvas: true
}).addTo(map);
var ciLayer = L.canvasIconLayer({}).addTo(map);
ciLayer.addOnClickListener(function (e,data) {
console.log(data[0].data.mydata)
});
var icon = L.icon({
iconUrl: 'https://img.icons8.com/metro/26/000000/marker.png',
iconSize: [20, 18],
iconAnchor: [10, 9]
});
var markers = [];
for (var i = 0; i < 10000; i++) {
var marker = L.marker([58.5578 + Math.random()*1.8, 29.0087 + Math.random()*3.6], {icon: icon}).bindPopup("I Am "+i);
marker.mydata="I Am "+i
markers.push(marker);
}
ciLayer.addLayers(markers);
.map{
width: 100%;
height: 100px;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.3.1/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet-canvas-marker#0.2.0"></script>
<div class="map" id="map"></div>
You can check examples provided by Leaflet.Canvas-Markers.
Hope this will helps you.
I have this modal in my index.html:
<div id="myModal" class="modal">
<span class="close1">×</span>
<div id="mapImage1"></div>
<div id="caption"></div>
</div>
The <div id="mapImage1"> is the leaflet map <div>
Then I have the function, which should load the Leaflet map into the modal. The parameter image is the image which I would like to show on the leaflet map.
function modalImage(modal,image,modalDiv,text,close) {
// Get the modal
var modal = document.getElementById(modal);
var img = document.getElementById(image);
var modalDiv = document.getElementById(modalDiv);
console.log(modalDiv);
var captionText = document.getElementById(text);
img.onclick = function () {
modal.style.display = "block";
initLeafletimage(modalDiv,img);
captionText.innerHTML = this.alt;
}
// Get the <span> element that closes the modal
var span = document.getElementsByClassName(close)[0];
// When the user clicks on <span> (x), close the modal
span.onclick = function () {
modal.style.display = "none";
}
}
The map itself is generated by this code:
function initLeafletimage(map,image){
console.log(image.src)
var imgDimensions={width:300, height:300} //this is the height and width of the image. It hasn't been loaded yet.
var map = L.map(map, {
maxZoom: 24,
minZoom: -24,
crs: L.CRS.Simple
}).setView([imgDimensions.height/2, imgDimensions.width/2], 0);
var imageUrl = image.src;
var imageBounds = [
[imgDimensions.width , 0],
[0, imgDimensions.height]
];
L.imageOverlay(imageUrl, imageBounds).addTo(map);
}
modalImage('myModal','left','mapImage1','caption','close1');
The map is not even showing up in the modal.
What have I missed?
Unfortunately, like #ghybs pointed out, I missed to define the height and width of the map div. That is why no map was present. With this css it works perfectly:
#mapImage1{
height: 100%;
width: 100%;
position: fixed;
}
I am currently in the process of upgrading from version 2.1.5 to 3.1.1.
I ran into an issue with the maxNativeZoom option on tile layer.
Basically it looks like it is being ignored and the map keeps zooming displaying white tiles.
My expectation would be that the tiles should be autoscaled.
This worked fine in version 2.1.5.
Here are the fiddles:
2.1.5: https://jsfiddle.net/jfwkq0s4/4/
3.1.1: http://jsfiddle.net/dbpfcoqo/6/
Here is the small sample code from the fiddles above:
L.mapbox.accessToken = 'pk.eyJ1IjoidHZibG9tYmVyZyIsImEiOiJjaXZsZmpsMWwwNXBuMnRudmJqNGQyMjJwIn0.842ovgKydac51tg6b9qKbg';
var map = L.mapbox.map('map', null, { maxZoom: 20})
.setView([40, -74.50], 9);
var layer = new L.mapbox.tileLayer('mapbox.streets', { maxNativeZoom: 17, maxZoom: 20 });
map.addLayer(layer);
I am wondering if MapBox/Leaflet changed the way you need to set these values or maybe they are no longer supported in their current version?
The option is still listed in their documentation.
I appreciate any help!
This seems to be a bug in Mapbox.js starting with version 3.0.0 (which uses Leaflet 1.0.1 or 1.0.2 internally).
It is visible on Mapbox.js example page for over zoom tiles: https://www.mapbox.com/mapbox.js/example/v1.0.0/overzoom/
I see that you have already opened an issue on Mapbox.js repository: https://github.com/mapbox/mapbox.js/issues/1250
What seems to happen is that Mapbox correctly freezes the X and Y coordinates of the tile past maxNativeZoom, but not the Z (zoom) value. Therefore it displays totally incorrect tiles, if available.
This bug is specific to Mapbox.js, Leaflet behaves as expected:
var map = L.map('map', {
maxZoom: 20
}).setView([48.86, 2.35], 11);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors',
maxNativeZoom: 11,
maxZoom: 20
}).addTo(map);
var $zoomLevel = document.getElementById("zoomLevel");
map.on('zoomend', showZoomLevel);
showZoomLevel();
function showZoomLevel() {
$zoomLevel.innerHTML = map.getZoom();
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.0.2/dist/leaflet.css">
<script src="https://unpkg.com/leaflet#1.0.2/dist/leaflet-src.js"></script>
Zoom level: <span id='zoomLevel'></span>
<div id="map" style="height: 170px"></div>
Here is my fix. I am also going to send this to MapBox. There are two main issues.
The first issue is the minZoom and maxZoom are always being overwritten by the mapbox tile layer setting.
The second issue is the z point was not being set correctly based on the maxNativeZoom.
This seems to work for me. See code example for details.
var customTileLayer = function (url, options) {
var formatPattern = /\.((?:png|jpg)\d*)(?=$|\?)/;
var tileLayerExtend = L.mapbox.TileLayer.extend({
_setTileJSON: function (json) {
//util.strict(json, 'object');
/*We had to create a function for this since util is private in mapbox */
strict(json, 'object');
if (!this.options.format) {
var match = json.tiles[0].match(formatPattern);
if (match) {
this.options.format = match[1];
}
}
var minZoom = this.options.minZoom || json.minzoom || 0;
var maxZoom = this.options.maxZoom || json.maxzoom || 18;
L.extend(this.options, {
tiles: json.tiles,
attribution: this.options.sanitizer(json.attribution),
minZoom: minZoom,
maxZoom: maxZoom,
tms: json.scheme === 'tms',
// bounds: json.bounds && util.lbounds(json.bounds)
/*We had to create a function for this since util is private in mapbox */
bounds: json.bounds && lBounds(json.bounds)
});
this._tilejson = json;
this.redraw();
return this;
},
getTileUrl: function (tilePoint) {
var tiles = this.options.tiles,
index = Math.floor(Math.abs(tilePoint.x + tilePoint.y) % tiles.length),
url = tiles[index];
tilePoint.z = this._getZoomForUrl();
var templated = L.Util.template(url, tilePoint);
if (!templated || !this.options.format) {
return templated;
} else {
return templated.replace(formatPattern,
(L.Browser.retina ? this.scalePrefix : '.') + this.options.format);
}
}
});
return new tileLayerExtend(url, options);
};
var lBounds = function(_) {
return new L.LatLngBounds([[_[1], _[0]], [_[3], _[2]]]);
};
var strict = function (_, type) {
if (typeof _ !== type) {
throw new Error('Invalid argument: ' + type + ' expected');
}
};
L.mapbox.accessToken = 'pk.eyJ1IjoidHZibG9tYmVyZyIsImEiOiJjaXZsZmpsMWwwNXBuMnRudmJqNGQyMjJwIn0.842ovgKydac51tg6b9qKbg';
var map = L.mapbox.map('map', null, { maxZoom: 20})
.setView([40, -74.50], 9);
var layer = new customTileLayer('mapbox.streets', { maxNativeZoom: 17, maxZoom: 20 });
var $zoomLevel = document.getElementById("zoomLevel");
map.addLayer(layer);
$zoomLevel.innerHTML = map.getZoom();
map.on('zoomend', function(e) {
var zoom = e.target.getZoom();
$zoomLevel.innerHTML= zoom;
});
body { margin:0; padding:0; }
#container { position: absolute; top: 0; bottom: 0; width: 100%; height: 100%; }
#map { height: 100%; width:100%; }
<script src="https://api.mapbox.com/mapbox.js/v3.1.1/mapbox.js"></script>
<link href="https://api.mapbox.com/mapbox.js/v3.1.1/mapbox.css" rel="stylesheet" />
<div id="container">
<span id='zoomLevel'></span>
<div id='map'></div>
</div>
in index.html I woluld like to add two Heatmaps users can see by checkbox in menu top right corner.
menu show other stuff by code like this
layerControl.addOverlay(geojson, "H2OpenMap");
in this portion of the page (line 383 to line 397)
$.getJSON('api.php', {'wells': '1'}, function(remoteData){
var geojson = L.geoJson(remoteData, {
pointToLayer: function (feature, latlng) {
var icon = chooseIcon(feature['properties']);
var marker = L.marker(latlng, {icon: new h2icon( {iconUrl: icon} )} );
var markerText = buildPopup(feature, true, latlng);
marker.bindPopup(markerText);
return marker;
}
}).addTo(map);
layerControl.addOverlay(geojson, "H2OpenMap");
map.fitBounds(geojson.getBounds(), {'padding': [10,10]});
});
First heat should use data from the same code before, selected by
if(feature['drinking_water'] == 'yes' ) {...
}
Second heat should use data from the same code before, selected by
if(feature['drinking_water'] == 'no' ) {...
}
The goal is to have two heat maps, one for clean water resources the other for not clean water resources, both can be selected by ratio button.
I've find this code looks good but I'm not able to give him data to use to create heatmap.....
//--------------------https://www.patrick-wied.at/static/heatmapjs/plugin-leaflet-layer.html-----------//
$.getJSON('api.php', {'wells': '1'}, function(remoteData){
var geojson = L.geoJson(remoteData, {
pointToLayer: function (feature, latlng) {
var heatData = L.marker(latlng);
console.log(heatData);
//var heatData = L.marker([{lat: new latlng(lat), lng: new latlng(lng)}]);
}})});
/*var testData = {
max: 8,
data: [{lat: 24.6408, lng:46.7728, count: 3},{lat: 50.75, lng:-1.55, count: 1}, ...]
};*/
var cleanWater = heatData;// mettere in un array solo la posizione degli elementi che rispettano la seguente condizione: feature['drinking_water'] == 'yes'
var cfg = {
// radius should be small ONLY if scaleRadius is true (or small radius is intended)
// if scaleRadius is false it will be the constant radius used in pixels
"radius": 2,
"maxOpacity": .8,
// scales the radius based on map zoom
"scaleRadius": true,
// if set to false the heatmap uses the global maximum for colorization
// if activated: uses the data maximum within the current map boundaries
// (there will always be a red spot with useLocalExtremas true)
"useLocalExtrema": true,
// which field name in your data represents the latitude - default "lat"
latField: 'lat',
// which field name in your data represents the longitude - default "lng"
lngField: 'lng',
// which field name in your data represents the data value - default "value"
valueField: 'count'
};
var heatmapLayer = new HeatmapOverlay(cfg);
var map = new L.Map('map-canvas', {
center: new L.LatLng(25.6586, -80.3568),
zoom: 4,
layers: [baseLayer, heatmapLayer]
});
heatmapLayer.setData(cleanWater);
//------------------------//--------------------//--------------------//--------------------//--------------------*/
in the root project it's following file with complete code:
https://github.com/H2OpenMap/map/blob/master/index_heat_test.html
Simplifying your problem I try to suggest you this example ...
http://bl.ocks.org/d3noob/raw/8973028/
This a simple code that implements a Leaflet heat map.
If you see at the source code ...
<!DOCTYPE html>
<html>
<head>
<title>Simple Leaflet Map with Heatmap </title>
<meta charset="utf-8" />
<link
rel="stylesheet"
href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css"
/>
</head>
<body>
<div id="map" style="width: 600px; height: 400px"></div>
<script
src="http://cdn.leafletjs.com/leaflet-0.7/leaflet.js">
</script>
<script
src="http://leaflet.github.io/Leaflet.heat/dist/leaflet-heat.js">
</script>
<script src="2013-earthquake.js"></script>
<script>
var map = L.map('map').setView([-41.5546,174.146], 10);
mapLink =
'OpenStreetMap';
L.tileLayer(
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© ' + mapLink + ' Contributors',
maxZoom: 18,
}).addTo(map);
var heat = L.heatLayer(quakePoints,{
radius: 20,
blur: 15,
maxZoom: 17,
}).addTo(map);
</script>
</body>
.... you'll find that the data is simulated with a coordinate array that you can see here ...
http://bl.ocks.org/d3noob/raw/8973028/2013-earthquake.js
I think that you've to convert your geojson data in this format and all will work!
Cesare