In native Leaflet map, lib CRS attribute should be set as below
var mymap = L.map('mapid', {
center: [-1800, 1000],
zoom: 13,
crs: L.CRS.Simple,
minZoom: 0,
maxZoom: 13,
});
How to do that in react-leaflet, I had tried some things but nothing successful :/
<Map crs={CRS.useSimple()} center={[-1800, 1000]} zoom={13} doubleClickZoom={false} >
</Map>
But there is an error that CRS is not imported.
How to import CRS?
Where do I wrong?
I need to import CRS from native leaflet.
import React, { Component } from 'react';
import {Map} from 'react-leaflet'
import {CRS} from 'leaflet';
and then in MAP component
<Map center={[0, 0]} zoom={2} doubleClickZoom={false} crs={CRS.Simple}>
...
</Map
Related
I'm using Leaflet with Nuxt3, TypeScript and Composition API on a production website.
As we're getting more and more markers, I'd like to use leaflet.markercluster but I can't get how to make it work properly
Here's my setup :
leaflet.client.ts
import {
LIcon,
LMap,
LMarker,
LPopup,
LTileLayer,
} from "#vue-leaflet/vue-leaflet";
import L from "leaflet";
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.component("LMap", LMap);
nuxtApp.vueApp.component("LTileLayer", LTileLayer);
nuxtApp.vueApp.component("LMarker", LMarker);
nuxtApp.vueApp.component("LIcon", LIcon);
nuxtApp.vueApp.component("LPopup", LPopup);
return {
provide: {
L,
},
};
});
Map.vue
<client-only>
<l-map
ref="locationsMap"
:min-zoom="leafletOptions.minZoom"
:max-zoom="leafletOptions.maxZoom"
:zoom-animation="true"
:zoom="leafletOptions.zoom"
:center="leafletOptions.center"
:useGlobalLeaflet="false"
:options="{ tap: false }"
#ready="onLeafletReady">
<l-tile-layer :url="leafletOptions.url"/>
<template v-for="location in locations"
:key="location.id">
<l-marker
:lat-lng="[location.attributes.lat, location.attributes.long]"
v-if="location.attributes.active">
<div v-if="location.attributes.lat && location.attributes.long">
<l-popup class="text-center flex flex-col gap-y-4">
...
</l-popup>
<l-icon>
...
</l-icon>
</div>
</l-marker>
</template>
</l-map>
...
</client-only>
<script setup lang="ts">
import {LIcon, LMap, LMarker, LPopup, LTileLayer} from "#vue-leaflet/vue-leaflet";
import "leaflet/dist/leaflet.css";
const leafletOptions = ref({
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
minZoom: 5,
maxZoom: 13,
zoom: 5.5,
map: null,
center: [47.040182, 2.536054],
bounds: null,
overlayLocation: false,
colors: ["#ED722E", "#F6BE00", "#979B0B", "#DA2C81"],
});
// Setup and api calls to get locations
</script>
package.json
{
...,
"depencencies": {
"#vue-leaflet/vue-leaflet": "^0.7.0",
"leaflet": "^1.9.3",
"leaflet.markercluster": "^1.5.3",
},
"devDependencies": {
"nuxt": "^3.0.0",
"typescript": "^4.9.4"
"#types/leaflet.markercluster": "^1.5.1",
}
}
The thing is, now I try to group my markers by adding leaflet.markercluster. So I added something like this :
leaflet.client.ts
...
import "leaflet.markercluster";
import "leaflet.markercluster/dist/MarkerCluster.css";
import "leaflet.markercluster/dist/MarkerCluster.Default.css";
export default defineNuxtPlugin((nuxtApp) => {
...
return {
provide: {
L,
},
};
});
But now I don't know what to do next. Using L.markerClusterGroup() as the official documentation says does not work as we get a 500 error for using a client-side method with ssr.
I also tried to directly import in my component with import :
Map.vue
import { MarkerClusterGroup } from 'leaflet.markercluster';
const markersGroup = ref(null);
...
const onLeafletReady = async () => {
markersGroup.value = new MarkerClusterGroup() // NOT WORKING
await nextTick();
leafletObject.value = locationsMap.value;
leafletReady.value = true;
leafletObject.value.addLayer(markersGroup.value)
}
But we got the same problem as using L.anyMethod() by getting a 500 error.
I saw that Sam85 on this question has the package installed, but that was not the same problem. :/
Has anyone ever tried to make it work with Nuxt 3 ?
I have basic javascript code that uses a simple Leaflet map; I have TIFF files that I parse through, and then I can display these on the map though Layer Control, in a simple index.html file. I can't figure out how to show the TIFF data in react-leaflet though. I can parse the data properly, but react-leaflet only seems to take PNG or PNG url's, and I can't find any documentation or anything that shows how to show TIFF files. I'm sure I'm missing something simple, but it's super frustrating :(
This is my code with react, and react-leaflet. It's working + parsing the TIFF data, I just don't know how to add the data to the layerscontrol baselayer TileLayer...
import React, { useMemo, useState } from "react";
import {
TileLayer,
Marker,
Popup,
MapContainer,
LayersControl,
LayerGroup,
FeatureGroup,
Circle,
useMap,
} from 'react-leaflet';
import chroma from 'chroma-js';
import parseGeoraster from 'georaster';
import GeoRasterLayer from 'georaster-layer-for-leaflet';
import AddLocate from "../components/AddLocate";
import { Helmet } from 'react-helmet';
import sample from '../data/tmin.tiff';
const MapBody = () => {
const center = [0, 0];
let tmin_layer = '';
fetch(sample)
.then(response => response.arrayBuffer())
.then(arrayBuffer => {
parseGeoraster(arrayBuffer).then(georaster => {
const min = georaster.mins[0];
const max = georaster.maxs[0];
const range = georaster.ranges[0];
const scale = chroma.scale('Spectral').domain([1, 0]);
tmin_layer = new GeoRasterLayer({
georaster: georaster,
opacity: 0.7,
pixelValuesToColorFn: function (pixelValues) {
var pixelValue = pixelValues[0];
if (pixelValue === 0) return null;
const scaledPixelValue = (pixelValue - min) / range;
const color = scale(scaledPixelValue).hex();
return color;
},
resolution: 256
});
console.log("layer:", tmin_layer);
})
})
return (
<>
<Helmet>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
/>
</Helmet>
<MapContainer className="map" center={center} zoom={2} scrollWheelZoom={false} doubleClickZoom={true}>
<TileLayer
className="tile"
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
//prevents map duplicating
noWrap={true} />
<LayersControl position="topright">
<LayersControl.BaseLayer name="TOPO TESTING">
<TileLayer className="tiles" url="https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png"/>
</LayersControl.BaseLayer>
<LayersControl.BaseLayer name="TIFF TEST">
<TileLayer className="tiffy" url={tmin_layer}/>
</LayersControl.BaseLayer>
</LayersControl>
<AddLocate/>
</MapContainer>
</>
)
}
export default MapBody;
I have a site with mapbox, the map itself works fine, but I can't add markers to it.
I copied the code from one source on which everything works, but when I added it to my project, the markers shifted from the correct coordinates on the map and got even more shifted when approaching.
here's my code
import React, { useState } from "react";
import ReactDOM from "react-dom";
import ReactMapboxGl, { Layer, Marker } from "react-mapbox-gl";
import { observer } from "mobx-react-lite";
import state from "../../state/state";
const Map = ReactMapboxGl({
accessToken:
"pk.eyJ1IjoibmFnaHQiLCJhIjoiY2wyYTJrazZxMDFlbzNpbnp0eTNnOG44aCJ9.i3nyiAJBTDyWviIWhsX-Zg",
});
const IndexMap = observer(({ coordinats }) => {
return (
<div style={{ height: "100vh", width: "100%", overflow: "hidden" }}>
<Map
style="mapbox://styles/mapbox/streets-v9" // eslint-disable-line
containerStyle={{
height: "100%",
width: "100%",
}}
center={{
lat: 51.5285582,
lng: -0.2416815,
}}
zoom={[12]}
>
<Marker coordinates={[-0.2416815, 51.5285582]} anchor="bottom">
<h1>marker</h1>
</Marker>
</Map>
</div>
);
});
export default IndexMap;
I think there are not enough styles for the map to set them in the right location.
I don't know what the problem was. I just moved the project to the folder with the working file. The link to the folder with the working file -https://codesandbox.io/embed/pwly8?codemirror=1
Back to very basics. My leaflet map renders, I can even add a scale but I don't see the marker L.marker([45, 1]).addTo(map);. I suppose I don't need to add a default icon. Any clue?
The (very short) code follows exactly the Quick Start Guide: codesandbox
The 'good' version:
import "leaflet/dist/leaflet.css";
import L from "leaflet";
const map = L.map("map").setView([45, 1], 4);
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution:
'© OpenStreetMap contributors'
}).addTo(map);
L.control.scale().addTo(map);
L.marker([45, 1], {icon:
new L.Icon({iconUrl: 'https://unpkg.com/leaflet#1.6.0/dist/images/marker-icon.png'})
}).addTo(map);
<div id="map" style="height:100vh"></div>
The default marker Icon is not found over the leaflet package.
Use:
L.marker([45, 1], {icon:
new L.Icon({iconUrl: 'https://unpkg.com/leaflet#1.6.0/dist/images/marker-icon.png'})
}).addTo(map);
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' }));
}