A collection of fine SVG map markers that can easily be colored, resized, or overlayed with any DOM node including icon libraries, like Lucide, FontAwesome, Bootstrap, or Material.
✨ DEMO
Check out the demo
- NodeJS
npm i leaflet-extra-markers
- Browser
<script type="importmap"> { "imports": { "leaflet": "https://unpkg.com/[email protected]/dist/leaflet.js", "leaflet-extra-marker": "https://unpkg.com/leaflet-extra-markers@latest/index.js" } } </script>
For more examples view the Demo.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<link
rel="stylesheet"
href="https://unpkg.com/[email protected]/dist/leaflet.css"
/>
</head>
<body>
<div id="map" style="width:100%;height:400px;">
<script type="importmap">
{
"imports": {
"leaflet": "https://unpkg.com/[email protected]/dist/leaflet.js",
"leaflet-extra-marker": "https://unpkg.com/leaflet-extra-markers@latest/index.js"
}
}
</script>
<script type="module">
import { Map, Marker } from "leaflet";
import { Icon, PinCirclePanel } from "leaflet-extra-markers";
const map = new Map("map").setView([0, 0], 3);
const marker = new Marker(map.getCenter(), {
icon: new Icon({
accentColor: "firebrick",
color: "indianred",
content: "42",
contentColor: "white",
scale: 1,
svg: PinCirclePanel,
}),
}).addTo(map);
</script>
</body>
</html>For more examples view the Demo.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<link
rel="stylesheet"
href="https://unpkg.com/[email protected]/dist/leaflet.css"
/>
</head>
<body>
<div id="map" style="width:100%;height:400px;">
<script type="importmap">
{
"imports": {
"leaflet": "https://unpkg.com/[email protected]/dist/leaflet-src.esm.js",
"leaflet-extra-markers": "https://unpkg.com/leaflet-extra-markers@latest/index.js"
}
}
</script>
<script type="module">
import * as L from "leaflet";
window.L = {...L};
import { Icon as ExtraIcon, PinCirclePanel } from "leaflet-extra-markers";
const map = new L.Map("map").setView([0, 0], 3);
const marker = new L.Marker(map.getCenter(), {
icon: new Icon({
accentColor: "firebrick",
color: "indianred",
content: "42",
contentColor: "white",
scale: 1,
svg: PinCirclePanel,
}),
}).addTo(map);
</script>
</body>
</html>The Icon class extends Leaflet's Icon class.
import { Marker } from "leaflet";
import { Icon, PinCirclePanel } from "leaflet-extra-markers";
const marker = new Marker([32.82,-117.43], {
icon: new Icon({
accentColor: "firebrick",
color: "indianred",
content: "42",
contentColor: "white",
size: 25,
svg: PinCirclePanel,
}),
});class Icon extends IconBase<ExtraOptions> {
constructor(options?: ExtraOptions);
createIcon(): HTMLElement;
createShadow(): HTMLElement;
}These are the options you can pass into the new Icon() contructor. Note that this interface extends Leaflet's IconOption, while these base options are supported as escape hatches, they should not be used in most circumstances.
The marker (Marker.icon in leaflet) svg node.
Default: "#000"
The accent color is applied to the icon variant and also the dot on the empty state.
Default: "#fff"
The marker color. Will be set on the root.style.color property. The SVG path for the base marker shape has a fillset tocurrentColor` to inherit this color.
Note: This setting could be overwritten by rootStyle.color.
Note: If svgFillImageSrc is defined, this setting will still be set but effectively ignored.
Default: "#000".
The content node to append to the contentWrapper.
This will be ignored if `contentHtml is set.
Default:
createElement(["div", {
style: {
display: "block",
height: "0.8em",
width: "0.8em",
backgroundColor: accentColor,
borderRadius: "100%",
},
}]);Dangerously sets innerHTML of the contentWrapper.
If set this will override the content property.
WARNING: Possible XSS vector; sanitize user inputs if using this.
Example: <i class="fa fa-coffee" />
The content (wrapper) color. Will be set on the `contentWrapper.style.color property.
Note: This setting could be overwritten by contentWrapperStyle.color.
Default: "#fff"
Sets the icon anchor.
bottomx center, y bottomcenterx center, y center
The scale of the SVG marker; height will be scaled proportionately. The markers are designed on a base 30px wide grid. Min: 0.1
Default: 1
The shadow variant.
Default: "cast"
The url of an image to use as a fill for the marker. Image will be clipped by marker base shape. Consider retina devices when sizing images.
The CSS class names added to the contentWrapper element.
The styles to set on contentWrapper element.
Default: {}
The CSS class names added to the root element.
The styles to set on root element.
Default: {}
The CSS class names added to the shadow element.
The styles to set on shadow element.
Default: {}
The CSS class names added to the svg element.
The styles to set on svg element.
Default: {}
Creates HTML element recursively from a data structure. Efficently uses document fragements and support style objects and class arrays -- skipping falsy values.
const svg = createElement([
"i",
{
"data-foo": "bar"
style: {
filter: "drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.32))",
},
class: [
"fa",
isCafe && "fa-coffee",
],
},
[
// Optionally pass in children with same structure.
]
])Creates SVG element recursively from a data structure. Efficently uses document fragements and support style objects and class arrays -- skipping falsy values.
const svg = createSvgElement([
"svg",
{
width: "30px",
height: "30px",
style: {
filter: "drop-shadow(2px 2px 2px rgba(0, 0, 0, 0.32))",
},
class: [
"extra-marker-icon",
],
},
["circle", { cx: "10", cy: "10", r: "5", fill: "currentColor" }],
])Original marker design file (Figma) is located at ./assets/markers.fig.
The markers are divided into 4 families:
pin- taller map markers; like a pushpin; origin at bottom centertack- short map markers; like a thumbtack; origin at bottom centerchip- shorter map markers; like a poker chip; origin at bottom centerpoint- simple point markers; origin at center center
Each icon family has many shapes:
circlediamondpentagonsquarestarteardrop(only forpinfamily)triangle
Each shape has many optional variants:
border-1is a relative 1px borderborder-2is a relative 2px borderpanelis a relative 2px border th a solid fill on the marker tail/pointer.
The variants are designed to completely cover the base shape so you can have fun with opacity, filter, or mix-blend-mode.
The SVG Icons are designed on a base 30px wide grid. The height varies per icon family.
The SVG shadows are inlined as data URIs to increase performance. It is possible to a custom shadow by passing in a shadowUrl options.
The following script was used to efficently encode the shadow SVGs into data URIs.
npx mini-svg-data-uri ./assets/shadow-ellipse.svgBelow is the HTML structure of the Marker Icon.
<div> <!-- leaflet-marker-plane -->
<div> <!-- `root` -->
<!-- `svg` -->
<div> <!-- `contentWrapper` -->
<!-- `content` or `contentHtml` -->
</div>
</div>
</div>
<div> <!-- leaflet-marker-plane -->
<img /> <!-- `shadow` -->
</div>Version 2 is a complete rewrite to support svg only icons with no image or css file dependencies.
- Upgrade to Leaflet v2.
- Remove referenced Image and CSS files as v2 only has JS dependencies.
- Update
Iconoptions/properties per the mapping below:
extraClasses-->rootClass.icon-->contentorcontentHtml.- Consider using the
createElementutil here.
- Consider using the
iconColor-->contentColor.iconRotate- removed; instead add the appropriate class or style to the element passed intocontent.innerHtml- removed.number-->content.prefix- removed. Instead add it to your HTML string forcontentHtmlor on the element if usingcontentshape- removed; instead import the desired marker.import { PinCircleBorder } from "leaflet-extra-markers";svg--> not supported as boolean; now this takes an SvgNode type (import desired marker and pass by reference)svgBorderColor- removed; this never worked but its intended effect can now be accomplished by settingaccentColor.svgOpacity- removed; this never worked but its intended effect can now be accomplished by settingsvgStyle.opacity.markerColor-->color; note that named colors have been removed. The legacy color mapping is below;const colors: { "red": "#a23337", "orange": "#ef9227", "orange-dark": "#d73e29", "yellow": "#f5bb39", "cyan": "#32a9dd", "blue": "#1b75bb", "blue-dark": "#276273", "purple": "#440444", "violet": "#90278d", "pink": "#c057a0", "green-light": "#70b044", "green": "#009549", "green-dark": "#006838", "white": "#ffffff", "black": "#231f20", };