Leaflet plugin for photo geotagging.


Screenshot of camera module

Leaflet.GeotagPhoto is part of The New York Public Library’s NYC Space/Time Directory.

You can also find Leaflet.GeotagPhoto on Leaflet’s plugin page.


Include the following HTML in your page’s <head> tag:

<link rel="stylesheet" href="https://unpkg.com/leaflet-geotag-photo/dist/Leaflet.GeotagPhoto.css" />
<script src="https://unpkg.com/leaflet-geotag-photo/dist/Leaflet.GeotagPhoto.min.js"></script>

The HTML above links to the latest version of Leaflet.GeotagPhoto. In production, you should link to a specific version, to prevent newer versions breaking your application:

<link rel="stylesheet" href="https://unpkg.com/leaflet-geotag-photo@0.5.1/dist/Leaflet.GeotagPhoto.css" />
<script src="https://unpkg.com/leaflet-geotag-photo@0.5.1/dist/Leaflet.GeotagPhoto.min.js"></script>



Crosshair mode


  .on('input', function (event) {
    var point = this.getCrosshairPoint()


L.GeotagPhoto.Crosshair extends L.Evented.

Function Description
L.geotagPhoto.crosshair(options?) Creation
addTo (map) Add L.GeotagPhoto.Crosshair to map
removeFrom (map) Remove L.GeotagPhoto.Crosshair from map
getCrosshairLatLng () Returns crosshair’s LatLng
getCrosshairPoint () Returns crosshair’s GeoJSON Point


Option Type Default Description
crosshairHTML HTML String <img src="<url>" width="100px" /> HTML string of crosshair element
controlCrosshairImg url ../images/crosshair.svg Crosshair image URL used by the default crosshairHTML


Camera mode


var cameraPoint = [6.83442, 52.43369]
var targetPoint = [6.83342, 52.43469]

var points = {
  type: 'Feature',
  properties: {
    angle: 20
  geometry: {
    type: 'GeometryCollection',
    geometries: [
        type: 'Point',
        coordinates: cameraPoint
        type: 'Point',
        coordinates: targetPoint

var options = {
  draggable: true

L.geotagPhoto.camera(points, options).addTo(map)
  .on('change', function (event) {
    // Get camera field of view
    // See:
    //   https://github.com/nypl-spacetime/field-of-view#output
    var fieldOfView = this.getFieldOfView()


L.GeotagPhoto.Camera extends L.FeatureGroup.

Function Description
L.geotagPhoto.camera(feature, options?) Creation, feature is input for field-of-view
getFieldOfView () Returns field of view of camera
getCameraLatLng () Returns camera’s LatLng
getTargetLatLng () Returns target’s LatLng
getCameraPoint () Returns camera’s GeoJSON Point
getTargetPoint () Returns target’s GeoJSON Point
getCenter () Returns LatLng of point halfway camera and target
getBounds () Returns LatLngBounds of field of view triangle
centerBounds (bounds) Moves camera and target so their center lies in the middle of bounds
setAngle (angle) Set angle of view
setCameraLatLng (latLng) Set LatLng of camera
setTargetLatLng (latLng) Set LatLng of target
setCameraAndTargetLatLng (cameraLatLng, targetLatLng) Set LatLng of camera and LatLng of target
setDraggable (boolean) Toggle between static or draggable camera


Option Type Default Description
draggable Boolean true Whether the camera is draggable with mouse/touch or not
angleMarker Boolean true Whether the angle of the field-of-view can be changed with a draggable marker
minAngle Number 5 Minimum angle of field-of-view
maxAngle Number 120 Maximum angle of field-of-view
cameraIcon L.Icon See below Camera icon
targetIcon L.Icon See below Target icon
angleIcon L.Icon See below Angle icon
outlineStyle L.Path options See below Style of field-of-view triangle’s outline
fillStyle L.Path options See below Style of field-of-view triangle’s fill polygon
control Boolean true Whether to show camera control buttons
controlCameraImg String ../images/camera-icon.svg URL to icon displayed in camera control button
controlCrosshairImg String ../images/crosshair-icon.svg URL to icon displayed in crosshair control button
const defaults = {
  cameraIcon: L.icon({
    iconUrl: '../images/camera.svg',
    iconSize: [38, 38],
    iconAnchor: [19, 19]

  targetIcon: L.icon({
    iconUrl: '../images/marker.svg',
    iconSize: [32, 32],
    iconAnchor: [16, 16]

  angleIcon: L.icon({
    iconUrl: '../images/marker.svg',
    iconSize: [32, 32],
    iconAnchor: [16, 16]

  outlineStyle: {
    color: 'black',
    opacity: 0.5,
    weight: 2,
    dashArray: '5, 7',
    lineCap: 'round',
    lineJoin: 'round'

  fillStyle: {
    weight: 0,
    fillOpacity: 0.2,
    fillColor: '#3388ff'

Keyboard navigation

Building & Publishing

To build the plugin, run:

npm run build

The resulting files will be available in the dist directory.

To publish the plugin to npm and unpkg.com, run:

npm publish

See also