Closed MathisBarre closed 3 years ago
Same here.
https://github.com/ghybs/leaflet-defaulticon-compatibility this one seems fix the issue for me.
Interesting, thanks
For the moment I did this:
<Marker
position={[51.505, -0.09]}
icon={L.divIcon({
iconSize: [size, size],
iconAnchor: [size / 2, size + 9],
className: "mymarker",
html: "😁",
})}
>
https://github.com/ghybs/leaflet-defaulticon-compatibility this one seems fix the issue for me.
Looks like it's working well ! Thanks !
No need for extra libs!
Simply create a PNG icon (64x64px in my case), put it in /public
, and then create an icon instance:
import { icon } from "leaflet"
const ICON = icon({
iconUrl: "/marker.png",
iconSize: [32, 32],
})
and use it like this:
<Marker icon={ICON} position={...} />
Yessssss, this is better than using the global variable L
The workarounds are nice, but for default behavior, i.e. showing the default Leaflet marker icon, it should work out of the box. Since we're talking about React here, which most of us use with webpack (via CRA), it should work to just import the CSS from app code, not imported from a CDN (as in the setup guide code) or at least put a warning in the docs, saying that Leaflet CSS doesn't play nice with webpack and you have to do this and that.
I just import "leaflet/dist/leaflet.css"
but yeah for the marker a working default would be nice
this seems to still be broken :(
this seems to still be broken :(
That's true but the workaround are still valid
Yeah https://github.com/PaulLeCam/react-leaflet/issues/808#issuecomment-747719927 is really cool. :)
You can create an intermediary component which injects this ICON
.
Yeah #808 (comment) is really cool. :)
You can create an intermediary component which injects this
ICON
.
I tried to create an intermediary component:
import {divIcon, Marker} from 'leaflet';
const ICON = divIcon();
export default function DivIconMarker(props) {
return <Marker icon={ICON} {...props} />
}
Loading this component dynamically into a Next.js page component produces an error:
If you're using create-react-app
, this will fix broken Marker images:
import L from 'leaflet';
import markerIcon2x from 'leaflet/dist/images/marker-icon-2x.png';
import markerIcon from 'leaflet/dist/images/marker-icon.png';
import markerShadow from 'leaflet/dist/images/marker-shadow.png';
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
iconUrl: markerIcon,
iconRetinaUrl: markerIcon2x,
shadowUrl: markerShadow,
})
If you're curious why the old fix at the start of this thread does not work, it is because the default Webpack file-loader
configuration (which is used by create-react-app
) does not allow using require()
for loading files.
I've tried this fix found in another old github issue :
import L from 'leaflet'; delete L.Icon.Default.prototype._getIconUrl; L.Icon.Default.mergeOptions({ iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'), iconUrl: require('leaflet/dist/images/marker-icon.png'), shadowUrl: require('leaflet/dist/images/marker-shadow.png') });
If you're using
create-react-app
, this will fix broken Marker images:import L from 'leaflet'; import markerIcon2x from 'leaflet/dist/images/marker-icon-2x.png'; import markerIcon from 'leaflet/dist/images/marker-icon.png'; import markerShadow from 'leaflet/dist/images/marker-shadow.png'; delete L.Icon.Default.prototype._getIconUrl; L.Icon.Default.mergeOptions({ iconUrl: markerIcon, iconRetinaUrl: markerIcon2x, shadowUrl: markerShadow, })
If you're curious why the old fix at the start of this thread does not work, it is because the default Webpack
file-loader
configuration (which is used bycreate-react-app
) does not allow usingrequire()
for loading files.I've tried this fix found in another old github issue :
import L from 'leaflet'; delete L.Icon.Default.prototype._getIconUrl; L.Icon.Default.mergeOptions({ iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'), iconUrl: require('leaflet/dist/images/marker-icon.png'), shadowUrl: require('leaflet/dist/images/marker-shadow.png') });
Awesome, using NextJS and create-next-app
and it works perfectly fine,
Only needs the src of the imported images instead of the object.
import L from 'leaflet';
import markerIcon2x from 'leaflet/dist/images/marker-icon-2x.png';
import markerIcon from 'leaflet/dist/images/marker-icon.png';
import markerShadow from 'leaflet/dist/images/marker-shadow.png';
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
iconUrl: markerIcon.src,
iconRetinaUrl: markerIcon2x.src,
shadowUrl: markerShadow.src,
})
Awesome, using NextJS and
create-next-app
and it works perfectly fine
Hmm, @DarkSuniuM's solution didn't work for me, using Next.js: browser was getting 404 on http://localhost:3000/[object Module]
. I'm not sure if Next or Leaftlet (or npm or something else) is breaking it.
My solution was, instead of any code changes, just to put the files it's looking for in a place where Next can find them: mkdir public && cp node_modules/leaflet/dist/images/* public
.
No need for extra libs!
Simply create a PNG icon (64x64px in my case), put it in
/public
, and then create an icon instance:import { icon } from "leaflet" const ICON = icon({ iconUrl: "/marker.png", iconSize: [32, 32], })
and use it like this:
<Marker icon={ICON} position={...} />
Yes, there is. Although this seems like a good solution, I noticed that the marker doesn't stay pinned in the same location as I zoom in or zoom out the map. https://github.com/ghybs/leaflet-defaulticon-compatibility fixes this issue.
No need for extra libs! Simply create a PNG icon (64x64px in my case), put it in
/public
, and then create an icon instance:import { icon } from "leaflet" const ICON = icon({ iconUrl: "/marker.png", iconSize: [32, 32], })
and use it like this:
<Marker icon={ICON} position={...} />
Yes, there is. Although this seems like a good solution, I noticed that the marker doesn't stay pinned in the same location as I zoom in or zoom out the map. https://github.com/ghybs/leaflet-defaulticon-compatibility fixes this issue.
thanks
Hello gorgeous people of the internet,
I found this issue and was able to fix it by customizing the marker icon to point to the correct URL.
Here is the code I used:
import { MapContainer, TileLayer, Marker, Popup, Circle, ZoomControl } from "react-leaflet";
import "leaflet/dist/leaflet.css";
import L from "leaflet";
import markerIcon from "leaflet/dist/images/marker-icon.png";
import markerIcon2x from "leaflet/dist/images/marker-icon-2x.png";
import markerShadow from "leaflet/dist/images/marker-shadow.png";
const customMarkerIcon = L.icon({
iconUrl: markerIcon,
iconRetinaUrl: markerIcon2x,
shadowUrl: markerShadow,
iconSize: [25, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
tooltipAnchor: [16, -28],
shadowSize: [41, 41],
});
const Map = () => {
return (
<MapContainer
className="mapContainer"
center={[51.505, -0.09]}
zoom={16}
scrollWheelZoom={false}
zoomControl={false}
>
<TileLayer
className="map"
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker position={[51.505, -0.09]} icon={customMarkerIcon}>
</Marker>
<Circle
center={[51.505, -0.09]}
pathOptions={{ color: "#50C878", fillColor: "#72FE9F" }}
radius={200}
/>
</MapContainer>
);
};
export default Map;
I hope this helps!
Hello gorgeous people of the internet,
I found this issue and was able to fix it by customizing the marker icon to point to the correct URL.
Here is the code I used:
import { MapContainer, TileLayer, Marker, Popup, Circle, ZoomControl } from "react-leaflet"; import "leaflet/dist/leaflet.css"; import L from "leaflet"; import markerIcon from "leaflet/dist/images/marker-icon.png"; import markerIcon2x from "leaflet/dist/images/marker-icon-2x.png"; import markerShadow from "leaflet/dist/images/marker-shadow.png"; const customMarkerIcon = L.icon({ iconUrl: markerIcon, iconRetinaUrl: markerIcon2x, shadowUrl: markerShadow, iconSize: [25, 41], iconAnchor: [12, 41], popupAnchor: [1, -34], tooltipAnchor: [16, -28], shadowSize: [41, 41], }); const Map = () => { return ( <MapContainer className="mapContainer" center={[51.505, -0.09]} zoom={16} scrollWheelZoom={false} zoomControl={false} > <TileLayer className="map" attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> <Marker position={[51.505, -0.09]} icon={customMarkerIcon}> </Marker> <Circle center={[51.505, -0.09]} pathOptions={{ color: "#50C878", fillColor: "#72FE9F" }} radius={200} /> </MapContainer> ); }; export default Map;
I hope this helps!
Hello @CodePhilanthropist!
I can set it as you did. But I need to change the marker icon of the react-leaflet-geoman-v2.
No need for extra libs! Simply create a PNG icon (64x64px in my case), put it in
/public
, and then create an icon instance:import { icon } from "leaflet" const ICON = icon({ iconUrl: "/marker.png", iconSize: [32, 32], })
and use it like this:
<Marker icon={ICON} position={...} />
Yes, there is. Although this seems like a good solution, I noticed that the marker doesn't stay pinned in the same location as I zoom in or zoom out the map. https://github.com/ghybs/leaflet-defaulticon-compatibility fixes this issue.
I'm using this lib https://github.com/holytrips/react-leaflet-marker to use react component as marker. I got the same problem, when zoomed marker just move around. The repo doesn't fix my problem. I wonder if I'm doing something wrong. Does react-leaflet-marker work on yours?
In nextJs 14.1.0 I have managed to add a custom marker image by doing the follwoing:
import MapMarkerIcon from "./_assets/some_icon.png";
const customIcon = new L.Icon({
iconUrl: MapMarkerIcon.src,
iconSize: [15, 15],
});
.
..
...
<Marker
key={id}
icon={customIcon}
/>
This worked for me. I'm using creact react app and typescript
import markerIcon from "leaflet/dist/images/marker-icon.png";
import markerShadow from "leaflet/dist/images/marker-shadow.png";
(delete (L.Icon.Default.prototype as any)._getIconUrl);
(L.Icon.Default.prototype as any)._getIconUrl = function (name: string): string {
return require('leaflet/dist/images/' + (name === 'icon' ? 'marker-icon' : 'marker-shadow') + '.png');
};
let DefaultIcon = L.icon({
iconUrl: icon,
shadowUrl: iconShadow,
});
const sizeMarkerIcon = 50
const IconMarker = icon({
iconUrl: `data:image/svg+xml;utf8,${encodeURIComponent(`<?xml version="1.0" encoding="iso-8859-1"?>
<svg xmlns="http://www.w3.org/2000/svg" width="0.67em" height="1em" viewBox="0 0 1024 1536">
<path fill="${theme.palette.primary.main}" d="M768 512q0-106-75-181t-181-75t-181 75t-75 181t75 181t181 75t181-75t75-181m256 0q0 109-33 179l-364 774q-16 33-47.5 52t-67.5 19t-67.5-19t-46.5-52L33 691Q0 621 0 512q0-212 150-362T512 0t362 150t150 362" />
</svg>
`)}`,
iconSize: [sizeMarkerIcon, sizeMarkerIcon],
iconAnchor: [sizeMarkerIcon / 2, sizeMarkerIcon],
popupAnchor: [0, -sizeMarkerIcon]
})
<Marker icon={IconMarker} position={position} draggable={false}>
<Popup>{descriptionCurrentPosition}</Popup>
</Marker>
Expected behavior
When I import my leaflet map in react with dynamic import (required with Next.js), I want the marker images to be display.
Actual behavior
Instead of expected behavior, the marker icon doesn't appear. When I inspect the images with devtools here is the src I get for the image :
http://localhost:3000/_next/static/media/marker-icon.2b3e1faf89f94a4835397e7a43b4f77d.png")marker-icon.png
Here is my actuel dependencies:
I've tried this fix found in another old github issue :
But unfortunately, it result to a compile error :
Steps to reproduce
You can clone this repository to reproduce the issue easily : https://github.com/MathisBarre/leaflet-icon-issue Otherwise you just need to dynamically import a leaflet map in nextjs