You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
268 lines
6.5 KiB
268 lines
6.5 KiB
/** |
|
* 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);
|
|
|