Im currently encountering bad performance with my Leaflet Map while using the Overpass Library, especially when moving around on the Map although there are not a lot of Markers (less than 100). This is still a problem with limited Zoom Level to 13.
This is a simple example:
<html>
<head>
<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>
<script src="OverPassLayer.bundle.js"></script>
</head>
<body>
<div id="map" style="width: 100%; height: 90%; position: relative; outline: none;"></div>
<script>
var tiles = L.tileLayer('https://a.tile.openstreetmap.de/{z}/{x}/{y}.png', {
minZoom: 15,
attribution: '© OpenStreetMap'
}),
latlng = L.latLng(52.5207,13.4093);
var map = L.map('map',{center: latlng,
zoom: 17,
layers: [tiles],
maxZoom: 18,
preferCanvas: false,
});
var icon = new L.Icon({
iconUrl: 'leaf-green.png', //https://leafletjs.com/examples/custom-icons/leaf-green.png
shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/images/marker-shadow.png',
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
shadowSize: [41, 41]
});
var opl = new L.OverPassLayer({
query: 'node["amenity"="bench"]({{bbox}});out;', //show all Benches on Map
markerIcon: icon,
minZoom: 13,
});
map.addLayer(opl);
</script>
</body>
</html>
Maybe markercluster can be a solution to this, but how do I add Positions from Overpass to a markercluster Layer?
Are there other solutions to this?
Related
I am using the code below OpenLayers to view a static image with the following dimensions 43000 px x 4000px, 10mb. In the browser on the computer the image appears normally, but the mobile browser does not appear the image. Could you tell me what I should do to fix this problem.
<html>
<head>
<meta charset="utf-8">
<title>Sistema de Solicitação de Acesso (SSA) - Alternativo</title>
<link rel="stylesheet" href="https://openlayers.org/en/v3.20.1/css/ol.css" type="text/css">
<!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?
features=requestAnimationFrame,Element.prototype.classList,URL">
</script>
<script src="https://openlayers.org/en/v3.20.1/build/ol.js"></script>
<style>
.map {
width: auto;
height: 500px;
border: 5px outset black;
border-radius: 20px;
}
</style>
</head>
<body>
<div id="map" class="map"></div>
<script>
var extent = [0, 0, 50000, 1900];
var projection = new ol.proj.Projection({
code: 'xkcd-image',
units: 'pixels',
extent: extent
});
var map = new ol.Map({layers: [
new ol.layer.Image({
source: new ol.source.ImageStatic({
attributions: 'Criado por: Givanildo Silva de Amorim',
url: 'https://i.ibb.co/GHCdx84/Linhas-7-8-9-10-11-12-13.png',
projection: projection,
imageExtent: extent
})
})
],
target: 'map',
view: new ol.View({
projection: projection,
center: [1600, 900],
zoom: 7,
maxZoom: 14
})
});
</script>
</body>
</html
I'm using the open source Leaflet.js library to create a simple map.
I'm trying to solve a specific problem though. Markers are tied to a specific lat/lng on a map, which makes sense, but I need to be able to make a marker have a fixed offset position from another marker, without it being tied to a lat/lng center.
So for example, the map may look like this:
But when you zoom out, it'll look like this:
What I actually want is for the right marker to be a fixed offset away from the left marker, instead of being tied to a latlng, as such:
I've tried experimenting with unproject but I believe I'm going down the wrong path of how to handle this. It's unconventional what I'm doing but if anyone has any insight into how I could do this, it would be greatly appreciated.
In addition to project() and unproject() methods to calculate position of second marker you can also listen to zoom events on the map and update the position of the second marker in order to keep the desired distance in pixels.
Have a look at the following example.
var marker;
var pos = L.latLng(28.478226,-16.313488);
var mymap = L.map('mapid').setView(pos, 13);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, ' +
'CC-BY-SA, ' +
'Imagery © Mapbox',
id: 'mapbox.streets'
}).addTo(mymap);
L.marker(pos).addTo(mymap);
setLinkedMarkerAtDistance(180);
mymap.on('zoomstart', function() {
if (marker) {
mymap.removeLayer(marker);
}
});
mymap.on('zoomend', function() {
setLinkedMarkerAtDistance(180);
});
function setLinkedMarkerAtDistance(d) {
var p = mymap.project(pos, mymap.getZoom());
var p1 = p.add(L.point(d,0));
var pos1 = mymap.unproject(p1, mymap.getZoom());
if (marker) {
marker.setLatLng(pos1).addTo(mymap);
} else {
marker = L.marker(pos1).addTo(mymap);
}
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.4/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin=""/>
<script src="https://unpkg.com/leaflet#1.3.4/dist/leaflet.js" integrity="sha512-nMMmRyTVoLYqjP9hrbed9S+FzjZHW5gY1TWCHA5ckwXZBadntCNs8kEqAWdrb9O7rxbCaA4lKTIWjDXZxflOcA==" crossorigin=""></script>
<div id="mapid" style="width: 600px; height: 400px;">
I hope this helps!
This sounds like an XY problem to me: you want to display some extra info (possibly looking similar to a normal Marker) next to a Marker A (with some pixels offset), and you try with another Marker B; but Marker B is tied to Lat/Lng coordinates instead of pixels offset, so you ask for help on how to use unproject.
To achieve your original objective, a Leaflet DivIcon would indeed have been a more appropriate solution: a part of the <div> would contain your actual Marker Icon, and another part would contain your extra info. That way, it always stays at the desired position, without having to compute any (un)projection and without any JS event listener involved:
var paris = [48.86, 2.35];
var map = L.map('map').setView(paris, 11);
var divIcon = L.divIcon({
html: `
<img src="https://unpkg.com/leaflet#1.3.4/dist/images/marker-icon.png" />
<div class="extra-info">
Some extra info
</div>
`,
className: 'my-div-icon',
iconAnchor: [12, 41]
});
L.marker(paris, {
icon: divIcon
}).addTo(map);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
html,
body,
#map {
height: 100%;
margin: 0;
}
.extra-info {
position: absolute;
left: 188px;
bottom: -20px;
min-width: 120px;
background: yellow;
border: 1px solid red;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.4/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin="" />
<script src="https://unpkg.com/leaflet#1.3.4/dist/leaflet-src.js" integrity="sha512-+ZaXMZ7sjFMiCigvm8WjllFy6g3aou3+GZngAtugLzrmPFKFK7yjSri0XnElvCTu/PrifAYQuxZTybAEkA8VOA==" crossorigin=""></script>
<div id="map"></div>
An even more appropriate solution would have been to use a Leaflet Tooltip, typically with your predefined offset, permanent: true option, a specific direction and custom styling (with className):
var paris = [48.86, 2.35];
var map = L.map('map').setView(paris, 11);
L.marker(paris).bindTooltip('Some extra info', {
offset: [188, 0],
className: 'my-tooltip',
permanent: true,
direction: 'right',
interactive: true
}).addTo(map);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
html,
body,
#map {
height: 100%;
margin: 0;
}
.leaflet-tooltip.my-tooltip {
background-color: yellow;
border: 1px solid red;
box-shadow: none;
}
.leaflet-tooltip.my-tooltip::before {
content: none;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.4/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin="" />
<script src="https://unpkg.com/leaflet#1.3.4/dist/leaflet-src.js" integrity="sha512-+ZaXMZ7sjFMiCigvm8WjllFy6g3aou3+GZngAtugLzrmPFKFK7yjSri0XnElvCTu/PrifAYQuxZTybAEkA8VOA==" crossorigin=""></script>
<div id="map"></div>
Then if you really want your extra info to be styled and manipulated like a normal Leaflet Marker, another possible solution would be to use a custom Marker with modified iconAnchor, to account for your desired pixel offset:
var paris = [48.86, 2.35];
var map = L.map('map').setView(paris, 11);
var OffsetIcon = L.Icon.Default.extend({
options: {
// Subtract your desired offset.
iconAnchor: [12 - 188, 41]
}
});
L.marker(paris).addTo(map);
L.marker(paris, {
icon: new OffsetIcon()
}).addTo(map);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
html,
body,
#map {
height: 100%;
margin: 0;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.4/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin="" />
<script src="https://unpkg.com/leaflet#1.3.4/dist/leaflet-src.js" integrity="sha512-+ZaXMZ7sjFMiCigvm8WjllFy6g3aou3+GZngAtugLzrmPFKFK7yjSri0XnElvCTu/PrifAYQuxZTybAEkA8VOA==" crossorigin=""></script>
<div id="map"></div>
The following code shows a marker and a popup that shows the lat and long whenever I click on the map.
I want the marker to change color from blue to red, and I want the popup to be above the marker so that it doesn't cover the marker. How can I do that? Thank you.
<!DOCTYPE html>
<html>
<head>
<title>Quick Start - 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.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin=""/>
<script src="https://unpkg.com/leaflet#1.3.1/dist/leaflet.js" integrity="sha512-/Nsx9X4HebavoBvEBuyp3I7od5tA0UzAxs+j83KgC8PU0kgB4XiK4Lfe4y4cgBtaRJQEIFCW+oC506aPT2L1zw==" crossorigin=""></script>
</head>
<body>
<div id="mapid" style="width: 600px; height: 400px;"></div>
<script>
var mymap = L.map('mapid').setView([51.505, -0.09], 13);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, ' +
'CC-BY-SA, ' +
'Imagery © Mapbox',
id: 'mapbox.streets'
}).addTo(mymap);
L.marker([40.7127837, -74.0059413]).addTo(mymap)
.bindPopup("<b>Hello world!</b><br />I am a popup.").openPopup();
var popup = L.popup();
function onMapClick(e) {
L.marker([e.latlng.lat, e.latlng.lng]).addTo(mymap)
popup
.setLatLng(e.latlng)
.setContent("You clicked the map at " + e.latlng.toString())
.openOn(mymap);
}
mymap.on('click', onMapClick);
</script>
</body>
</html>
The marker uses an icon image to display, so you will need to create your own custom icon, with the iconUrl pointing at the image you want to use for the marker, and then tell the marker to use your custom icon when rendering. You can also specify the popupAnchor in the icon settings to move the popup away from the icon
Example (Leaflet docs)
var myIcon = L.icon({
iconUrl: 'my-icon.png',
iconSize: [38, 95],
iconAnchor: [22, 94],
popupAnchor: [-3, -76],
shadowUrl: 'my-icon-shadow.png',
shadowSize: [68, 95],
shadowAnchor: [22, 94]
});
L.marker([50.505, 30.57], {icon: myIcon}).addTo(map);
I want to display the tooltip centered (inside) of the marker.
Background
I want to display a count for each marker (first -> last) and I've found out I could do that with tooltip (Any better suggestions)
so my marker looks like this now,
var marker = L.marker(latlng, {icon: blueIcon}).bindTooltip(feature.properties.count,
{
permanent: true,
direction: 'right'
});
I couldn't find any further documentation on direction centered or similar.
The tooltip provides the functionality to see which was the first and last marker however it seems not to be best practice.
So my questions:
Is there a better solution than tooltip?
how can I display the count centered in the marker?
Example
Current:
wanted:
(Here I would make the background invis so I could just see the text.)
I've found out you could add direction: center.
Ref: http://leafletjs.com/reference-1.0.0.html#tooltip-direction
I've solved my problem with DivIcon
var numberIcon = L.divIcon({
className: "number-icon-default",
iconSize: [25, 41],
iconAnchor: [10, 44],
popupAnchor: [3, -40],
html: feature.properties.count
});
with the css like
.number-icon-default
{
background-image: url("#{request.contextPath}/lib/leaflet/images/marker-icon.png");
text-align:center;
color:Black;
text-shadow: 1px 1px #000000;
font-size: large;
font-weight: bold;
}
Result
Is there a better solution than tooltip?
Not necessarily "better" (which depends on your exact requirements), but a more simple solution would be to use a Marker Icon with some HTML text in it.
Many Leaflet plugins can provide you with such feature, e.g. Leaflet.extra-markers:
var map = L.map('map').setView([48.86, 2.35], 11);
var redMarker = L.ExtraMarkers.icon({
number: '42',
icon: 'fa-number',
markerColor: 'red',
shape: 'square',
prefix: 'fa'
});
L.marker([48.86, 2.35], {
icon: redMarker
}).addTo(map);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
<!-- Leaflet assets -->
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/leaflet#1.3.1/dist/leaflet-src.js" integrity="sha512-IkGU/uDhB9u9F8k+2OsA6XXoowIhOuQL1NTgNZHY1nkURnqEGlDZq3GsfmdJdKFe1k1zOc6YU2K7qY+hF9AodA==" crossorigin=""></script>
<!-- Leaflet.extramarkers assets -->
<link rel="stylesheet" href="https://unpkg.com/leaflet-extra-markers#1.0.6/src/assets/css/leaflet.extra-markers.css" />
<script src="https://unpkg.com/leaflet-extra-markers#1.0.6/src/assets/js/leaflet.extra-markers.js"></script>
<div id="map" style="height: 200px"></div>
I am very new to leaflet so I am only just trying to grasp the basics. When following the tutorial online provided by Leaflet, I am struggling to get the map to load. If I use the coordinates provided I have no issues, however if I change the coordinates, nothing loads.
Can anyone help? Here's what I have:
<!DOCTYPE html>
<html>
<head>
<title>Leaflet Web Map</title>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<style>
#map {
width: 960px;
height:500px;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
var map = L.map('map',{
center: [43.64701, -79.39425],
zoom: 15
});
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
</script>
this loads no bother but if I change the coordinates at all it doesn't load.
To change the map center you should change it in the map property: center: [43.00, -79.00].
var map = L.map('map',{
center: [43.00, -79.00],
zoom: 15
});
You should remember that first coordinate, latitude, takes number in range (-90, 90), while second one, longitude should be set in range (-180, 180). But anyway if you excess that second coordinate application will just calculate it's value as if it was in given ranges.
Maybe you mixed something up and tried to change it here L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',..? This line stands for loading basemap tiles, not centering the map.
Try to
var tileLayer = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png',
{
attribution: false
});
var map = L.map('map',
{
zoomControl: true,
layers: [tileLayer],
maxZoom: 18,
minZoom: 6
})
.setView([43.64701, -79.39425], 15);
setTimeout(function () { map.invalidateSize() }, 800);
I wasn't able to reproduce your problem. Changing the center still loads a map. (Click [Run Code Snippet] button, below)
var map = L.map('map', {
//center: [43.64701, -79.39425], //comment out one of the centers
center: [40, -80],
zoom: 15
});
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
<!DOCTYPE html>
<html>
<head>
<title>Leaflet Web Map</title>
<link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<style>
#map {
width: 960px;
height: 500px;
}
</style>
</head>
<body>
<div id="map"></div>
</body>
</html>
I noticed that you didn't have an end body, end html tag, so I added those.
What coordinates were you trying to change?