flipbook-vue
Version:
3D page flip effect for Vue.js
1,331 lines (1,276 loc) • 44.4 kB
JavaScript
/*!
* @license
* flipbook-vue v1.0.0-beta.4
* Copyright © 2023 Takeshi Sone.
* Released under the MIT License.
*/
'use strict';
var rematrix = require('rematrix');
var vue = require('vue');
var Matrix = /*@__PURE__*/(function () {
function Matrix(arg) {
if (arg) {
if (arg.m) {
this.m = [].concat( arg.m );
} else {
this.m = [].concat( arg );
}
} else {
this.m = rematrix.identity();
}
}
Matrix.prototype.clone = function clone () {
return new Matrix(this);
};
Matrix.prototype.multiply = function multiply$1 (m) {
return this.m = rematrix.multiply(this.m, m);
};
Matrix.prototype.perspective = function perspective$1 (d) {
return this.multiply(rematrix.perspective(d));
};
Matrix.prototype.transformX = function transformX (x) {
return (x * this.m[0] + this.m[12]) / (x * this.m[3] + this.m[15]);
};
Matrix.prototype.translate = function translate$1 (x, y) {
return this.multiply(rematrix.translate(x, y));
};
Matrix.prototype.translate3d = function translate3d$1 (x, y, z) {
return this.multiply(rematrix.translate3d(x, y, z));
};
Matrix.prototype.rotateY = function rotateY$1 (deg) {
return this.multiply(rematrix.rotateY(deg));
};
Matrix.prototype.toString = function toString$1 () {
return rematrix.toString(this.m);
};
return Matrix;
}());
var spinner = "data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22500%22%20height%3D%22500%22%20viewBox%3D%220%200%20500%20500%22%20fill%3D%22transparent%22%20style%3D%22background-color%3A%20%23fff%22%3E%20%20%3Ccircle%20%20%20%20cx%3D%22250%22%20%20%20%20cy%3D%22250%22%20%20%20%20r%3D%2248%22%20%20%20%20stroke%3D%22%23333%22%20%20%20%20stroke-width%3D%222%22%20%20%20%20stroke-dasharray%3D%22271%2030%22%20%20%3E%20%20%20%20%3CanimateTransform%20%20%20%20%20%20attributeName%3D%22transform%22%20%20%20%20%20%20attributeType%3D%22XML%22%20%20%20%20%20%20type%3D%22rotate%22%20%20%20%20%20%20from%3D%220%20250%20250%22%20%20%20%20%20%20to%3D%22360%20250%20250%22%20%20%20%20%20%20dur%3D%221s%22%20%20%20%20%20%20repeatCount%3D%22indefinite%22%20%20%20%20%2F%3E%20%20%3C%2Fcircle%3E%3C%2Fsvg%3E";
var easeIn, easeInOut, easeOut;
easeIn = function(x) {
return Math.pow(x, 2);
};
easeOut = function(x) {
return 1 - easeIn(1 - x);
};
easeInOut = function(x) {
if (x < 0.5) {
return easeIn(x * 2) / 2;
} else {
return 0.5 + easeOut((x - 0.5) * 2) / 2;
}
};
var script = {
props: {
pages: {
type: Array,
required: true
},
pagesHiRes: {
type: Array,
default: function() {
return [];
}
},
flipDuration: {
type: Number,
default: 1000
},
zoomDuration: {
type: Number,
default: 500
},
zooms: {
type: Array,
default: function() {
return [1, 2, 4];
}
},
perspective: {
type: Number,
default: 2400
},
nPolygons: {
type: Number,
default: 10
},
ambient: {
type: Number,
default: 0.4
},
gloss: {
type: Number,
default: 0.6
},
swipeMin: {
type: Number,
default: 3
},
singlePage: {
type: Boolean,
default: false
},
forwardDirection: {
validator: function(val) {
return val === 'right' || val === 'left';
},
default: 'right'
},
centering: {
type: Boolean,
default: true
},
startPage: {
type: Number,
default: null
},
loadingImage: {
type: String,
default: spinner
},
clickToZoom: {
type: Boolean,
default: true
},
dragToFlip: {
type: Boolean,
default: true
},
wheel: {
type: String,
default: 'scroll'
}
},
data: function() {
return {
viewWidth: 0,
viewHeight: 0,
imageWidth: null,
imageHeight: null,
displayedPages: 1,
nImageLoad: 0,
nImageLoadTrigger: 0,
imageLoadCallback: null,
currentPage: 0,
firstPage: 0,
secondPage: 1,
zoomIndex: 0,
zoom: 1,
zooming: false,
touchStartX: null,
touchStartY: null,
maxMove: 0,
activeCursor: null,
hasTouchEvents: false,
hasPointerEvents: false,
minX: 2e308,
maxX: -2e308,
preloadedImages: {},
flip: {
progress: 0,
direction: null,
frontImage: null,
backImage: null,
auto: false,
opacity: 1
},
currentCenterOffset: null,
animatingCenter: false,
startScrollLeft: 0,
startScrollTop: 0,
scrollLeft: 0,
scrollTop: 0,
loadedImages: {}
};
},
computed: {
IE: function() {
return typeof navigator !== 'undefined' && /Trident/.test(navigator.userAgent);
},
canFlipLeft: function() {
if (this.forwardDirection === 'left') {
return this.canGoForward;
} else {
return this.canGoBack;
}
},
canFlipRight: function() {
if (this.forwardDirection === 'right') {
return this.canGoForward;
} else {
return this.canGoBack;
}
},
canZoomIn: function() {
return !this.zooming && this.zoomIndex < this.zooms_.length - 1;
},
canZoomOut: function() {
return !this.zooming && this.zoomIndex > 0;
},
numPages: function() {
if (this.pages[0] === null) {
return this.pages.length - 1;
} else {
return this.pages.length;
}
},
page: function() {
if (this.pages[0] !== null) {
return this.currentPage + 1;
} else {
return Math.max(1, this.currentPage);
}
},
zooms_: function() {
return this.zooms || [1];
},
canGoForward: function() {
return !this.flip.direction && this.currentPage < this.pages.length - this.displayedPages;
},
canGoBack: function() {
return !this.flip.direction && this.currentPage >= this.displayedPages && !(this.displayedPages === 1 && !this.pageUrl(this.firstPage - 1));
},
leftPage: function() {
if (this.forwardDirection === 'right' || this.displayedPages === 1) {
return this.firstPage;
} else {
return this.secondPage;
}
},
rightPage: function() {
if (this.forwardDirection === 'left') {
return this.firstPage;
} else {
return this.secondPage;
}
},
showLeftPage: function() {
return this.pageUrl(this.leftPage);
},
showRightPage: function() {
return this.pageUrl(this.rightPage) && this.displayedPages === 2;
},
cursor: function() {
if (this.activeCursor) {
return this.activeCursor;
} else if (this.IE) {
return 'auto';
} else if (this.clickToZoom && this.canZoomIn) {
return 'zoom-in';
} else if (this.clickToZoom && this.canZoomOut) {
return 'zoom-out';
} else if (this.dragToFlip) {
return 'grab';
} else {
return 'auto';
}
},
pageScale: function() {
var scale, vw, xScale, yScale;
vw = this.viewWidth / this.displayedPages;
xScale = vw / this.imageWidth;
yScale = this.viewHeight / this.imageHeight;
scale = xScale < yScale ? xScale : yScale;
if (scale < 1) {
return scale;
} else {
return 1;
}
},
pageWidth: function() {
return Math.round(this.imageWidth * this.pageScale);
},
pageHeight: function() {
return Math.round(this.imageHeight * this.pageScale);
},
xMargin: function() {
return (this.viewWidth - this.pageWidth * this.displayedPages) / 2;
},
yMargin: function() {
return (this.viewHeight - this.pageHeight) / 2;
},
polygonWidth: function() {
var w;
w = this.pageWidth / this.nPolygons;
w = Math.ceil(w + 1 / this.zoom);
return w + 'px';
},
polygonHeight: function() {
return this.pageHeight + 'px';
},
polygonBgSize: function() {
return ((this.pageWidth) + "px " + (this.pageHeight) + "px");
},
polygonArray: function() {
return this.makePolygonArray('front').concat(this.makePolygonArray('back'));
},
boundingLeft: function() {
var x;
if (this.displayedPages === 1) {
return this.xMargin;
} else {
x = this.pageUrl(this.leftPage) ? this.xMargin : this.viewWidth / 2;
if (x < this.minX) {
return x;
} else {
return this.minX;
}
}
},
boundingRight: function() {
var x;
if (this.displayedPages === 1) {
return this.viewWidth - this.xMargin;
} else {
x = this.pageUrl(this.rightPage) ? this.viewWidth - this.xMargin : this.viewWidth / 2;
if (x > this.maxX) {
return x;
} else {
return this.maxX;
}
}
},
centerOffset: function() {
var retval;
retval = this.centering ? Math.round(this.viewWidth / 2 - (this.boundingLeft + this.boundingRight) / 2) : 0;
if (this.currentCenterOffset === null && this.imageWidth !== null) {
this.currentCenterOffset = retval;
}
return retval;
},
centerOffsetSmoothed: function() {
return Math.round(this.currentCenterOffset);
},
dragToScroll: function() {
return !this.hasTouchEvents;
},
scrollLeftMin: function() {
var w;
w = (this.boundingRight - this.boundingLeft) * this.zoom;
if (w < this.viewWidth) {
return (this.boundingLeft + this.centerOffsetSmoothed) * this.zoom - (this.viewWidth - w) / 2;
} else {
return (this.boundingLeft + this.centerOffsetSmoothed) * this.zoom;
}
},
scrollLeftMax: function() {
var w;
w = (this.boundingRight - this.boundingLeft) * this.zoom;
if (w < this.viewWidth) {
return (this.boundingLeft + this.centerOffsetSmoothed) * this.zoom - (this.viewWidth - w) / 2;
} else {
return (this.boundingRight + this.centerOffsetSmoothed) * this.zoom - this.viewWidth;
}
},
scrollTopMin: function() {
var h;
h = this.pageHeight * this.zoom;
if (h < this.viewHeight) {
return this.yMargin * this.zoom - (this.viewHeight - h) / 2;
} else {
return this.yMargin * this.zoom;
}
},
scrollTopMax: function() {
var h;
h = this.pageHeight * this.zoom;
if (h < this.viewHeight) {
return this.yMargin * this.zoom - (this.viewHeight - h) / 2;
} else {
return (this.yMargin + this.pageHeight) * this.zoom - this.viewHeight;
}
},
scrollLeftLimited: function() {
return Math.min(this.scrollLeftMax, Math.max(this.scrollLeftMin, this.scrollLeft));
},
scrollTopLimited: function() {
return Math.min(this.scrollTopMax, Math.max(this.scrollTopMin, this.scrollTop));
}
},
mounted: function() {
window.addEventListener('resize', this.onResize, {
passive: true
});
this.onResize();
this.zoom = this.zooms_[0];
return this.goToPage(this.startPage);
},
beforeDestroy: function() {
return window.removeEventListener('resize', this.onResize, {
passive: true
});
},
methods: {
onResize: function() {
var viewport;
viewport = this.$refs.viewport;
if (!viewport) {
return;
}
this.viewWidth = viewport.clientWidth;
this.viewHeight = viewport.clientHeight;
this.displayedPages = this.viewWidth > this.viewHeight && !this.singlePage ? 2 : 1;
if (this.displayedPages === 2) {
this.currentPage &= ~1;
}
this.fixFirstPage();
this.minX = 2e308;
return this.maxX = -2e308;
},
fixFirstPage: function() {
if (this.displayedPages === 1 && this.currentPage === 0 && this.pages.length && !this.pageUrl(0)) {
return this.currentPage++;
}
},
pageUrl: function(page, hiRes) {
if ( hiRes === void 0 ) hiRes = false;
var url;
if (hiRes && this.zoom > 1 && !this.zooming) {
url = this.pagesHiRes[page];
if (url) {
return url;
}
}
return this.pages[page] || null;
},
pageUrlLoading: function(page, hiRes) {
if ( hiRes === void 0 ) hiRes = false;
var url;
url = this.pageUrl(page, hiRes);
if (hiRes && this.zoom > 1 && !this.zooming) {
// High-res image doesn't use 'loading'
return url;
}
return url && this.loadImage(url);
},
flipLeft: function() {
if (!this.canFlipLeft) {
return;
}
return this.flipStart('left', true);
},
flipRight: function() {
if (!this.canFlipRight) {
return;
}
return this.flipStart('right', true);
},
makePolygonArray: function(face) {
var bgPos, dRadian, dRotate, direction, i, image, j, lighting, m, originRight, pageMatrix, pageRotation, pageX, polygonWidth, progress, rad, radian, radius, ref, results, rotate, theta, x, x0, x1, z;
if (!this.flip.direction) {
return [];
}
progress = this.flip.progress;
direction = this.flip.direction;
if (this.displayedPages === 1 && direction !== this.forwardDirection) {
progress = 1 - progress;
direction = this.forwardDirection;
}
this.flip.opacity = this.displayedPages === 1 && progress > .7 ? 1 - (progress - .7) / .3 : 1;
image = face === 'front' ? this.flip.frontImage : this.flip.backImage;
polygonWidth = this.pageWidth / this.nPolygons;
pageX = this.xMargin;
originRight = false;
if (this.displayedPages === 1) {
if (this.forwardDirection === 'right') {
if (face === 'back') {
originRight = true;
pageX = this.xMargin - this.pageWidth;
}
} else {
if (direction === 'left') {
if (face === 'back') {
pageX = this.pageWidth - this.xMargin;
} else {
originRight = true;
}
} else {
if (face === 'front') {
pageX = this.pageWidth - this.xMargin;
} else {
originRight = true;
}
}
}
} else {
if (direction === 'left') {
if (face === 'back') {
pageX = this.viewWidth / 2;
} else {
originRight = true;
}
} else {
if (face === 'front') {
pageX = this.viewWidth / 2;
} else {
originRight = true;
}
}
}
pageMatrix = new Matrix();
pageMatrix.translate(this.viewWidth / 2);
pageMatrix.perspective(this.perspective);
pageMatrix.translate(-this.viewWidth / 2);
pageMatrix.translate(pageX, this.yMargin);
pageRotation = 0;
if (progress > 0.5) {
pageRotation = -(progress - 0.5) * 2 * 180;
}
if (direction === 'left') {
pageRotation = -pageRotation;
}
if (face === 'back') {
pageRotation += 180;
}
if (pageRotation) {
if (originRight) {
pageMatrix.translate(this.pageWidth);
}
pageMatrix.rotateY(pageRotation);
if (originRight) {
pageMatrix.translate(-this.pageWidth);
}
}
if (progress < 0.5) {
theta = progress * 2 * Math.PI;
} else {
theta = (1 - (progress - 0.5) * 2) * Math.PI;
}
if (theta === 0) {
theta = 1e-9;
}
radius = this.pageWidth / theta;
radian = 0;
dRadian = theta / this.nPolygons;
rotate = dRadian / 2 / Math.PI * 180;
dRotate = dRadian / Math.PI * 180;
if (originRight) {
rotate = -theta / Math.PI * 180 + dRotate / 2;
}
if (face === 'back') {
rotate = -rotate;
dRotate = -dRotate;
}
this.minX = 2e308;
this.maxX = -2e308;
results = [];
for (i = j = 0, ref = this.nPolygons; (0 <= ref ? j < ref : j > ref); i = 0 <= ref ? ++j : --j) {
bgPos = (i / (this.nPolygons - 1) * 100) + "% 0px";
m = pageMatrix.clone();
rad = originRight ? theta - radian : radian;
x = Math.sin(rad) * radius;
if (originRight) {
x = this.pageWidth - x;
}
z = (1 - Math.cos(rad)) * radius;
if (face === 'back') {
z = -z;
}
m.translate3d(x, 0, z);
m.rotateY(-rotate);
x0 = m.transformX(0);
x1 = m.transformX(polygonWidth);
this.maxX = Math.max(Math.max(x0, x1), this.maxX);
this.minX = Math.min(Math.min(x0, x1), this.minX);
lighting = this.computeLighting(pageRotation - rotate, dRotate);
radian += dRadian;
rotate += dRotate;
results.push([face + i, image, lighting, bgPos, m.toString(), Math.abs(Math.round(z))]);
}
return results;
},
computeLighting: function(rot, dRotate) {
var DEG, POW, blackness, diffuse, gradients, lightingPoints, specular;
gradients = [];
lightingPoints = [-0.5, -0.25, 0, 0.25, 0.5];
if (this.ambient < 1) {
blackness = 1 - this.ambient;
diffuse = lightingPoints.map(function (d) {
return (1 - Math.cos((rot - dRotate * d) / 180 * Math.PI)) * blackness;
});
gradients.push(("linear-gradient(to right,\n rgba(0, 0, 0, " + (diffuse[0]) + "),\n rgba(0, 0, 0, " + (diffuse[1]) + ") 25%,\n rgba(0, 0, 0, " + (diffuse[2]) + ") 50%,\n rgba(0, 0, 0, " + (diffuse[3]) + ") 75%,\n rgba(0, 0, 0, " + (diffuse[4]) + "))"));
}
if (this.gloss > 0 && !this.IE) {
DEG = 30;
POW = 200;
specular = lightingPoints.map(function (d) {
return Math.max(Math.pow( Math.cos((rot + DEG - dRotate * d) / 180 * Math.PI), POW ), Math.pow( Math.cos((rot - DEG - dRotate * d) / 180 * Math.PI), POW ));
});
gradients.push(("linear-gradient(to right,\n rgba(255, 255, 255, " + (specular[0] * this.gloss) + "),\n rgba(255, 255, 255, " + (specular[1] * this.gloss) + ") 25%,\n rgba(255, 255, 255, " + (specular[2] * this.gloss) + ") 50%,\n rgba(255, 255, 255, " + (specular[3] * this.gloss) + ") 75%,\n rgba(255, 255, 255, " + (specular[4] * this.gloss) + "))"));
}
return gradients.join(',');
},
flipStart: function(direction, auto) {
var this$1$1 = this;
if (direction !== this.forwardDirection) {
if (this.displayedPages === 1) {
this.flip.frontImage = this.pageUrl(this.currentPage - 1);
this.flip.backImage = null;
} else {
this.flip.frontImage = this.pageUrl(this.firstPage);
this.flip.backImage = this.pageUrl(this.currentPage - this.displayedPages + 1);
}
} else {
if (this.displayedPages === 1) {
this.flip.frontImage = this.pageUrl(this.currentPage);
this.flip.backImage = null;
} else {
this.flip.frontImage = this.pageUrl(this.secondPage);
this.flip.backImage = this.pageUrl(this.currentPage + this.displayedPages);
}
}
this.flip.direction = direction;
this.flip.progress = 0;
return requestAnimationFrame(function () {
return requestAnimationFrame(function () {
if (this$1$1.flip.direction !== this$1$1.forwardDirection) {
if (this$1$1.displayedPages === 2) {
this$1$1.firstPage = this$1$1.currentPage - this$1$1.displayedPages;
}
} else {
if (this$1$1.displayedPages === 1) {
this$1$1.firstPage = this$1$1.currentPage + this$1$1.displayedPages;
} else {
this$1$1.secondPage = this$1$1.currentPage + 1 + this$1$1.displayedPages;
}
}
if (auto) {
return this$1$1.flipAuto(true);
}
});
});
},
flipAuto: function(ease) {
var this$1$1 = this;
var animate, duration, startRatio, t0;
t0 = Date.now();
duration = this.flipDuration * (1 - this.flip.progress);
startRatio = this.flip.progress;
this.flip.auto = true;
this.$emit(("flip-" + (this.flip.direction) + "-start"), this.page);
animate = function () {
return requestAnimationFrame(function () {
var ratio, t;
t = Date.now() - t0;
ratio = startRatio + t / duration;
if (ratio > 1) {
ratio = 1;
}
this$1$1.flip.progress = ease ? easeInOut(ratio) : ratio;
if (ratio < 1) {
return animate();
} else {
if (this$1$1.flip.direction !== this$1$1.forwardDirection) {
this$1$1.currentPage -= this$1$1.displayedPages;
} else {
this$1$1.currentPage += this$1$1.displayedPages;
}
this$1$1.$emit(("flip-" + (this$1$1.flip.direction) + "-end"), this$1$1.page);
if (this$1$1.displayedPages === 1 && this$1$1.flip.direction === this$1$1.forwardDirection) {
this$1$1.flip.direction = null;
} else {
this$1$1.onImageLoad(1, function () {
return this$1$1.flip.direction = null;
});
}
return this$1$1.flip.auto = false;
}
});
};
return animate();
},
flipRevert: function() {
var this$1$1 = this;
var animate, duration, startRatio, t0;
t0 = Date.now();
duration = this.flipDuration * this.flip.progress;
startRatio = this.flip.progress;
this.flip.auto = true;
animate = function () {
return requestAnimationFrame(function () {
var ratio, t;
t = Date.now() - t0;
ratio = startRatio - startRatio * t / duration;
if (ratio < 0) {
ratio = 0;
}
this$1$1.flip.progress = ratio;
if (ratio > 0) {
return animate();
} else {
this$1$1.firstPage = this$1$1.currentPage;
this$1$1.secondPage = this$1$1.currentPage + 1;
if (this$1$1.displayedPages === 1 && this$1$1.flip.direction !== this$1$1.forwardDirection) {
this$1$1.flip.direction = null;
} else {
this$1$1.onImageLoad(1, function () {
return this$1$1.flip.direction = null;
});
}
return this$1$1.flip.auto = false;
}
});
};
return animate();
},
onImageLoad: function(trigger, cb) {
this.nImageLoad = 0;
this.nImageLoadTrigger = trigger;
return this.imageLoadCallback = cb;
},
didLoadImage: function(ev) {
if (this.imageWidth === null) {
this.imageWidth = (ev.target || ev.path[0]).naturalWidth;
this.imageHeight = (ev.target || ev.path[0]).naturalHeight;
this.preloadImages();
}
if (!this.imageLoadCallback) {
return;
}
if (++this.nImageLoad >= this.nImageLoadTrigger) {
this.imageLoadCallback();
return this.imageLoadCallback = null;
}
},
zoomIn: function(zoomAt) {
if ( zoomAt === void 0 ) zoomAt = null;
if (!this.canZoomIn) {
return;
}
this.zoomIndex += 1;
return this.zoomTo(this.zooms_[this.zoomIndex], zoomAt);
},
zoomOut: function(zoomAt) {
if ( zoomAt === void 0 ) zoomAt = null;
if (!this.canZoomOut) {
return;
}
this.zoomIndex -= 1;
return this.zoomTo(this.zooms_[this.zoomIndex], zoomAt);
},
zoomTo: function(zoom, zoomAt) {
var this$1$1 = this;
if ( zoomAt === void 0 ) zoomAt = null;
var animate, containerFixedX, containerFixedY, end, endX, endY, fixedX, fixedY, rect, start, startX, startY, t0, viewport;
viewport = this.$refs.viewport;
if (zoomAt) {
rect = viewport.getBoundingClientRect();
fixedX = zoomAt.pageX - rect.left;
fixedY = zoomAt.pageY - rect.top;
} else {
fixedX = viewport.clientWidth / 2;
fixedY = viewport.clientHeight / 2;
}
start = this.zoom;
end = zoom;
startX = viewport.scrollLeft;
startY = viewport.scrollTop;
containerFixedX = fixedX + startX;
containerFixedY = fixedY + startY;
endX = containerFixedX / start * end - fixedX;
endY = containerFixedY / start * end - fixedY;
t0 = Date.now();
this.zooming = true;
this.$emit('zoom-start', zoom);
animate = function () {
return requestAnimationFrame(function () {
var ratio, t;
t = Date.now() - t0;
ratio = t / this$1$1.zoomDuration;
if (ratio > 1 || this$1$1.IE) {
ratio = 1;
}
ratio = easeInOut(ratio);
this$1$1.zoom = start + (end - start) * ratio;
this$1$1.scrollLeft = startX + (endX - startX) * ratio;
this$1$1.scrollTop = startY + (endY - startY) * ratio;
if (t < this$1$1.zoomDuration) {
return animate();
} else {
this$1$1.$emit('zoom-end', zoom);
this$1$1.zooming = false;
this$1$1.zoom = zoom;
this$1$1.scrollLeft = endX;
return this$1$1.scrollTop = endY;
}
});
};
animate();
if (end > 1) {
return this.preloadImages(true);
}
},
zoomAt: function(zoomAt) {
this.zoomIndex = (this.zoomIndex + 1) % this.zooms_.length;
return this.zoomTo(this.zooms_[this.zoomIndex], zoomAt);
},
swipeStart: function(touch) {
this.touchStartX = touch.pageX;
this.touchStartY = touch.pageY;
this.maxMove = 0;
if (this.zoom <= 1) {
if (this.dragToFlip) {
return this.activeCursor = 'grab';
}
} else {
this.startScrollLeft = this.$refs.viewport.scrollLeft;
this.startScrollTop = this.$refs.viewport.scrollTop;
return this.activeCursor = 'all-scroll';
}
},
swipeMove: function(touch) {
var x, y;
if (this.touchStartX == null) {
return;
}
x = touch.pageX - this.touchStartX;
y = touch.pageY - this.touchStartY;
this.maxMove = Math.max(this.maxMove, Math.abs(x));
this.maxMove = Math.max(this.maxMove, Math.abs(y));
if (this.zoom > 1) {
if (this.dragToScroll) {
this.dragScroll(x, y);
}
return;
}
if (!this.dragToFlip) {
return;
}
if (Math.abs(y) > Math.abs(x)) {
return;
}
this.activeCursor = 'grabbing';
if (x > 0) {
if (this.flip.direction === null && this.canFlipLeft && x >= this.swipeMin) {
this.flipStart('left', false);
}
if (this.flip.direction === 'left') {
this.flip.progress = x / this.pageWidth;
if (this.flip.progress > 1) {
this.flip.progress = 1;
}
}
} else {
if (this.flip.direction === null && this.canFlipRight && x <= -this.swipeMin) {
this.flipStart('right', false);
}
if (this.flip.direction === 'right') {
this.flip.progress = -x / this.pageWidth;
if (this.flip.progress > 1) {
this.flip.progress = 1;
}
}
}
return true;
},
swipeEnd: function(touch) {
if (this.touchStartX == null) {
return;
}
if (this.clickToZoom && this.maxMove < this.swipeMin) {
this.zoomAt(touch);
}
if (this.flip.direction !== null && !this.flip.auto) {
if (this.flip.progress > 1 / 4) {
this.flipAuto(false);
} else {
this.flipRevert();
}
}
this.touchStartX = null;
return this.activeCursor = null;
},
onTouchStart: function(ev) {
this.hasTouchEvents = true;
return this.swipeStart(ev.changedTouches[0]);
},
onTouchMove: function(ev) {
if (this.swipeMove(ev.changedTouches[0])) {
if (ev.cancelable) {
return ev.preventDefault();
}
}
},
onTouchEnd: function(ev) {
return this.swipeEnd(ev.changedTouches[0]);
},
onPointerDown: function(ev) {
this.hasPointerEvents = true;
if (this.hasTouchEvents) {
return;
}
if (ev.which && ev.which !== 1) { // Ignore right-click
return;
}
this.swipeStart(ev);
try {
return ev.target.setPointerCapture(ev.pointerId);
} catch (error) {
}
},
onPointerMove: function(ev) {
if (!this.hasTouchEvents) {
return this.swipeMove(ev);
}
},
onPointerUp: function(ev) {
if (this.hasTouchEvents) {
return;
}
this.swipeEnd(ev);
try {
return ev.target.releasePointerCapture(ev.pointerId);
} catch (error) {
}
},
onMouseDown: function(ev) {
if (this.hasTouchEvents || this.hasPointerEvents) {
return;
}
if (ev.which && ev.which !== 1) { // Ignore right-click
return;
}
return this.swipeStart(ev);
},
onMouseMove: function(ev) {
if (!(this.hasTouchEvents || this.hasPointerEvents)) {
return this.swipeMove(ev);
}
},
onMouseUp: function(ev) {
if (!(this.hasTouchEvents || this.hasPointerEvents)) {
return this.swipeEnd(ev);
}
},
dragScroll: function(x, y) {
this.scrollLeft = this.startScrollLeft - x;
return this.scrollTop = this.startScrollTop - y;
},
onWheel: function(ev) {
if (this.wheel === 'scroll' && this.zoom > 1 && this.dragToScroll) {
this.scrollLeft = this.$refs.viewport.scrollLeft + ev.deltaX;
this.scrollTop = this.$refs.viewport.scrollTop + ev.deltaY;
if (ev.cancelable) {
ev.preventDefault();
}
}
if (this.wheel === 'zoom') {
if (ev.deltaY >= 100) {
this.zoomOut(ev);
return ev.preventDefault();
} else if (ev.deltaY <= -100) {
this.zoomIn(ev);
return ev.preventDefault();
}
}
},
preloadImages: function(hiRes) {
if ( hiRes === void 0 ) hiRes = false;
var i, j, k, ref, ref1, ref2, ref3, src;
for (i = j = ref = this.currentPage - 3, ref1 = this.currentPage + 3; (ref <= ref1 ? j <= ref1 : j >= ref1); i = ref <= ref1 ? ++j : --j) {
this.pageUrlLoading(i); // this preloads image
}
if (hiRes) {
for (i = k = ref2 = this.currentPage, ref3 = this.currentPage + this.displayedPages; (ref2 <= ref3 ? k < ref3 : k > ref3); i = ref2 <= ref3 ? ++k : --k) {
src = this.pagesHiRes[i];
if (src) {
(new Image()).src = src;
}
}
}
},
goToPage: function(p) {
if (p === null || p === this.page) {
return;
}
if (this.pages[0] === null) {
if (this.displayedPages === 2 && p === 1) {
this.currentPage = 0;
} else {
this.currentPage = p;
}
} else {
this.currentPage = p - 1;
}
this.minX = 2e308;
this.maxX = -2e308;
return this.currentCenterOffset = this.centerOffset;
},
loadImage: function(url) {
var this$1$1 = this;
var img;
if (this.imageWidth === null) {
// First loaded image defines the image width and height.
// So it must be true image, not 'loading' image.
return url;
} else {
if (this.loadedImages[url]) {
return url;
} else {
img = new Image();
img.onload = function () {
if (this$1$1.$set) {
return this$1$1.$set(this$1$1.loadedImages, url, true);
} else {
return this$1$1.loadedImages[url] = true;
}
};
img.src = url;
return this.loadingImage;
}
}
}
},
watch: {
currentPage: function() {
this.firstPage = this.currentPage;
this.secondPage = this.currentPage + 1;
return this.preloadImages();
},
centerOffset: function() {
var this$1$1 = this;
var animate;
if (this.animatingCenter) {
return;
}
animate = function () {
return requestAnimationFrame(function () {
var diff, rate;
rate = 0.1;
diff = this$1$1.centerOffset - this$1$1.currentCenterOffset;
if (Math.abs(diff) < 0.5) {
this$1$1.currentCenterOffset = this$1$1.centerOffset;
return this$1$1.animatingCenter = false;
} else {
this$1$1.currentCenterOffset += diff * rate;
return animate();
}
});
};
this.animatingCenter = true;
return animate();
},
scrollLeftLimited: function(val) {
var this$1$1 = this;
if (this.IE) {
return requestAnimationFrame(function () {
return this$1$1.$refs.viewport.scrollLeft = val;
});
} else {
return this.$refs.viewport.scrollLeft = val;
}
},
scrollTopLimited: function(val) {
var this$1$1 = this;
if (this.IE) {
return requestAnimationFrame(function () {
return this$1$1.$refs.viewport.scrollTop = val;
});
} else {
return this.$refs.viewport.scrollTop = val;
}
},
pages: function(after, before) {
this.fixFirstPage();
if (!(before != null ? before.length : void 0) && (after != null ? after.length : void 0)) {
if (this.startPage > 1 && after[0] === null) {
return this.currentPage++;
}
}
},
startPage: function(p) {
return this.goToPage(p);
}
}
};
var _hoisted_1 = ["src"];
var _hoisted_2 = ["src"];
function render(_ctx, _cache) {
return (vue.openBlock(), vue.createElementBlock("div", null, [
vue.renderSlot(_ctx.$slots, "default", vue.normalizeProps(vue.guardReactiveProps({
canFlipLeft: _ctx.canFlipLeft,
canFlipRight: _ctx.canFlipRight,
canZoomIn: _ctx.canZoomIn,
canZoomOut: _ctx.canZoomOut,
page: _ctx.page,
numPages: _ctx.numPages,
flipLeft: _ctx.flipLeft,
flipRight: _ctx.flipRight,
zoomIn: _ctx.zoomIn,
zoomOut: _ctx.zoomOut,
}))),
vue.createElementVNode("div", {
class: vue.normalizeClass(["viewport", {
zoom: _ctx.zooming || _ctx.zoom > 1,
'drag-to-scroll': _ctx.dragToScroll,
}]),
ref: "viewport",
style: vue.normalizeStyle({ cursor: _ctx.cursor == 'grabbing' ? 'grabbing' : 'auto' }),
onTouchmove: _cache[7] || (_cache[7] = function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (_ctx.onTouchMove && _ctx.onTouchMove.apply(_ctx, args));
}),
onPointermove: _cache[8] || (_cache[8] = function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (_ctx.onPointerMove && _ctx.onPointerMove.apply(_ctx, args));
}),
onMousemove: _cache[9] || (_cache[9] = function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (_ctx.onMouseMove && _ctx.onMouseMove.apply(_ctx, args));
}),
onTouchend: _cache[10] || (_cache[10] = function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (_ctx.onTouchEnd && _ctx.onTouchEnd.apply(_ctx, args));
}),
onTouchcancel: _cache[11] || (_cache[11] = function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (_ctx.onTouchEnd && _ctx.onTouchEnd.apply(_ctx, args));
}),
onPointerup: _cache[12] || (_cache[12] = function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (_ctx.onPointerUp && _ctx.onPointerUp.apply(_ctx, args));
}),
onPointercancel: _cache[13] || (_cache[13] = function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (_ctx.onPointerUp && _ctx.onPointerUp.apply(_ctx, args));
}),
onMouseup: _cache[14] || (_cache[14] = function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (_ctx.onMouseUp && _ctx.onMouseUp.apply(_ctx, args));
}),
onWheel: _cache[15] || (_cache[15] = function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (_ctx.onWheel && _ctx.onWheel.apply(_ctx, args));
})
}, [
vue.createElementVNode("div", {
class: "flipbook-container",
style: vue.normalizeStyle({ transform: ("scale(" + (_ctx.zoom) + ")") })
}, [
vue.createElementVNode("div", {
class: "click-to-flip left",
style: vue.normalizeStyle({ cursor: _ctx.canFlipLeft ? 'pointer' : 'auto' }),
onClick: _cache[0] || (_cache[0] = function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (_ctx.flipLeft && _ctx.flipLeft.apply(_ctx, args));
})
}, null, 4 /* STYLE */),
vue.createElementVNode("div", {
class: "click-to-flip right",
style: vue.normalizeStyle({ cursor: _ctx.canFlipRight ? 'pointer' : 'auto' }),
onClick: _cache[1] || (_cache[1] = function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (_ctx.flipRight && _ctx.flipRight.apply(_ctx, args));
})
}, null, 4 /* STYLE */),
vue.createElementVNode("div", {
style: vue.normalizeStyle({ transform: ("translateX(" + (_ctx.centerOffsetSmoothed) + "px)") })
}, [
(_ctx.showLeftPage)
? (vue.openBlock(), vue.createElementBlock("img", {
key: 0,
class: "page fixed",
style: vue.normalizeStyle({
width: _ctx.pageWidth + 'px',
height: _ctx.pageHeight + 'px',
left: _ctx.xMargin + 'px',
top: _ctx.yMargin + 'px',
}),
src: _ctx.pageUrlLoading(_ctx.leftPage, true),
onLoad: _cache[2] || (_cache[2] = function ($event) { return (_ctx.didLoadImage($event)); })
}, null, 44 /* STYLE, PROPS, HYDRATE_EVENTS */, _hoisted_1))
: vue.createCommentVNode("v-if", true),
(_ctx.showRightPage)
? (vue.openBlock(), vue.createElementBlock("img", {
key: 1,
class: "page fixed",
style: vue.normalizeStyle({
width: _ctx.pageWidth + 'px',
height: _ctx.pageHeight + 'px',
left: _ctx.viewWidth / 2 + 'px',
top: _ctx.yMargin + 'px',
}),
src: _ctx.pageUrlLoading(_ctx.rightPage, true),
onLoad: _cache[3] || (_cache[3] = function ($event) { return (_ctx.didLoadImage($event)); })
}, null, 44 /* STYLE, PROPS, HYDRATE_EVENTS */, _hoisted_2))
: vue.createCommentVNode("v-if", true),
vue.createElementVNode("div", {
style: vue.normalizeStyle({ opacity: _ctx.flip.opacity })
}, [
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(_ctx.polygonArray, function (ref) {
var key = ref[0];
var bgImage = ref[1];
var lighting = ref[2];
var bgPos = ref[3];
var transform = ref[4];
var z = ref[5];
return (vue.openBlock(), vue.createElementBlock("div", {
class: vue.normalizeClass(["polygon", { blank: !bgImage }]),
key: key,
style: vue.normalizeStyle({
backgroundImage: bgImage && ("url(" + (_ctx.loadImage(bgImage)) + ")"),
backgroundSize: _ctx.polygonBgSize,
backgroundPosition: bgPos,
width: _ctx.polygonWidth,
height: _ctx.polygonHeight,
transform: transform,
zIndex: z,
})
}, [
vue.withDirectives(vue.createElementVNode("div", {
class: "lighting",
style: vue.normalizeStyle({ backgroundImage: lighting })
}, null, 4 /* STYLE */), [
[vue.vShow, lighting.length]
])
], 6 /* CLASS, STYLE */))
}), 128 /* KEYED_FRAGMENT */))
], 4 /* STYLE */),
vue.createElementVNode("div", {
class: "bounding-box",
style: vue.normalizeStyle({
left: _ctx.boundingLeft + 'px',
top: _ctx.yMargin + 'px',
width: _ctx.boundingRight - _ctx.boundingLeft + 'px',
height: _ctx.pageHeight + 'px',
cursor: _ctx.cursor,
}),
onTouchstart: _cache[4] || (_cache[4] = function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (_ctx.onTouchStart && _ctx.onTouchStart.apply(_ctx, args));
}),
onPointerdown: _cache[5] || (_cache[5] = function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (_ctx.onPointerDown && _ctx.onPointerDown.apply(_ctx, args));
}),
onMousedown: _cache[6] || (_cache[6] = function () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];
return (_ctx.onMouseDown && _ctx.onMouseDown.apply(_ctx, args));
})
}, null, 36 /* STYLE, HYDRATE_EVENTS */)
], 4 /* STYLE */)
], 4 /* STYLE */)
], 38 /* CLASS, STYLE, HYDRATE_EVENTS */)
]))
}
var e=[],t=[];function n(n,r){if(n&&"undefined"!=typeof document){var a,s=!0===r.prepend?"prepend":"append",d=!0===r.singleTag,i="string"==typeof r.container?document.querySelector(r.container):document.getElementsByTagName("head")[0];if(d){var u=e.indexOf(i);-1===u&&(u=e.push(i)-1,t[u]={}),a=t[u]&&t[u][s]?t[u][s]:t[u][s]=c();}else { a=c(); }65279===n.charCodeAt(0)&&(n=n.substring(1)),a.styleSheet?a.styleSheet.cssText+=n:a.appendChild(document.createTextNode(n));}function c(){var e=document.createElement("style");if(e.setAttribute("type","text/css"),r.attributes){ for(var t=Object.keys(r.attributes),n=0;n<t.length;n++){ e.setAttribute(t[n],r.attributes[t[n]]); } }var a="prepend"===s?"afterbegin":"beforeend";return i.insertAdjacentElement(a,e),e}}
var css = ".viewport[data-v-5c04eecf]{-webkit-overflow-scrolling:touch;height:100%;width:100%}.viewport.zoom[data-v-5c04eecf]{overflow:scroll}.viewport.zoom.drag-to-scroll[data-v-5c04eecf]{overflow:hidden}.flipbook-container[data-v-5c04eecf]{height:100%;position:relative;-webkit-transform-origin:top left;transform-origin:top left;-webkit-user-select:none;user-select:none;width:100%}.click-to-flip[data-v-5c04eecf]{height:100%;position:absolute;top:0;-webkit-user-select:none;user-select:none;width:50%}.click-to-flip.left[data-v-5c04eecf]{left:0}.click-to-flip.right[data-v-5c04eecf]{right:0}.bounding-box[data-v-5c04eecf]{position:absolute;-webkit-user-select:none;user-select:none}.page[data-v-5c04eecf],.polygon[data-v-5c04eecf]{-webkit-backface-visibility:hidden;backface-visibility:hidden;position:absolute}.polygon[data-v-5c04eecf]{background-repeat:no-repeat;left:0;top:0;-webkit-transform-origin:center left;transform-origin:center left}.polygon.blank[data-v-5c04eecf]{background-color:#ddd}.polygon .lighting[data-v-5c04eecf]{height:100%;width:100%}";
n(css,{});
script.render = render;
script.__scopeId = "data-v-5c04eecf";
script.__file = "src/Flipbook.vue";
module.exports = script;