Are your SVGs accessible on the URLs provided? Upon inspecting the leaflet marker typings, I observed that the Icon
also features an imagePath
which could be utilized.
Personally, I have achieved excellent outcomes by utilizing DivIcon
for custom markers. DivIcons support static HTML content, allowing you to incorporate any HTML elements and even ReactElements with appropriate coding.
import { divIcon } from "leaflet";
import { ReactElement } from "react";
import { renderToString } from "react-dom/server";
export const createLeafletIcon = (
icon: ReactElement,
size: number,
className?: string,
width: number = size,
height: number = size,
center: boolean = false
) => {
const widthAnchor = width / 2;
const heightAnchor = center ? height / 2 : height;
return divIcon({
html: renderToString(icon),
iconSize: [width, height],
iconAnchor: [widthAnchor, heightAnchor],
popupAnchor: [0, -heightAnchor],
className: className ? className : "",
});
};
In your specific context, simply prepare the icons as reusable React components across different sections of your application.
Below is a customized marker component for contextual reference:
import { LatLngLiteral } from "leaflet";
import React, { Children, ReactElement, useEffect, useRef } from "react";
import { Marker, Popup, useMap } from "react-leaflet";
import { MapPin } from "tabler-icons-react";
import { createLeafletIcon } from "./utils";
// The component remains unchanged beyond this point</answer1>
<exanswer1><div class="answer accepted" i="75482444" 4.0" c="1676615611" a="RGlzY28=" ai="11196441">
<p>Are your svgs accessible on the urls you provide? When I look into the leaflet marker typings I noticed that <code>Icon
also have a imagePath
that you could try to use instead.
However I have great success with using DivIcon
for custom markers.
DivIcons can handled static html, which means that you can use any html you want and with some code you can use ReactElements.
import { divIcon } from "leaflet";
import { ReactElement } from "react";
import { renderToString } from "react-dom/server";
export const createLeafletIcon = (
icon: ReactElement,
size: number,
className?: string,
width: number = size,
height: number = size,
center: boolean = false
) => {
const widthAnchor = width / 2;
const heightAnchor = center ? height / 2 : height;
return divIcon({
html: renderToString(icon),
iconSize: [width, height],
iconAnchor: [widthAnchor, heightAnchor],
popupAnchor: [0, -heightAnchor],
className: className ? className : "",
});
};
In your case just prepare the icons as react components that you can reuse in other instances in your application as well.
This is my custom marker component for some context
import { LatLngLiteral } from "leaflet";
import React, { Children, ReactElement, useEffect, useRef } from "react";
import { Marker, Popup, useMap } from "react-leaflet";
import { MapPin } from "tabler-icons-react";
import { createLeafletIcon } from "./utils";
export interface LeafletMarkerProps {
position: LatLngLiteral;
flyToPosition?: boolean;
size?: number;
color?: string;
icon?: ReactElement;
defaultOpen?: boolean;
onOpen?: () => void;
children?: React.ReactNode;
markerType?: string;
zIndexOffset?: number;
centerMarker?: boolean;
}
const LeafletMarker: React.FC<LeafletMarkerProps> = ({
position,
flyToPosition = false,
children,
size = 30,
color,
defaultOpen = false,
onOpen,
icon = <MapPin size={size} color={color} />,
markerType,
zIndexOffset,
centerMarker = false,
}) => {
const map = useMap();
const markerRef = useRef(null);
position && flyToPosition && map.flyTo(position);
const markerIcon = createLeafletIcon(
icon,
size,
markerType,
size,
size,
centerMarker
); // Important to not get default styling
useEffect(() => {
if (defaultOpen) {
try {
if (markerRef.current !== null && !markerRef.current.isPopupOpen()) {
markerRef.current.openPopup();
}
} catch (error) {}
}
}, [defaultOpen, position.lat, position.lng]);
return (
<Marker
eventHandlers={{
popupopen: () => onOpen && onOpen(),
}}
ref={markerRef}
icon={markerIcon}
position={position}
zIndexOffset={zIndexOffset}
>
{/* autoPan important to not have jittering */}
{children && <Popup autoPan={false}>{children}</Popup>}
</Marker>
);
};
export default LeafletMarker;