# MarkersPlugin Styles

NPM version NPM Downloads jsDelivr Hits
API Documentation

Displays various shapes, images and texts on the viewer.

This plugin is available in the @photo-sphere-viewer/markers-plugin (opens new window) package.

# Usage

The plugin provides a powerful markers system allowing to define points of interest on the panorama with optional tooltip and description. Markers can be dynamically added/removed and you can react to user click/tap.

There are four types of markers :

  • HTML defined with the html/element attribute
  • Images defined with the image/imageLayer attribute
  • Videos defined with the videoLayer attribute
  • SVGs defined with the square/rect/circle/ellipse/path attribute
  • Dynamic polygons & polylines defined with the polygon/polygonPixels/polyline/polylinePixels attribute

Markers can be added at startup with the markers option or after load with the various methods.

const viewer = new PhotoSphereViewer.Viewer({
    plugins: [
        [PhotoSphereViewer.MarkersPlugin, {
            markers: [
                {
                    id: 'new-marker',
                    position: { yaw: '45deg', pitch: '0deg' },
                    image: 'assets/pin-red.png',
                    size: { width: 32, height: 32 },
                },
            ],
        }],
    ],
});

const markersPlugin = viewer.getPlugin(PhotoSphereViewer.MarkersPlugin);

markersPlugin.addEventListener('select-marker', ({ marker }) => {
    markersPlugin.updateMarker({
        id: marker.id,
        image: 'assets/pin-blue.png',
    });
});

# Example

The following example contains all types of markers. Click anywhere on the panorama to add a red marker, right-click to change it's color and double-click to remove it.

TIP

You can try markers live in the playground.

# Markers

# Definition

One, and only one, of these options is required for each marker.

Name Type Description
image string Path to an image file. Requires width and height to be defined.
imageLayer string Path to an image file.
videoLayer string Path to a video file.
html string HTML content of the marker. It is recommended to define width and height.
element HTMLElement Existing DOM element.
square integer Size of the square.
rect integer[2]
{width:int,height:int}
Size of the rectangle.
circle integer Radius of the circle.
ellipse integer[2]
{rx:int,ry:int}
Radiuses of the ellipse.
path string Definition of the path (0,0 will be placed at the defined position).
polygon double[2][]
string[2][]
Array of points defining the polygon in spherical coordinates.
polygonPixels integer[2][] Same as polygon but in pixel coordinates on the panorama image.
polyline double[2][]
string[2][]
Same as polygon but generates a polyline.
polylinePixels integer[2][] Same as polygonPixels but generates a polyline.

Examples :

{
  image: 'pin-red.png',
  imageLayer: 'pin-blue.png',
  videoLayer: 'intro.mp4',
  html: 'Click here',
  element: document.querySelector('#my-marker'),
  square: 10,
  rect: [10, 5],
  rect: {width: 10, height: 5},
  circle: 10,
  ellipse: [10, 5],
  ellipse: {rx: 10, ry: 5},
  path: 'M 0 0 L 60 60 L 60 0 L 0 60 L 0 0',
  polygon: [[0.2, 0.4], [0.9, 1.1], [1.5, 0.7]],
  polygonPixels: [[100, 200], [150, 300], [300, 200]],
  polyline: [[0.2, 0.4], [0.9, 1.1]],
  polylinePixels: [[100, 200], [150, 300]],
}

What is the difference between "image" and "imageLayer" ?

Both allows to display an image but the difference is in the rendering technique. And image marker is rendered flat above the viewer but and imageLayer is rendered inside the panorama itself, this allows for more natural movements and scaling.

Custom element markers

The element marker accepts Web Components (opens new window). If your component has an updateMarker() method it will be called by the plugin on each render with a bunch of properties:

  • marker: reference to the marker object itself
  • position: computed 2D position in the viewport
  • viewerPosition: current camera orientation in yaw+pitch
  • zoomLevel: current zoom level
  • viewerSize: size of the viewport

Check the demo

"Layers" positionning

There is two ways to position imageLayer and videoLayer markers:

  • position (one value) + size + anchor (optional) + orientation (optional)
  • position with four values defining the corners of the image/video

Check the demo

# Options

# id (required)

  • type: string

Unique identifier of the marker.

# position (required for all but polygons/polylines)

  • type: { yaw, pitch } | { textureX, textureY } | array

Position of the marker in spherical coordinates (radians/degrees) or texture coordinates (pixels).

For imageLayer and videoLayer it can be defined as an array of four positions (clockwise from top-left) to precisely place the four corners of the element.

(This option is ignored for polygons and polylines).

  • type: { width, height }

Size of the marker in pixels.

(This option is ignored for polygons and polylines).

# rotation

  • type: string | number

Rotation applied to the marker, in degrees or radians.

(This option is ignored for polygons and polylines).

# orientation (only for imageLayer, videoLayer)

  • type: 'front' | 'horizontal' | 'vertical-left' | 'vertical-right'
  • default: 'front'

Applies a perspective on the image to make it look like placed on the floor or on a wall.

(Ignored if position is an array).

# scale

  • type: double[] | { zoom: double[], yaw: [] }
  • default: no scaling

Configures the scale of the marker depending on the zoom level and/or the horizontal angle offset. This aims to give a natural feeling to the size of the marker as the users zooms and moves.

(This option is ignored for polygons, polylines, imageLayer and videoLayer markers).

# hoverScale

  • type: boolean | number | { amount?: number, duration?: number, easing?: string }
  • default: null

Overrides the global defaultHoverScale. The configuration is merged with the default configuration of x2 scaling in 100ms with a linear easing. Defining hoverScale: false allows to disable the scaling for this marker. See demo.

(This option is ignored for polygons, polylines and imageLayer markers).

{
    defaultHoverScale: { amount: 1.5, duration: 150 },
    markers: [
        {
            ...,
            hoverScale: { amount: 3 },
            hoverScale: 3,
            hoverScale: false,
        },
    ],
}

# opacity

  • type: number
  • default: 1

Opacity of the marker.

# zIndex

  • type: number
  • default: 1

Ordering of the marker.

(This option is ignored for polygons and polylines markers).

WARNING

imageLayer and videoLayer are always renderer first, then polygon and polyline, then standard markers.

# className

  • type: string

CSS class(es) added to the marker element.

(This option is ignored for imageLayer and videoLayer markers).

# style

  • type: object

CSS properties to set on the marker (background, border, etc.).

(For imageLayer and videoLayer markers only cursor can be configured).

style: {
  backgroundColor: 'rgba(0, 0, 0, 0.5)',
  cursor         : 'help'
}

# svgStyle

  • type: object

SVG properties to set on the marker (fill, stroke, etc.). (Only for polygons, polylines and svg markers).

svgStyle: {
  fill       : 'rgba(0, 0, 0, 0.5)',
  stroke     : '#ff0000',
  strokeWidth: '2px'
}

Image and pattern background

You can define complex SVG backgrounds such as images by using a pattern definition. See demo.

# chromaKey

  • type: object
  • default: { enabled: false }

Will make a color of the image/video transparent. See demo.

(This option is only applicable to imagerLayer and videoLayer).

# anchor

  • type: string
  • default: 'center center'

Defines where the marker is placed toward its defined position. Any CSS position is valid like bottom center or 20% 80%.

(This option is ignored for polygons and polylines).

# zoomLvl

  • type: number
  • default: undefined

The zoom level which will be applied when calling gotoMarker() method or when clicking on the marker in the list. If not provided, the current zoom level is kept.

# visible

  • type: boolean
  • default: true

Initial visibility of the marker.

# tooltip

  • type: string | {content: string, position: string, className: string, trigger: string}
  • default: {content: null, position: 'top center', className: null, trigger: 'hover'}

Accepted positions are combinations of top, center, bottom and left, center, right.

Possible triggers are hover and click.

tooltip: 'This is a marker' // tooltip with default position and style

tooltip: { // tooltip with custom position
  content: 'This is marker',
  position: 'bottom left',
}

tooltip: { // tooltip with a custom class shown on click
  content: 'This is marker',
  className: 'custom-tooltip',
  trigger: 'click',
}

# content

  • type: string

HTML content that will be displayed on the side panel when the marker is clicked.

# listContent

  • type: string

The name that appears in the list of markers. If not provided, the tooltip content will be used.

# hideList

  • type: boolean
  • default: false

Hide the marker in the markers list.

# autoplay

  • type: boolean
  • default: true

Autoplay of videoLayer markers

# data

  • type: any

Any custom data you want to attach to the marker. You may access this data in the various events.

# Configuration

# markers

  • type: MarkerConfig[]
  • updatable: no, use setMarkers() method

Initial list of markers.

# defaultHoverScale

  • type: boolean | number | { amount?: number, duration?: number, easing?: string }
  • default: null

Default mouse hover scaling applied to all markers, can be overriden with each marker hoverScale parameter. Defining defaultHoverScale: true will use the default configuration of x2 scaling in 100ms with a linear easing.

# gotoMarkerSpeed

  • type: string|number
  • default: '8rpm'
  • updatable: yes

Default animation speed for gotoMarker method.

# clickEventOnMarker

  • type: boolean
  • default: false
  • updatable: yes

If a click event is triggered on the viewer additionally to the select-marker event.

# lang

  • type: object
  • default:
lang: {
  markers: 'Markers',
  markersList: 'Markers list',
}

Note: this option is not part of the plugin but is merged with the main lang object.

# Methods

# addMarker(properties)

Adds a new marker to the viewer.

markersPlugin.addMarker({
    id: 'new-marker',
    position: { yaw: '45deg', pitch: '0deg' },
    image: 'assets/pin-red.png',
});

# clearMarkers()

Removes all markers.

# getCurrentMarker(): Marker

Returns the last marker clicked by the user.

# gotoMarker(id[, speed]): Animation

Moves the view to face a specific marker.

markersPlugin.gotoMarker('marker-1', '4rpm')
  .then(() => /* animation complete */);

# hideMarker(id) | showMarker(id) | toggleMarker(id)

Changes the visiblity of a marker.

# removeMarker(id) | removeMarkers(ids)

Removes a marker.

# setMarkers(properties[])

Replaces all markers by new ones.

# updateMarker(properties)

Updates a marker with new properties. The type of the marker cannot be changed.

markersPlugin.updateMarker({
    id: 'existing-marker',
    image: 'assets/pin-blue.png',
});

# showMarkerTooltip(id) | hideMarkerTooltip(id)

Allows to always display a tooltip.

# showAllTooltips() | hideAllTooltips() | toggleAllTooltips()

Allows to always display all tooltips.

# Events

# select-marker(marker, doubleClick, rightClick)

Triggered when the user clicks on a marker.

markersPlugin.addEventListener('select-marker', ({ marker }) => {
    console.log(`Clicked on marker ${marker.id}`);
});

# unselect-marker(marker)

Triggered when a marker was selected and the user clicks elsewhere.

# marker-visibility(marker, visible)

Triggered when the visibility of a marker changes.

markersPlugin.addEventListener('marker-visibility', ({ marker, visible }) => {
    console.log(`Marker ${marker.id} is ${visible ? 'visible' : 'not visible'}`);
});

# enter-marker(marker) | leave-marker(marker)

Triggered when the user puts the cursor hover or away a marker.

# Buttons

This plugin adds buttons to the default navbar:

  • markers allows to hide/show all markers
  • markersList allows to open a list of all markers on the left panel

If you use a custom navbar you will need to manually add the buttons to the list.