How can you put leaflet polylines in multiple panes? - leaflet

What am I doing wrong? The intent is to have a few (say 6) leafletjs panes, each containing many markers and polylines, so the panes can be hidden independently. Here is a simplified program showing just two lines and markers in jsfiddle. The problem is, the polylines all get grouped in the same SVG and all get hidden together. Each pane in the example should show one polyline and one marker.
I don't want to remove the polylines from the map to hide them, then recreating them would not perform well.
If needed, the polylines could be drawn using D3 on top of the leaflet map but I was hoping it could all be done in leaflet.
Thanks!
JS:
'use strict';
document.addEventListener("DOMContentLoaded", function(event) {
var map = L.map('map').setView([30.5, -0.09], 2);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
var pane1 = map.createPane('pane1');
var pane2 = map.createPane('pane2');
function hide(pane) {
pane.style.display = 'none';
}
function show(pane) {
pane.style.display = '';
}
let icon = new L.Icon.Default();
function dr(pane, latlng){
L.polyline([[45.421, -75.697], latlng], {
weight: 2,
pane: pane
}).addTo(map);
L.marker(latlng, {
icon: icon,
pane: pane
}).addTo(map);
}
// define two locations with lines from Ottawa
dr(pane1, [ 42.3732216, -72.5198537 ]);
dr(pane2, [ 35.9606384, -83.9207392 ]);
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function loop(){
for( var i = 0; i<100; i++){
hide(pane1);
show(pane2);
await sleep(1000);
hide(pane2);
show(pane1);
await sleep(1000);
}
}
loop();});
HTML:
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.5.1/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.6.0/leaflet-src.js" integrity="sha256-wc8X54qvAHZGQY6nFv24TKlc3wtO0bgAfqj8AutTIu0=" crossorigin="anonymous"></script>
<style>
html, body {
height: 100%;
margin: 0;
}
#map {
width: 900px;
height: 500px;
}
</style>
</head>
<body>
<div id='map'></div>
</body>
</html>
<script src="c.js"></script>

Related

MapQuest add text in flag icon

I have the following code and I want to add different text in each of the icons. Example for the location "Quebec" it should be entered "08h00" for "Beaupre" .. "15h00" etc..
<html>
<head>
<script src="https://api.mqcdn.com/sdk/mapquest-js/v1.3.2/mapquest.js"></script>
<link type="text/css" rel="stylesheet" href="https://api.mqcdn.com/sdk/mapquest-js/v1.3.2/mapquest.css"/>
<script type="text/javascript">
window.onload = function() {
L.mapquest.key = '';
// Geocode three locations, then call the createMap callback
L.mapquest.geocoding().geocode(['Quebec,Qc', 'Beaupre,Qc', 'Montmagny,Qc'], createMap);
function createMap(error, response) {
// Initialize the Map
var map = L.mapquest.map('map', {
layers: L.mapquest.tileLayer('map'),
center: [0, 0],
zoom: 12
});
// Generate the feature group containing markers from the geocoded locations
var featureGroup = generateMarkersFeatureGroup(response);
// Add markers to the map and zoom to the features
featureGroup.addTo(map);
map.fitBounds(featureGroup.getBounds());
}
function generateMarkersFeatureGroup(response) {
var group = [];
for (var i = 0; i < response.results.length; i++) {
var location = response.results[i].locations[0];
var locationLatLng = location.latLng;
// Create a marker for each location
var marker = L.marker(locationLatLng, {icon: L.mapquest.icons.flag()})
.bindPopup(location.adminArea5 + ', ' + location.adminArea3);
group.push(marker);
}
return L.featureGroup(group);
}
}
</script>
</head>
<body style="border: 0; margin: 0;">
<div id="map" style="width: 100%; height: 530px;"></div>
</body>
</html>
Could anyone help me please ?
Thanks.
Try setting the symbol for the flag like icon: L.mapquest.icons.flag({symbol:"08h00"})
More details here: https://developer.mapquest.com/documentation/mapquest-js/v1.3/l-mapquest-icons/

changing the default layer in leafletjs

In https://leafletjs.com/examples/layers-control/example.html there are two layers - Grayscale and Streets. It defaults to Grayscale but how would one change the default to Streets instead?
In that example there's this:
var map = L.map('map', {
center: [39.73, -104.99],
zoom: 10,
layers: [grayscale, cities]
});
I tried swapping the order of the variables in layers but that didn't do anything.
There's also this:
var baseLayers = {
"Grayscale": grayscale,
"Streets": streets
};
I tried reversing that, as well, without success.
I even tried renaming the names of the layers, thinking that it might be done alphabetically, but no such luck.
Any ideas?
It has to do with which layer has been added to the map. So remove the array layers from the map instance and add streets layer to the map. That will define the preselected layer.
<!DOCTYPE html>
<html>
<head>
<title>Layers Control Tutorial - Leaflet</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin="" />
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
<style>
html,
body {
height: 100%;
margin: 0;
}
#map {
width: 600px;
height: 400px;
}
</style>
</head>
<body>
<div id='map'></div>
<script>
var cities = L.layerGroup();
L.marker([39.61, -105.02]).bindPopup('This is Littleton, CO.').addTo(cities),
L.marker([39.74, -104.99]).bindPopup('This is Denver, CO.').addTo(cities),
L.marker([39.73, -104.8]).bindPopup('This is Aurora, CO.').addTo(cities),
L.marker([39.77, -105.23]).bindPopup('This is Golden, CO.').addTo(cities);
var mbAttr = 'Map data © OpenStreetMap contributors, ' +
'Imagery © Mapbox',
mbUrl = 'https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw';
var map = L.map('map', {
center: [39.73, -104.99],
zoom: 10,
});
var grayscale = L.tileLayer(mbUrl, {
id: 'mapbox/light-v9',
tileSize: 512,
zoomOffset: -1,
attribution: mbAttr
});
var streets = L.tileLayer(mbUrl, {
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1,
attribution: mbAttr
}).addTo(map)
var baseLayers = {
"Streets": streets,
"Grayscale": grayscale
};
var overlays = {
"Cities": cities
};
L.control.layers(baseLayers, overlays).addTo(map);
</script>
</body>
</html>

Using Leaflet in a Svelte App - the Correct Way

I have written a Svelte component that displays a map using Leaflet. The following code of the component works.
I'm just wondering if this is the way to do it, or if there is a "more correct" or "smarter" way? Especially in view of the await import('leaflet'); in loadMap() and the way the CSS is loaded from the CDN in onMount()...
<script>
import { onMount } from 'svelte';
let map;
onMount(() => {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'https://unpkg.com/leaflet#1.6.0/dist/leaflet.css';
link.onload = () => loadMap();
document.head.appendChild(link);
return () => {
map.remove();
link.parentNode.removeChild(link);
};
});
async function loadMap() {
await import('leaflet');
map = L.map('map').setView([49, 12], 13);
L.tileLayer('https://a.tile.openstreetmap.org/{z}/{x}/{y}.png ', {
attribution:
'Map data © OpenStreetMap contributors, CC-BY-SA',
maxZoom: 18,
}).addTo(map);
}
</script>
<style>
#map {
height: 480px;
}
</style>
<div id="map" />
You could use <svelte:head> to load the css and javascript: According to the docs:
This element makes it possible to insert elements into document.head. During server-side rendering, head content is exposed separately to the main html content.
So the head component would look like this:
<svelte:head>
<link
rel="stylesheet"
href="https://unpkg.com/leaflet#1.6.0/dist/leaflet.css"
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin="" />
<script
src="https://unpkg.com/leaflet#1.6.0/dist/leaflet.js"
integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="
crossorigin="">
</script>
</svelte:head>
Here is a full REPL to play around.

Leaflet.Deflate with Leaflet.markercluster does not show cluster coverage on hover

when you mouse over a cluster, Leaflet.markercluster should show the bounds of its markers. this is the (simplified) code I am using:
map = new L.Map('map');
L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 13,
attribution: 'Map data © OpenStreetMap contributors'
}
).addTo(map);
map.setView([51.505, -0.09], 11);
let deflate_features = L.deflate({
minSize: 40,
markerCluster: true
});
deflate_features.addTo(map);
var polygon = L.polygon([
[51.509, -0.08],
[51.503, -0.06],
[51.51, -0.047]
]);
deflate_features.addLayer(polygon);
var polyline = L.polyline([
[51.52, -0.05],
[51.53, -0.10],
], {
color: 'red'
});
deflate_features.addLayer(polyline);
#map {position: absolute; top: 0; bottom: 0; left: 0; right: 0;}
<html>
<head>
<link href="https://unpkg.com/leaflet#1.3.3/dist/leaflet.css" rel="stylesheet" />
<link href="https://unpkg.com/leaflet.markercluster#1.3.0/dist/MarkerCluster.css" rel="stylesheet" />
<link href="https://unpkg.com/leaflet.markercluster#1.3.0/dist/MarkerCluster.Default.css" rel="stylesheet" />
<script src="https://unpkg.com/leaflet#1.3.3/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.markercluster#1.3.0/dist/leaflet.markercluster.js"></script>
<script src="https://unpkg.com/Leaflet.Deflate#1.0.0-alpha.2/dist/L.Deflate.js"></script>
</head>
<body>
<div id="map"></div>
</body>
</html>
why does the cluster coverage on hover not show?
coverage is not shown if there are only 2 objects... :|
adding a third object, e.g.:
var polyline2 = L.polyline([
[51.535, -0.1],
[51.525, -0.05],
], {
color: 'green'
});
deflate_features.addLayer(polyline2);
enables cluster coverage:

Leaflet : remove layer if zoom level greater than 9

I built a heatmap on Leaflet.
My first goal is to see the heatmap when you open the map. The second goal is not to view the heatmap if the zoom level is greater than 9.
I tried this :
if (map.getZoom() >9 {
map.removeLayer (heatmapLayer);
};
But it did not work.
Would you have any suggestions ?
Thanks !
Here is the code :
<!DOCTYPE html>
<html lang="en">
<head>
<title>Application - version 1.0</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.6.3/leaflet.css" />
<link rel="stylesheet" href="style_p.css" />
<style type="text/css">
html, body, #map {
margin: 0;
margin-top: 0%;
width: 100%;
height: 100%;
};
</style>
</head>
<!-- Favicon -->
<link rel="icon" href="california.ico" />
<body>
<div id="map"></div>
<script src="http://cdn.leafletjs.com/leaflet-0.6.3/leaflet-src.js"></script>
<script src="http://maps.google.com/maps/api/js?v=3.2&sensor=false"></script>
<script src="jquery.js"></script>
<script type="text/javascript" src="heatmap.js"></script>
<script type="text/javascript" src="heatmap-leaflet.js"></script>
<script type="text/javascript" src="sloopjohnb.js"></script>
<script src="google.js"></script>
<script src="leaflet_search.js"></script>
<script type="text/javascript" charset="utf-8">
$(function() {
var osm = new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
var base = new L.TileLayer('http://129.206.74.245:8001/tms_r.ashx?x={x}&y={y}&z={z}');
var ggl2 = new L.Google('SATELLITE');
var heatmapLayer;
heatmapLayer = L.TileLayer.heatMap({
radius: 10,
opacity: 0.8,
gradient: {
0.45: "rgb(0,0,255)",
0.55: "rgb(0,255,255)",
0.65: "rgb(0,255,0)",
0.95: "yellow",
1.0: "rgb(255,0,0)"
}
});
var Data1={
max: 1,
data: sloopjohnb
};
heatmapLayer.addData(Data1.data);
var baseMaps = {
"Fond OSM": osm,
"Fond de carte de base": base,
"Photo. aérienne Google" : ggl2
};
var overlayMaps = {
'Heatmap': heatmapLayer
};
map = new L.Map('map', {
minZoom : 1,
maxZoom : 11,
boxZoom : true,
layers: [base, heatmapLayer]
});
var controls = L.control.layers(baseMaps, overlayMaps, {position: 'bottomright'});
controls.addTo(map);
map.addControl(L.control.search());
L.control.scale().addTo(map);
map.attributionControl.addAttribution('Heatmap.js');
map.setView(new L.LatLng(39.291,-5.9765),2);
// Disparition de la heatmap en fct du zoom
map.on('zoomend', function () {
if (map.getZoom() > 9) {
map.removeLayer(heatmapLayer);
}
});
});
</script>
</body>
</html>
Are you sure you are creating the listener correctly?
For example, this seems like it should be called when the user zooms. So something like:
Edited
map.on('zoomend', function () {
if (map.getZoom() > 9 && map.hasLayer(heatmapLayer)) {
map.removeLayer(heatmapLayer);
}
if (map.getZoom() < 9 && map.hasLayer(heatmapLayer) == false)
{
map.addLayer(heatmapLayer);
}
});
If you ONLY want the layer added/removed based on zoom, don't add it to your layer control here:
var controls = L.control.layers(baseMaps, overlayMaps, {position: 'bottomright'});
controls.addTo(map);
You will just have to make sure you are doing your adding/removing when it is necessary. Try messing with this set up a little and see where you get. Also, the Documentation is well written regarding the use of L.tileLayer
You can use the leaflet-zoom-show-hide library to do it. This will automatically show/hide your layers as you zoom.
zsh = new ZoomShowHide(map);
var marker1 = L.marker([50.096, 14.425]);
// minzoom, maxzoom
zsh.addLayer(marker1, 10, 13);
var marker2 = L.marker([50.076, 14.425]);
zsh.addLayer(marker2, 8, null);