How can you position zoom controls to bottom right? - leaflet

I'm working with ngx-leaflet. By default the map shows the zoom controls on the top left. However I cannot find how the positioning of this can be changed.
Here is an outdated method:
options = {
layers: L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 10, attribution: '...' }),
zoom: 5,
zoomControl: false,
center: L.latLng(46.879966, -121.726909)
};
mapReady(map: L.Map) {
map.addControl(L.control.zoom({ position: 'bottomright' }));
}
.
<div class="leaflet-container grow z-0" leaflet [leafletZoom]="leafletZoom" [leafletCenter]="leafletCenter" (leafletMapReady)="($event)">
<div [leafletLayer]="tileLayer"></div>
<div *ngFor="let marker of markerLayers " [leafletLayer]="marker"></div>
</div>
source
Is there an updated way to do this with the latest version of ngx-leaflet (3.0)?
Here's a screenshot that shows that there isn't a zoom method on the control object:

Since you're using direct imports, you want to do the following:
import { control, Map, latLng, tileLayer } from 'leaflet';
options = {
layers: tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 10, attribution: '...' }),
zoom: 5,
zoomControl: false,
center: latLng(46.879966, -121.726909)
};
mapReady(map: Map) {
map.addControl(control.zoom({ position: 'bottomright' }));
}

Related

How to add I3SLoader 3dtile layer (deck.gl) integrated with mapbox

I am trying to add arcgis 3d layer in mapbox with DeckGL. But I have this error (Uncaught TypeError: Tile3DLayer is not a constructor)
If I could bring data from arcgis sceneserver ,I try add two maps like compare(mapbox gl swipe tool) them.
maybe there are different ways to solve this problem. Taking the arcgis data I need and calling two maps on the same web page. Then make a presentation with the comparison tool between these maps.
<html>
<head>
<title>deck.gl + Mapbox Integration</title>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<script src="https://unpkg.com/deck.gl#^6.2.0/deckgl.min.js"></script>
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v0.50.0/mapbox-gl.js"></script>
<link rel="stylesheet" type="text/css" href="https://api.tiles.mapbox.com/mapbox-gl-js/v0.50.0/mapbox-gl.css">
<script src="https://unpkg.com/#loaders.gl/i3s#2.1.6/dist/dist.min.js"></script>
</head>
<body>
<div id="map" style="width: 100vw; height: 100vh"></div>
</body>
<script type="text/javascript">
const { MapboxLayer, ScatterplotLayer } = deck;
// Get a mapbox API access token
mapboxgl.accessToken = 'pk.eyJ1IjoidWJlcmRhdGEiLCJhIjoiY2pudzRtaWloMDAzcTN2bzN1aXdxZHB5bSJ9.2bkj3IiRC8wj3jLThvDGdA';
// Initialize mapbox map
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v9',
center: [-74.50, 40],
zoom: 9
});
const {DeckGL, Tile3DLayer} = deck;
const {I3SLoader} = loaders;
const deckgl = new DeckGL({
controller: true,
layers: [
new Tile3DLayer({
id: 'tile-3d-layer',
data:
'https://tiles.arcgis.com/tiles/z2tnIkrLQ2BRzr6P/arcgis/rest/services/SanFrancisco_Bldgs/SceneServer/layers/0',
loader: I3SLoader,
onTilesetLoad: (tileset) => {
const {zoom, cartographicCenter} = tileset;
const [longitude, latitude] = cartographicCenter;
const viewState = {
...deckgl.viewState,
zoom: zoom + 2.5,
longitude,
latitude
};
deckgl.setProps({initialViewState: viewState});
}
})
]
});
map.on('load', () => {
map.addLayer(deckgl);
});
</script>
</html>
I'm using React, the core code is here, hope I can help you.
// import { MapboxLayer } from '#deck.gl/mapbox';
// import {I3SLoader} from '#loaders.gl/i3s';
// import { Tile3DLayer } from '#deck.gl/geo-layers';
// import mapboxgl from 'mapbox-gl';
mapboxgl.accessToken = 'your-token';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
center: [-122.51473530281777,37.70463582140094],
zoom: 13
});
const layer = new MapboxLayer({
id:'i3s',
type: Tile3DLayer,
data: 'https://tiles.arcgis.com/tiles/z2tnIkrLQ2BRzr6P/arcgis/rest/services/SanFrancisco_Bldgs/SceneServer/layers/0',
loader: I3SLoader
});
map.on('load', () => {
map.resize();
map.addLayer(layer);
});

Leaflet zooms so now and than too much on clicking a cluster

Leaflet zooms so now and than too much on clicking a cluster.
A small part of 1 marker is shown on the right and a small part from the other marker is shown on the left side of the map.
My workaround is counting markers in scope and re-adjust the zoomlevel when the counter = 0.
Shouldn't that be in the zoomcalculation of leaflet?
The zoom correction:
mcg.on('clusterclick', function () {
if (markersInScope == 0) {
var zoom = map.getZoom();
map.setZoom(zoom - 1);
}
});
You could try adjusting the zoom to fit the bounds of the mcg and add some padding
mcg.on('clusterclick', function () {
map.fitBounds(mcg.getBounds().pad(0.5));
}
});
If you add the markers to a featureGroup, the bounds for the group will available to you:
Here is a sample file from Leaflet:
<!DOCTYPE html>
<html>
<head>
<title>Leaflet debug page</title>
<link rel="stylesheet" href="../../dist/leaflet.css" />
<link rel="stylesheet" href="../css/screen.css" />
<script src="../leaflet-include.js"></script>
</head>
<body>
<div id="map" style="width: 600px; height: 600px; border: 1px solid #ccc"></div>
<button onclick="geojsonLayerBounds();">Show GeoJSON layer bounds</button>
<button onclick="featureGroupBounds();">Show feature group bounds</button>
<script src="geojson-sample.js"></script>
<script>
var osmUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
osmAttrib = '© OpenStreetMap contributors',
osm = L.tileLayer(osmUrl, {maxZoom: 18, attribution: osmAttrib}),
rectangle,
featureGroup;
var map = new L.Map('map', {
center: new L.LatLng(0.78, 102.37),
zoom: 7,
layers: [osm]
});
var geojson = L.geoJson(geojsonSample, {
style: function (feature) {
return {color: feature.properties.color};
},
onEachFeature: function (feature, layer) {
var popupText = 'geometry type: ' + feature.geometry.type;
if (feature.properties.color) {
popupText += '<br/>color: ' + feature.properties.color
}
layer.bindPopup(popupText);
}
});
geojson.addLayer(new L.Marker(new L.LatLng(2.745530718801952, 105.194091796875)))
var eye1 = new L.Marker(new L.LatLng(-0.7250783020332547, 101.8212890625));
var eye2 = new L.Marker(new L.LatLng(-0.7360637370492077, 103.2275390625));
var nose = new L.Marker(new L.LatLng(-1.3292264529974207, 102.5463867187));
var mouth = new L.Polyline([
new L.LatLng(-1.3841426927920029, 101.7333984375),
new L.LatLng(-1.6037944300589726, 101.964111328125),
new L.LatLng(-1.6806671337507222, 102.249755859375),
new L.LatLng(-1.7355743631421197, 102.67822265625),
new L.LatLng(-1.5928123762763, 103.0078125),
new L.LatLng(-1.3292264529974207, 103.3154296875)
]);
map.addLayer(eye1).addLayer(eye2).addLayer(nose).addLayer(mouth);
featureGroup = new L.FeatureGroup([eye1, eye2, nose, mouth]);
map.addLayer(geojson);
map.addLayer(featureGroup);
function geojsonLayerBounds() {
if (rectangle) {
rectangle.setBounds(geojson.getBounds());
} else {
rectangle = new L.Rectangle(geojson.getBounds());
map.addLayer(rectangle);
}
}
function featureGroupBounds() {
if (rectangle) {
rectangle.setBounds(featureGroup.getBounds());
} else {
rectangle = new L.Rectangle(featureGroup.getBounds());
map.addLayer(rectangle);
}
}
</script>
</body>
</html>

MapBox markers Move on zooming

I'm working on MapBoxgl and I want to add several markers.
Here is my index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link href=" /assets/css/bootstrap.min.css " rel="stylesheet" />
<link href=" /assets/css/mapbox-gl.css " rel="stylesheet" />
<link href=" /assets/css/main.css " rel="stylesheet" />
</head>
<body>
<div id="map"></div>
<script src="/assets/js/mapbox-gl.js"></script>
<script src="/assets/js/map-style.js"></script>
</body>
</html>
This is map-style.js:
var map = new mapboxgl.Map({
container: 'map',
center: [57.3221, 33.5928],
zoom: 5,
style: style
});
var geojson = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [30.61, 46.28]
},
properties: {
title: 'point 1',
description: 'point 1 Description',
message: 'point1',
iconSize: [25, 25]
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [30.62, 46.2845]
},
properties: {
title: 'point 2',
description: 'point 2 Description',
message: 'point 2',
iconSize: [25, 25]
}
}]
};
map.on('load', function () {
// add markers to map
geojson.features.forEach(function(marker) {
// create a DOM element for the marker
var el = document.createElement('div');
el.className = 'markers';
el.style.backgroundImage = 'url(assets/marker-azure.png)';
//el.style.width = marker.properties.iconSize[0] + 'px';
el.style.height = marker.properties.iconSize[1] + 'px';
el.addEventListener('click', function() {
window.alert(marker.properties.message);
});
// add marker to map
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.addTo(map);
});
});
And following is main.css portion related to map and marker:
#map { position:absolute; top:0; bottom:0; width:100% }
.markers {
display: absolute;
border: none;
border-radius: 50%;
cursor: pointer;
padding: 0;
}
So, my problem is that when I add width property to markers, their icon be displayed correctly (with a bit stretch) but they are in wrong coordinate and move on zoom, like picture below:
On the other hand, if width property is eliminated, they are in right place and does not move on zooming, but they are very stretched and in fact as wide as screen (following image):
It's noteworthy that I've used bootstrap. Can it be the reason of this? If not, what's the problem?
Thanks
import 'mapbox-gl/dist/mapbox-gl.css';
Adding import css works for me.
I found the solution and share it here with others who will encounter this problem. The problem caused because of using a not-most-recent version of the library. After upgrading to the latest release, I could get rid of that problem.
Note that these kinds of problems sometimes occur, when you use npm. Make sure that the library is downloaded completely and It's the latest release.
Latest releases of MapBox can be found at here.
had similar issue, the marker seemed to change position on zoom in/out, fixed it by setting offset, thought to share if it can help others, here is the fiddle
// add marker to map
var m = new mapboxgl.Marker(el, {offset: [0, -50/2]});
m.setLngLat(coordinates);
m.addTo(map);
(Using mapbox 1.13.0)
I had a similar issue where the popups weren't displaying and would change position based on zoom.
Mapbox officially states that you need to include the css file to have markers and popups work as expected.
https://docs.mapbox.com/mapbox-gl-js/guides/install/
HOWEVER, you can also copy that css directly into a component and use that as an element. For example:
export default function MarkerMapTest(props) {
const mapContainer = React.useRef(null)
const map = React.useRef(null)
const elemRef = React.useRef(null)
React.useEffect(() => {
map.current = new mapboxgl.Map({
container: mapContainer.current,
style: "mapbox://styles/mapbox/dark-v10",
center: [151.242, -33.9132],
zoom: 14,
})
const marker = new mapboxgl.Marker({
element: elemRef.current,
})
.setLngLat([151.242, -33.9132])
.addTo(map.current)
}, [])
return (
<div
style={{ width: 600, height: 600, backgroundColor: "gray" }}
ref={mapContainer}
>
<div
style={{
width: 30,
height: 30,
borderRadius: 15,
backgroundColor: "red",
position: "absolute", // !
top: 0, // !
left: 0, // !
}}
ref={elemRef}
/>
</div>
In my case the svg I used had some space around the real content. That way it seemed for me that the marker was moving. A simple fix was to remove the space around the content (e.g. with the "Resize page to drawing or selection" option of inkscape: https://graphicdesign.stackexchange.com/a/21638)
Also it is important to set display: block on the svg-marker. See: https://stackoverflow.com/a/39716426/11603006

Markers aren't working properly when I use them on a component

So I start using leaflet on my site, and I manage to make a search in which with the name of my items, I could show them. the problem is that I need to display information on click, but my markers aren't clickable.
here is my component:
<template>
<div id="mapid" style="width: 600px; height: 400px"></div>
</template>
<script>
var swal = require('sweetalert');
var config = require('../../config.js');
var Vue = require('vue');
name: 'mapOrganization',
data: function(){
return {
L : {},
}
},
ready: function(){
var L = require('../../lib/leaflet/leaflet.js')
L.Icon.Default.imagePath = '../../lib/leaflet/images';
this.initMap();
}
methods: {
initMap: function(organizations) {
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.eyJ1IjoibWFwYm94IiwiYSI6ImNpandmbXliNDBjZWd2M2x6bDk3c2ZtOTkifQ._QA7i5Mpkd_m30IGElHziw', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, ' +
'CC-BY-SA, ' +
'Imagery © Mapbox',
id: 'mapbox.streets'
}).addTo(mymap);
L.marker([51.5, -0.09]).addTo(mymap).bindPopup("<b>Hello world!</b><br />I am a popup.").openPopup();
L.circle([51.508, -0.11], 500, {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5
}).addTo(mymap).bindPopup("I am a circle.");
L.polygon([
[51.509, -0.08],
[51.503, -0.06],
[51.51, -0.047]
]).addTo(mymap).bindPopup("I am a polygon.");
var popup = L.popup();
function onMapClick(e) {
popup
.setLatLng(e.latlng)
.setContent("dasd" + e.latlng.toString())
.openOn(mymap);
}
mymap.on('click', onMapClick);
}
}
I have try with the Option {clickable: true}, still not working. I'm using the simple example leaflet give on start.

Leaflet how to increase maxZoom

I am using Leaflet in my application and I need to zoom more than 18 levels (19 or 20 will be enough I think). But when I zoom more than 18 levels, the map image disappears leaving only a grey plane.
Here is the html:
<div id="map"></div>
Here is the js:
var options = {
maxZoom: 19,
minZoom: 18
};
$timeout(function() {
$scope.map = L.map('map', options).setView([38.62276209666611, 34.70849695797369], 18);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© Example'
}).addTo($scope.map);
$scope.map.dragging.disable();
});
I already tried these:
map.options.minZoom = 18;
map.options.maxZoom = 19;
And maxNativeZoom.
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© Example',
maxNativeZoom:19,
maxZoom:25
}).addTo($scope.map);
maxNativeZoom is an option of L.TileLayer, not an option of L.Map. This is properly documented in the Leaflet reference.
See a working example.
Also set maxZoom to tileLayer
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© Example',
maxZoom: 20
}).addTo($scope.map);
here is a Mapbox configuration, I found that the perfect zoom settings for me are "maxNativeZoom" : 19, "maxZoom": 20, you can increase the maxZoom value, but you can't increase "maxNativeZoom" value above 19 because it will show gray tiles
L.tileLayer("http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
{"attribution": "Mapbox", "detectRetina": false, "maxNativeZoom": 19, "maxZoom": 20, "minZoom": 0, "noWrap": false, "opacity": 1, "subdomains": "abc", "tms": false})