13

I 've put together a very simple React / Leaflet demo but the marker icon is not showing at all. Full running code is here.

Here's what I have in my componentDidMount method:

componentDidMount() {
this.map = L.map("map-id", {
  center: [37.98, 23.72],
  zoom: 12,
  zoomControl: true
});

const mapboxAccessToken =
  "pk.eyJ1IjoibXBlcmRpa2VhcyIsImEiOiJjazZpMjZjMW4wOXJzM2ttc2hrcTJrNG9nIn0.naHhlYnc4czWUjX0-icY7Q";
L.tileLayer(
  "https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}",
  {
    attribution:
      'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
    maxZoom: 25,
    id: "mapbox/streets-v11",
    accessToken: mapboxAccessToken
  }
).addTo(this.map);

L.marker([37.98, 23.72])
  .addTo(this.map)
  .bindPopup("a marker")
  .openPopup();
}

Basically, the popup is visible, but not the marker icon itself. I.e., here's what I see:

enter image description here

2
  • On my machine the icon is expressed as base64, but it apparently doesn't show up because it is malformed: <img src='data:image/png;base64, ... GgIwYdwAAAAASUVORK5CYII=")marker-icon.png'. Removing the suffix ")marker-icon.png in the browser debugger makes the icon appear, but I don't know where it's coming from. In addition there is an empty square around the icon, which probably represents the missing drop shadow.
    – Qwertie
    Commented May 21, 2021 at 22:49
  • Related issue: github.com/PaulLeCam/react-leaflet/issues/453
    – Qwertie
    Commented May 27, 2021 at 2:28

7 Answers 7

31

I'm using react-leaflet. Here's how I did it.

import markerIconPng from "leaflet/dist/images/marker-icon.png"
import {Icon} from 'leaflet'

then, later, inside the MapContainer:

<Marker position={[lat, lng]} icon={new Icon({iconUrl: markerIconPng, iconSize: [25, 41], iconAnchor: [12, 41]})} />
3
  • 2
    Nice !!!!!!!!!!!!!!!!!!!!! Commented Oct 11, 2021 at 15:30
  • 4
    I'm using nextjs and this almost worked for me. It wants a specific path instead of an imported image. Say your icon is marker-icon.png. Place it under the static directory e.g. public and use new Icon({ iconUrl : '/marker-icon.png' ... })
    – superk
    Commented Jul 17, 2022 at 6:42
  • The best answer. And you can import any marker icon to use instead of the default one. Commented Aug 24, 2022 at 17:21
7

Try to add an icon:

const myIcon = L.icon({
   iconUrl: 'myIcon.png',
   // ...
});

L.marker([37.98, 23.72], {icon: myIcon})
  .addTo(this.map)

Perhaps you have some problems with the default one: https://leafletjs.com/reference-1.6.0.html#icon-default

1
4

Here's what worked for me in the end (I'm on webpack):

const defaultIcon = new L.icon({
  iconUrl: require('../node_modules/leaflet/dist/images/marker-icon.png'); // your path may vary ...
  iconSize: [8, 8],
  iconAnchor: [2, 2],
  popupAnchor: [0, -2]
});

generateMarkers().forEach( c=> {
   L.marker(c, {icon: defaultIcon}).addTo(this.map).bindPopup('a marker; yeah').openPopup();
}
4

include this before in index.js file before calling render function.

import markerIcon from "../node_modules/leaflet/dist/images/marker-icon.png";
L.Marker.prototype.setIcon(L.icon({
  iconUrl:markerIcon
}))
1
  • This works like a charm in Vue 3, ES6. Commented Oct 27, 2022 at 15:55
2

Just for reference, this is due to webpack trying to include the Marker Icon image file specified in Leaflet CSS as a static asset in different folder and possibly file renaming (e.g. for finger printing); all this interferes with Leaflet algorithm which uses that image only as a pointer to its actual CSS images folder, which therefore can be completely missing after webpack build step.

See details in https://github.com/Leaflet/Leaflet/issues/4968

I specifically made a Leaflet plugin to cover this issue: https://github.com/ghybs/leaflet-defaulticon-compatibility

Retrieve all Leaflet Default Icon options from CSS, in particular all icon images URL's, to improve compatibility with bundlers and frameworks that modify URL's in CSS.

Unfortunately, it would still not work in CodeSandbox (or even in StackBlitz), because the latter does not handle these static assets. It is visible by just trying to use Leaflet Layers Control, which uses a very simple CSS background image, which is also missing in CodeSandbox.

But everything should be fine in your own environment.

demo in CodeSandbox: https://codesandbox.io/s/elegant-swirles-yzsql

and in StackBlitz (same static assets issue): https://stackblitz.com/edit/react-vqgtxd?file=index.js

0
1

I guess one simple way is just changes the image path:

L.Icon.Default.imagePath='images/'

I'm using react so I copied the folder /node_modules/leaflet/dist/images to /public.

0
 L.Icon.Default.imagePath='/path_to_your_images';
    var icon = L.icon({
        iconUrl: 'marker-icon.png',
        shadowUrl: 'marker-shadow.png',

        iconSize:     [25, 41],
        shadowSize:   [30, 65],
        iconAnchor:   [12, 41],
        shadowAnchor: [7, 65]
    });

this solution works for me!

Not the answer you're looking for? Browse other questions tagged or ask your own question.