leaflet-extra-markers
v2.0.1
Published
Custom map markers for Leaflet JS
Downloads
21,187
Maintainers
Readme
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
Table of contents
Getting started
Install
- 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>
Leaflet V2 usage
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>Leaflet V1 usage
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>API
class Icon
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;
}interface ExtraOptions
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.
svg: SvgNode | undefined
The marker (Marker.icon in leaflet) svg node.
Default: "#000"
accentColor: string | undefined
The accent color is applied to the icon variant and also the dot on the empty state.
Default: "#fff"
color: string | undefined
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".
content: Content | ((opts: ExtraOptions) => Content) | undefined
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%",
},
}]);contentHtml: string | undefined
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" />
contentColor: string | undefined
The content (wrapper) color. Will be set on the `contentWrapper.style.color property.
Note: This setting could be overwritten by contentWrapperStyle.color.
Default: "#fff"
origin: "bottom" | "center" | undefined
Sets the icon anchor.
bottomx center, y bottomcenterx center, y center
scale: number | undefined
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
shadow: "cast" | "drop" | "ellipse" | "none" | undefined
The shadow variant.
Default: "cast"
svgFillImageSrc: string | undefined
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.
contentWrapperClass: string | undefined
The CSS class names added to the contentWrapper element.
contentWrapperStyle: Partial<CSSStyleDeclaration> | undefined
The styles to set on contentWrapper element.
Default: {}
rootClass: string | undefined
The CSS class names added to the root element.
rootStyle: Partial<CSSStyleDeclaration> | undefined
The styles to set on root element.
Default: {}
shadowClass: string | undefined
The CSS class names added to the shadow element.
shadowStyle: Partial<CSSStyleDeclaration> | undefined
The styles to set on shadow element.
Default: {}
svgClass: string | undefined
The CSS class names added to the svg element.
svgStyle: Partial<CSSStyleDeclaration> | undefined
The styles to set on svg element.
Default: {}
function createElement(params: ElementParams): HTMLElement
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.
]
])function createSvgElement(params: ElementParams): SVGElement
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" }],
])Design
Original marker design file (Figma) is located at ./assets/markers.fig.
SVG
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.
Shadows
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.svgHTML
Below 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>Migration guide
v1 to v2
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", };
