nextcloud-gallery/js/slideshowzoomablepreview.js

269 lines
6.5 KiB
JavaScript

/**
* Nextcloud - Gallery
*
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Olivier Paroz <galleryapps@oparoz.com>
*
* @copyright Olivier Paroz 2017
*/
/* global SlideShow, bigshot*/
(function ($, SlideShow, bigshot) {
"use strict";
/**
* Creates a zoomable preview
*
* @param {*} container
* @constructor
*/
var ZoomablePreview = function (container) {
this.container = container;
this.element = this.container.get(0);
var bigshotContainer = container.find('.bigshotContainer');
this.bigshotElement = bigshotContainer.get(0);
this._detectFullscreen();
this._setupControls();
$(window).resize(function () {
this._zoomDecider();
}.bind(this));
};
ZoomablePreview.prototype = {
container: null,
element: null,
bigshotContainer: null,
bigshotElement: null,
zoomable: null,
fullScreen: null,
canFullScreen: false,
currentImage: null,
mimeType: null,
maxZoom: 3,
smallImageDimension: 200 / window.devicePixelRatio,
smallImageScale: 2,
/**
* Launches the Bigshot zoomable preview
*
* @param {*} image
* @param {number} currentImage
* @param {string} mimeType
*/
startBigshot: function (image, currentImage, mimeType) {
this.currentImage = currentImage;
this.mimeType = mimeType;
if (this.zoomable !== null) {
this.zoomable.dispose();
this.zoomable = null;
}
var maxZoom = this.maxZoom;
var imgWidth = image.naturalWidth / window.devicePixelRatio;
var imgHeight = image.naturalHeight / window.devicePixelRatio;
// Set arbitrary image dimension when we have a SVG
if (imgWidth === 0 && mimeType === 'image/svg+xml') {
imgWidth = 2048;
imgHeight = 2048;
}
if (imgWidth < this.smallImageDimension &&
imgHeight < this.smallImageDimension &&
this.mimeType !== 'image/svg+xml') {
maxZoom += 3;
this.currentImage.isSmallImage = true;
}
this.zoomable = new bigshot.SimpleImage(new bigshot.ImageParameters({
container: this.bigshotElement,
maxZoom: maxZoom,
minZoom: 0,
touchUI: false,
width: imgWidth,
height: imgHeight
}), image);
// Reset our zoom based on image and window dimensions.
this._resetZoom();
// prevent zoom-on-doubleClick
this.zoomable.addEventListener('dblclick', function (ie) {
ie.preventDefault();
});
// Reset image position and size on orientation change
var self = this;
$(window).bind('orientationchange resize', function () {
self._resetZoom();
});
},
/**
* Resets the element for the next image to be displayed
*/
reset: function () {
if (this.zoomable !== null) {
this.zoomable.stopFlying();
this._resetZoom();
}
},
/**
* Throws away the zoomable preview
*/
stop: function () {
if (this.fullScreen !== null) {
this._fullScreenExit();
}
if (this.zoomable !== null) {
this.zoomable.dispose();
this.zoomable = null;
}
},
/**
* Launches fullscreen mode if the browser supports it
*/
fullScreenToggle: function () {
if (this.zoomable === null) {
return;
}
if (this.fullScreen !== null) {
this._fullScreenExit();
} else {
this._fullScreenStart();
}
},
/**
* Resizes the image to its original size
*/
zoomToOriginal: function () {
if (this.zoomable === null) {
return;
}
if (this.currentImage.isSmallImage) {
this.zoomable.flyTo(0, 0, this.smallImageScale, true);
} else if ($(window).width() < this.zoomable.width ||
$(window).height() < this.zoomable.height) {
// The image is larger than the window.
// Set minimum zoom and call flyZoomToFit.
this.zoomable.setMinZoom(this.zoomable.getZoomToFitValue());
this.zoomable.flyZoomToFit();
} else {
this.zoomable.setMinZoom(0);
this.zoomable.flyTo(0, 0, 0, true);
}
},
/**
* Fits the image in the browser window
*/
zoomToFit: function () {
if (this.zoomable !== null) {
this.zoomable.flyZoomToFit();
}
},
/**
* Detect fullscreen capability
* @private
*/
_detectFullscreen: function () {
this.canFullScreen = this.element.requestFullscreen !== undefined ||
this.element.mozRequestFullScreen !== undefined ||
this.element.webkitRequestFullscreen !== undefined ||
this.element.msRequestFullscreen !== undefined;
},
/**
* Makes UI controls work on touchscreens. Pinch only works on iOS
* @private
*/
_setupControls: function () {
var browser = new bigshot.Browser();
this.container.children('input').each(function (i, e) {
browser.registerListener(e, 'click', browser.stopEventBubblingHandler(), false);
browser.registerListener(e, 'touchstart', browser.stopEventBubblingHandler(),
false);
browser.registerListener(e, 'touchend', browser.stopEventBubblingHandler(), false);
});
},
/**
* Determines whether the image should be shown at its original size or if it should fill
* the screen
*
* @private
*/
_zoomDecider: function () {
if (this.zoomable !== null) {
if (this.fullScreen === null && this.mimeType !== 'image/svg+xml') {
this.zoomToOriginal();
} else {
this.zoomToFit();
}
}
},
/**
* Resets the image to its original zoomed size
*
* @private
*/
_resetZoom: function () {
if (this.zoomable === null) {
return;
}
if (this.currentImage.isSmallImage) {
this.zoomable.setZoom(this.smallImageScale, true);
} else if ($(window).width() < this.zoomable.width ||
$(window).height() < this.zoomable.height ||
this.fullScreen !== null ||
this.mimeType === 'image/svg+xml') {
// The image is larger than the window, or we are fullScreen,
// or this is an SVG. Set minimum zoom and call zoomToFit.
this.zoomable.setMinZoom(this.zoomable.getZoomToFitValue());
this.zoomable.zoomToFit();
} else {
// Zoom to the image size.
this.zoomable.setMinZoom(0);
this.zoomable.setZoom(0, true);
}
},
/**
* Starts the fullscreen previews
*
* @private
*/
_fullScreenStart: function () {
if (!this.canFullScreen) {
return;
}
this.fullScreen = new bigshot.FullScreen(this.element);
this.fullScreen.open();
this.fullScreen.addOnClose(function () {
this._fullScreenExit();
}.bind(this));
},
/**
* Stops the fullscreen previews
*
* @private
*/
_fullScreenExit: function () {
if (this.fullScreen === null) {
return;
}
this.fullScreen.close();
this.fullScreen = null;
this._zoomDecider();
}
};
SlideShow.ZoomablePreview = ZoomablePreview;
})(jQuery, SlideShow, bigshot);