diff --git a/build/docs-index.leafdoc b/build/docs-index.leafdoc
index a2daea29..67e75a4a 100644
--- a/build/docs-index.leafdoc
+++ b/build/docs-index.leafdoc
@@ -12,6 +12,7 @@ This file just defines the order of the classes in the docs.
@class TileLayer
@class TileLayer.WMS
@class ImageOverlay
+@class VideoOverlay
@class Path
@class Polyline
diff --git a/build/leafdoc-templates/html.hbs b/build/leafdoc-templates/html.hbs
index 8c3d765d..f220b10a 100644
--- a/build/leafdoc-templates/html.hbs
+++ b/build/leafdoc-templates/html.hbs
@@ -50,6 +50,7 @@
TileLayer
TileLayer.WMS
ImageOverlay
+ VideoOverlay
Vector Layers
diff --git a/debug/map/videooverlay.html b/debug/map/videooverlay.html
new file mode 100644
index 00000000..5f2726d7
--- /dev/null
+++ b/debug/map/videooverlay.html
@@ -0,0 +1,79 @@
+
+
+
+ Leaflet debug page
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Populate with 10 markers
+
+
+
+
diff --git a/docs/examples.md b/docs/examples.md
index 96789c45..dcf36486 100644
--- a/docs/examples.md
+++ b/docs/examples.md
@@ -88,8 +88,14 @@ description="How the default map panes work to display overlays on top of tiles,
%}
-=======
+{% include tutorial_link.html
+page="video-overlay/"
+thumbnail="video-overlay/thumbnail.gif"
+title="Showing video files"
+description="Leaflet can help you display videos somewhere on the map."
+%}
+***
The following tutorials cover how to create plugins for Leaflet, and are intended only for developers experienced in Javascript:
diff --git a/docs/examples/video-overlay/example-bounds.md b/docs/examples/video-overlay/example-bounds.md
new file mode 100644
index 00000000..c9daeee5
--- /dev/null
+++ b/docs/examples/video-overlay/example-bounds.md
@@ -0,0 +1,23 @@
+---
+layout: tutorial_frame
+title: Video Overlay Tutorial
+---
+
+
diff --git a/docs/examples/video-overlay/example-nocontrols.md b/docs/examples/video-overlay/example-nocontrols.md
new file mode 100644
index 00000000..69dbc0c2
--- /dev/null
+++ b/docs/examples/video-overlay/example-nocontrols.md
@@ -0,0 +1,31 @@
+---
+layout: tutorial_frame
+title: Video Overlay Tutorial
+---
+
+
diff --git a/docs/examples/video-overlay/example.md b/docs/examples/video-overlay/example.md
new file mode 100644
index 00000000..03d2aa64
--- /dev/null
+++ b/docs/examples/video-overlay/example.md
@@ -0,0 +1,58 @@
+---
+layout: tutorial_frame
+title: Video Overlay Tutorial
+---
+
+
diff --git a/docs/examples/video-overlay/index.md b/docs/examples/video-overlay/index.md
new file mode 100644
index 00000000..1cc22baa
--- /dev/null
+++ b/docs/examples/video-overlay/index.md
@@ -0,0 +1,122 @@
+---
+layout: tutorial_v2
+title: Leaflet on Mobile
+---
+
+## Video on webpages
+
+Video used to be a hard task when building a webpage, until the [`` HTML element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video) was made available.
+
+Nowadays, we can use the following HTML code:
+
+
+
+
+
+
+To display this video:
+
+
+
+
+
+
+If a video can be shown in a webpage in this way, then Leaflet can display it inside a map. It is important that the videos are prepared in such a way that they will fit the map: The video should have a "north-up" orientation, and its proportions should fit the map. If not, it will look out of place.
+
+### Bounds of an image overlay
+
+First of all, create a Leaflet map and add a background `L.TileLayer` in the usual way:
+
+ var map = L.map('map').setView([37.8, -96], 4);
+
+ L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=' + mapboxAccessToken, {
+ id: 'mapbox.satellite',
+ attribution: ...
+ }).addTo(map);
+
+Then, we'll define the geographical bounds that the video will cover. This is an instance of [`L.LatLngBounds`](../../reference.html#latlngbounds), which is a rectangular shape:
+
+ var bounds = L.latLngBounds([[ 32, -130], [ 13, -100]]);
+
+If you want to see the area covered by a `LatLngBounds`, use a [`L.Rectangle`]((../../reference.html#latlngbounds)):
+
+ L.rectangle(bounds).addTo(map);
+
+ map.fitBounds(bounds);
+
+{% include frame.html url="example-bounds.html" %}
+
+
+### Adding the video overlay
+
+Adding a video overlay works very similar to adding a image overlay. For just one image, [`L.ImageOverlay`s](../../reference.html#imageoverlay) is used like this:
+
+ var overlay = L.imageOverlay( imageUrl, bounds, options );
+
+For a video overlay, just:
+
+* Use `L.videoOverlay` instead of `L.imageOverlay`
+* Instead of the image URL, specify one video URL *or* an array of video URLs
+
+```
+ var videoUrls = [
+ 'https://www.mapbox.com/bites/00188/patricia_nasa.webm',
+ 'https://www.mapbox.com/bites/00188/patricia_nasa.mp4'
+ ];
+
+ var bounds = L.latLngBounds([[ 32, -130], [ 13, -100]]);
+
+ var videoOverlay = L.videoOverlay( videoUrls, bounds, {
+ opacity: 0.8
+ }).addTo(map);
+```
+
+And just like that, you'll get the video on your map:
+
+{% include frame.html url="example-nocontrols.html" %}
+
+
+Video overlays behave like any other Leaflet layer - you can add and remove them, let the user select from several videos using a [layers control](../layers-control/), etc.
+
+
+### A bit of control over the video
+
+If you read the API documentation, you'll notice that the `L.VideoOverlay` class does not have a `play()` or `pause()` method.
+
+For this, the `getElement()` method of the video overlay is useful. It returns the [`HTMLVideoElement`](https://developer.mozilla.org/docs/Web/API/HTMLImageElement) (which inherits from [`HTMLMediaElement`](https://developer.mozilla.org/docs/Web/API/HTMLMediaElement)) for the overlay - and that has methods like `play()` and `pause()`, e.g.
+
+```
+ videoOverlay.getElement().pause();
+```
+
+This allows us to build custom interfaces. For example, we can build a small subclass of `L.Control` to play/pause this video overlay once it's loaded:
+
+```
+ videoOverlay.on('load', function () {
+ var MyPauseControl = L.Control.extend({
+ onAdd: function() {
+ var button = L.DomUtil.create('button');
+ button.innerHTML = '⏸';
+ L.DomEvent.on(button, 'click', function () {
+ videoOverlay.getElement().pause();
+ });
+ return button;
+ }
+ });
+ var MyPlayControl = L.Control.extend({
+ onAdd: function() {
+ var button = L.DomUtil.create('button');
+ button.innerHTML = '⏵';
+ L.DomEvent.on(button, 'click', function () {
+ videoOverlay.getElement().play();
+ });
+ return button;
+ }
+ });
+
+ var pauseControl = (new MyPauseControl()).addTo(map);
+ var playControl = (new MyPlayControl()).addTo(map);
+ });
+```
+
+{% include frame.html url="example.html" %}
diff --git a/docs/examples/video-overlay/thumbnail.gif b/docs/examples/video-overlay/thumbnail.gif
new file mode 100644
index 00000000..f2fcc29d
Binary files /dev/null and b/docs/examples/video-overlay/thumbnail.gif differ
diff --git a/src/layer/ImageOverlay.js b/src/layer/ImageOverlay.js
index a6a86657..2d901578 100644
--- a/src/layer/ImageOverlay.js
+++ b/src/layer/ImageOverlay.js
@@ -168,7 +168,8 @@ export var ImageOverlay = Layer.extend({
},
// @method getElement(): HTMLElement
- // Get the img element that represents the ImageOverlay on the map
+ // Returns the instance of [`HTMLImageElement`](https://developer.mozilla.org/docs/Web/API/HTMLImageElement)
+ // used by this overlay.
getElement: function () {
return this._image;
},
diff --git a/src/layer/VideoOverlay.js b/src/layer/VideoOverlay.js
new file mode 100644
index 00000000..811729ab
--- /dev/null
+++ b/src/layer/VideoOverlay.js
@@ -0,0 +1,69 @@
+import {ImageOverlay} from './ImageOverlay';
+
+/*
+ * @class VideoOverlay
+ * @aka L.VideoOverlay
+ * @inherits ImageOverlay
+ *
+ * Used to load and display a video player over specific bounds of the map. Extends `ImageOverlay`.
+ *
+ * A video overlay uses the [``](https://developer.mozilla.org/docs/Web/HTML/Element/video)
+ * HTML5 element.
+ *
+ * @example
+ *
+ * ```js
+ * var videoUrl = 'https://www.mapbox.com/bites/00188/patricia_nasa.webm',
+ * imageBounds = [[ 32, -130], [ 13, -100]];
+ * L.imageOverlay(imageUrl, imageBounds).addTo(map);
+ * ```
+ */
+
+export var VideoOverlay = ImageOverlay.extend({
+
+ // @section
+ // @aka VideoOverlay options
+ options: {
+ // @option autoplay: Boolean = true
+ // Whether the video starts playing automatically when loaded.
+ autoplay: true,
+
+ // @option loop: Boolean = true
+ // Whether the video will loop back to the beginning when played.
+ loop: true
+ },
+
+ _initImage: function () {
+ var vid = this._image = L.DomUtil.create('video',
+ 'leaflet-image-layer ' + (this._zoomAnimated ? 'leaflet-zoom-animated' : ''));
+
+ vid.onselectstart = L.Util.falseFn;
+ vid.onmousemove = L.Util.falseFn;
+
+ // @event load: Event
+ // Fired when the video has finished loading the first frame
+ vid.onloadeddata = L.bind(this.fire, this, 'load');
+
+ if (!L.Util.isArray(this._url)) { this._url = [this._url]; }
+
+ vid.autoplay = !!this.options.autoplay;
+ vid.loop = !!this.options.loop;
+ for (var i = 0; i < this._url.length; i++) {
+ var source = L.DomUtil.create('source');
+ source.src = this._url[i];
+ vid.appendChild(source);
+ }
+ }
+
+ // @method getElement(): HTMLVideoElement
+ // Returns the instance of [`HTMLVideoElement`](https://developer.mozilla.org/docs/Web/API/HTMLVideoElement)
+ // used by this overlay.
+});
+
+
+// @factory L.videoOverlay(videoUrl: String|Array, bounds: LatLngBounds, options?: VideoOverlay options)
+// Instantiates an image overlay object given the URL of the video (or array of URLs) and the
+// geographical bounds it is tied to.
+export function videoOverlay(url, bounds, options) {
+ return new L.VideoOverlay(url, bounds, options);
+}
diff --git a/src/layer/index.js b/src/layer/index.js
index 417e8737..23793efa 100644
--- a/src/layer/index.js
+++ b/src/layer/index.js
@@ -12,6 +12,7 @@ GeoJSON.asFeature = asFeature;
export {GeoJSON, geoJSON, geoJson};
export {ImageOverlay, imageOverlay} from './ImageOverlay';
+export {VideoOverlay, videoOverlay} from './VideoOverlay';
export {DivOverlay} from './DivOverlay';
export {Popup, popup} from './Popup';