Skip to main content
The Plan plugin embeds a Leaflet map into the viewer overlay showing the GPS location of the panorama. It uses OpenStreetMap by default but supports any Leaflet-compatible tile layer. Clickable hotspots can also be displayed on the map.
Looking for a custom image map (floor plan, site plan, etc.)? Use the Map plugin instead.

Installation

npm install @photo-sphere-viewer/plan-plugin
The Plan plugin requires Leaflet. Import both the Leaflet JavaScript and CSS files before using this plugin.
This plugin also requires its own stylesheet. Import @photo-sphere-viewer/plan-plugin/index.css or add the CDN link to your <head>.

Usage

The only required option is coordinates — the GPS position of the panorama.
import { Viewer } from '@photo-sphere-viewer/core';
import { PlanPlugin } from '@photo-sphere-viewer/plan-plugin';

const viewer = new Viewer({
    plugins: [
        PlanPlugin.withConfig({
            coordinates: [6.79077, 44.58041], // [longitude, latitude]
        }),
    ],
});

Configuration

coordinates
[number, number]
required
GPS position of the panorama as [longitude, latitude]. Updatable. You can also call setCoordinates().
bearing
number | string
default:"0"
Rotation offset applied to the central pin to align it with the panorama’s orientation. Updatable.
layers
array
default:"OpenStreetMap"
Available base tile layers. When more than one layer is configured, a button lets the user switch between them. Each entry is an object with:
  • name — display name
  • urlTemplate — tile URL template for standard raster tiles (e.g. 'https://tile.openstreetmap.org/{z}/{x}/{y}.png')
  • layer — any custom Leaflet layer instance (alternative to urlTemplate)
  • attribution — attribution text
layers: [
    {
        name: 'OpenStreetMap',
        urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
        attribution: '&copy; OpenStreetMap',
    },
    {
        name: 'OpenTopoMap',
        layer: new L.TileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
            subdomains: ['a', 'b', 'c'],
            maxZoom: 17,
        }),
        attribution: '&copy; OpenTopoMap',
    },
]
Ignored when configureLeaflet is used.
configureLeaflet
function
(map) => void. Callback for full manual Leaflet configuration. When provided, the default tile layer is not applied.
configureLeaflet(map) {
    // use the full Leaflet API: https://leafletjs.com/reference.html
}
size
{ width: string, height: string }
default:"{ width: '300px', height: '200px' }"
Size of the widget. Accepts any CSS length unit. Updatable.
position
string
default:"'bottom left'"
Position of the widget on screen. Accepted values: combinations of top/bottom and left/right. Updatable.
pinImage
string
SVG or image URL for the central position pin. Defaults to a built-in SVG. Updatable.
pinSize
number
default:"35"
Size of the central pin in pixels. Updatable.
hotspots
PlanHotspot[]
default:"null"
Markers visible on the map. Updatable. See Hotspots below. You can also call setHotspots().
Markers from the Markers plugin appear on the plan map by setting their plan data property to a hotspot object. The marker tooltip is reused and clicking a plan hotspot rotates the viewer to face the marker.
spotStyle
object
Default style for hotspots. Updatable. Individual hotspots can override with their own style.
FieldTypeDefaultDescription
sizenumber15Hotspot diameter
imagestringSVG or image URL
colorstring'white'Fill color when no image
borderSizenumber0Border width
borderColorstringnullBorder color
hoverSizenumbernullSize on hover
hoverImagestringnullImage on hover
hoverColorstringnullColor on hover
hoverBorderSizenumber4Border width on hover
hoverBorderColorstring'rgba(255,255,255,0.8)'Border color on hover
defaultZoom
number
default:"15"
Initial Leaflet zoom level.
visibleOnLoad
boolean
default:"true"
Show the map when the first panorama loads.
minimizeOnHotspotClick
boolean
default:"true"
Minimize the map when the user clicks a hotspot or marker. Updatable.
buttons
object
default:"{ maximize: true, close: true, reset: true }"
Control which buttons are visible around the map widget.
lang
object
Localization strings merged with the main viewer lang object.
lang: {
    map: 'Map',
    mapMaximize: 'Maximize',
    mapMinimize: 'Minimize',
    mapReset: 'Reset',
    mapLayers: 'Base layer',
}

Hotspots

id
string
Identifier used to match select-hotspot events. Auto-generated if not set.
coordinates
[number, number]
required
GPS position of the hotspot as [longitude, latitude].
style
object
Overrides the default spotStyle for this hotspot.
tooltip
string | { content: string, className: string }
Tooltip shown when hovering the hotspot.

Methods

setHotspots(hotspots)

Replaces all hotspots.
planPlugin.setHotspots([
    { id: '1', coordinates: [6.79077, 44.58041], tooltip: 'Hotspot one' },
    { id: '2', coordinates: [6.79100, 44.58060] },
]);

clearHotspots()

Removes all hotspots.

setCoordinates(coordinates)

Updates the panorama’s GPS position on the map.
planPlugin.setCoordinates([6.79077, 44.58041]);

close() / open()

Toggles between closed and open states.

maximize() / minimize()

Toggles between maximized and minimized views. Has no effect when the map is closed.

getLeaflet()

Returns the underlying Leaflet map instance for direct access to the Leaflet API.

setZoom(level)

Sets the Leaflet zoom level.

Events

select-hotspot(hotspotId)

Fired when the user clicks a hotspot.
planPlugin.addEventListener('select-hotspot', ({ hotspotId }) => {
    console.log(`Clicked hotspot ${hotspotId}`);
});

view-changed(view)

Fired when the map state changes. view is 'maximized', 'normal', or 'closed'.

SCSS variables

VariableDefaultDescription
$radius8pxCorner radius of the widget
$shadow0 0 5px rgba(0,0,0,.7)Widget shadow
$button-size34pxButton size
$button-backgroundrgba(0,0,0,.5)Button background
$button-colorwhiteButton icon color
$transitionease-in-out .3sAnimation transition

Build docs developers (and LLMs) love