- var enableInlineVideo = require('iphone-inline-video');
- var touchEnabled = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints);
- function createVideoElement(src, className, time, muted) {
- var video = document.createElement('video');
- video.src = src + (time ? '#' + time : '');
- video.controls = false;
- video.muted = muted || false;
- video.preload = 'auto';
- if (className) {
- video.className = className;
- }
- enableInlineVideo(video, !muted);
- return video;
- }
- function warmVideoTubes(video, cb) {
- if (video.paused) {
- var videoMuted = video.muted;
- var videoTime = video.currentTime;
-
- var onLoadededMetadata = function() {
- video.removeEventListener('loadedmetadata', onLoadededMetadata);
- video.currentTime = videoTime;
- if (cb) {
- cb(video);
- }
- };
-
- video.muted = true;
- video.play();
- video.pause();
- video.muted = videoMuted;
- if (video.duration >= 0) {
- onLoadededMetadata();
- } else {
- video.addEventListener('loadedmetadata', onLoadededMetadata);
- }
- }
- }
- function createLivePhotoElements(keyframeUrl, videoUrl, stillImageTime) {
- var container = document.createElement('div');
- container.className = 'live-photo';
- container.setAttribute('data-live-photo', '');
- var img = document.createElement('img');
- img.className = 'live-photo-keyframe';
- img.src = keyframeUrl;
- var postroll = createVideoElement(videoUrl, 'live-photo-postroll', stillImageTime, true);
- var video = createVideoElement(videoUrl, 'live-photo-video');
- var icon = document.createElement('i');
- icon.className = 'live-photo-icon';
- container.appendChild(img);
- container.appendChild(postroll);
- container.appendChild(video);
- container.appendChild(icon);
- return {
- container: container,
- img: img,
- postroll: postroll,
- video: video,
- icon: icon,
- };
- }
- function defaultPlayEvents() {
- var events = ['mousedown'];
- if (touchEnabled) {
- events.push('touchstart');
- }
- return events;
- }
- function defaultStopEvents() {
- var events = ['mouseup', 'mouseout'];
- if (touchEnabled) {
- events.push('touchend');
- }
- return events;
- }
- function LivePhoto(keyframeUrl, videoUrl, stillImageTime, options) {
-
- if (!(this instanceof LivePhoto)) {
- return new LivePhoto(keyframeUrl, videoUrl, stillImageTime, options);
- }
-
- var elements, replaceEl;
- if (keyframeUrl instanceof HTMLElement) {
- options = videoUrl;
- replaceEl = keyframeUrl;
- videoUrl = replaceEl.getAttribute('data-live-photo');
- stillImageTime = parseFloat(replaceEl.getAttribute('data-live-photo-still-image-time'));
- keyframeUrl = replaceEl.src;
- }
-
- options || (options = {});
- this.postrollMs = options.postrollMs || 375;
- this.deactivateMs = options.deactivateMs || 500;
- this.previewMs = options.previewMs || 500;
-
- this.stillImageTime = stillImageTime || NaN;
-
- if (!keyframeUrl && !options.noErrors) {
- throw new Error('LivePhoto Error: Missing keyframeUrl');
- }
- if (!videoUrl && !options.noErrors) {
- throw new Error('LivePhoto Error: Missing videoUrl');
- }
- elements = createLivePhotoElements(keyframeUrl, videoUrl, stillImageTime);
-
- if (replaceEl) {
- replaceEl.parentNode.insertBefore(elements.container, replaceEl);
- replaceEl.parentNode.removeChild(replaceEl);
- }
-
- this.container = elements.container;
- this.img = elements.img;
- this.video = elements.video;
- this.postroll = elements.postroll;
- this.icon = elements.icon;
-
- this.__onVideoCanPlayThrough = this._onVideoCanPlayThrough.bind(this);
- this.__onVideoLoadededMetadata = this._onVideoLoadededMetadata.bind(this);
- this.__onPostrollTimeUpdate = this._onPostrollTimeUpdate.bind(this);
- this.__startVideoPlayback = this._startVideoPlayback.bind(this);
- this.__startPostrollPlayback = this._startPostrollPlayback.bind(this);
- this.__resetPlayback = this._resetPlayback.bind(this);
- this.__resetPreview = this._resetPreview.bind(this);
-
- this.video.addEventListener('canplaythrough', this.__onVideoCanPlayThrough);
- if (this.video.duration) {
- this._setDuration(this.video.duration);
- this._resetPostroll();
- } else {
- this._setDuration(0);
- this.video.addEventListener('loadedmetadata', this.__onVideoLoadededMetadata);
- }
-
- this._playing = false;
- this._canPlayThrough = false;
- this._playWhenReady = false;
-
- if (options.useEventHandlers !== false) {
- this._addEventHandlers(options.playEvents, options.stopEvents);
- }
- }
- LivePhoto.prototype = {
-
- _addEventHandlers: function(playEvents, stopEvents) {
- var container = this.container;
- var bootstrapped = false;
- var playVideo = this.play.bind(this);
- var video = this.video;
- var postroll = this.postroll;
- var play = function(e) {
- e.preventDefault();
- if (bootstrapped) {
- playVideo();
- } else {
- var videoReady = false;
- var postrollReady = false;
- warmVideoTubes(video, function() {
- videoReady = true;
- if (postrollReady) {
- playVideo();
- }
- });
- warmVideoTubes(postroll, function() {
- postrollReady = true;
- if (videoReady) {
- playVideo();
- }
- });
- bootstrapped = true;
- }
- };
- (playEvents && playEvents !== false) || (playEvents = defaultPlayEvents);
- if (typeof playEvents === 'function') {
- playEvents = playEvents(this);
- }
- if (typeof playEvents === 'string') {
- playEvents = playEvents.split(/[,\s]+/);
- }
- playEvents.forEach(function(playEvent) {
- if (playEvent) {
- container.addEventListener(playEvent, play);
- }
- });
- var stopVideo = this.stop.bind(this);
- var stop = function(e) {
- e.preventDefault();
- stopVideo();
- };
- (stopEvents && stopEvents !== false) || (stopEvents = defaultStopEvents);
- if (typeof stopEvents === 'function') {
- stopEvents = stopEvents(this);
- }
- if (typeof stopEvents === 'string') {
- stopEvents = stopEvents.split(/[,\s]+/);
- }
- stopEvents.forEach(function(stopEvent) {
- if (stopEvent) {
- container.addEventListener(stopEvent, stop);
- }
- });
- },
-
- _onVideoCanPlayThrough: function() {
- this._canPlayThrough = true;
- if (this._playWhenReady) {
- this._playWhenReady = false;
- this.play();
- }
- this.container.classList.remove('loading');
- this.video.removeEventListener('canplaythrough', this.__onVideoCanPlayThrough);
- },
-
- _onVideoLoadededMetadata: function() {
- this._setDuration(this.video.duration || 0);
- this._resetPostroll();
- this.video.removeEventListener('loadedmetadata', this.__onVideoLoadededMetadata);
- },
-
- _onPostrollTimeUpdate: function(e) {
- if (this.postroll.currentTime >= this.stillImageTime - 0.1) {
- this._resetPreview();
- }
- },
-
- _clearTimeouts: function() {
- clearTimeout(this._resetVideoTimeout);
- clearTimeout(this._resetPostrollTimeout);
- clearTimeout(this._resetPreviewTimeout);
- this.postroll.removeEventListener('timeupdate', this.__onPostrollTimeUpdate);
- },
-
- _setDuration: function(duration) {
- this.duration = duration;
- if (typeof this.stillImageTime !== 'number' || isNaN(this.stillImageTime)) {
-
-
-
- this.stillImageTime = duration * 0.5;
- }
- this.previewStart = Math.max(0, this.stillImageTime - this.previewMs / 1000);
- },
-
- _resetPostroll: function() {
- this.postroll.pause();
- this.postroll.currentTime = this.stillImageTime;
- },
-
- _resetVideo: function() {
- this.video.pause();
- this.video.currentTime = 0;
- this.video.muted = false;
- },
-
- _startVideoPlayback: function() {
- this.video.play();
- this._resetPostroll();
- },
-
- _startPostrollPlayback: function() {
- this._resetPostroll();
- this.postroll.play();
- },
-
- _resetPlayback: function() {
- this._playing = false;
- this._resetVideo();
- this._resetPostroll();
- },
-
- _resetPreview: function() {
- this.postroll.removeEventListener('timeupdate', this.__onPostrollTimeUpdate);
- this._resetPostroll();
- this.container.classList.remove('preview');
- },
-
- load: function() {
- this.video.load();
- this.postroll.load();
- },
-
- play: function() {
- if (this._playing) {
- return;
- }
- if (!this._canPlayThrough) {
- this._playWhenReady = true;
- this._clearTimeouts();
- this.load();
- this.container.classList.add('loading');
- return;
- }
- this._playing = true;
- this._clearTimeouts();
- this._startPostrollPlayback();
- this.video.currentTime = 0;
- this._resetPostrollTimeout = setTimeout(this.__startVideoPlayback, this.postrollMs);
- this.container.classList.add('active');
- },
-
- stop: function() {
- if (!this._playing) {
- return;
- }
- this.video.muted = true;
- this._clearTimeouts();
- this.container.classList.remove('active');
- this._resetVideoTimeout = setTimeout(this.__resetPlayback, this.deactivateMs);
- },
-
- preview: function() {
- if (this._playing) {
- return;
- }
- this._clearTimeouts();
- this.postroll.currentTime = this.previewStart;
- this.postroll.play();
- this.container.classList.add('preview');
- this._previewCompleteTimeout = setTimeout(this.__resetPreview, 1000 * (this.stillImageTime - this.previewStart));
-
- this.postroll.addEventListener('timeupdate', this.__onPostrollTimeUpdate);
- },
- };
- module.exports = LivePhoto;