AI-BOOK / flipbook.webgl.js
ginipick's picture
Upload 6 files
8b7579c verified
/*
* Real3D FlipBook [https://real3dflipbook.com]
* @author creativeinteractivemedia [https://codecanyon.net/user/creativeinteractivemedia/portfolio]
* @version 4.10
* @date 2025-05-15
*/
'use strict';
var FLIPBOOK = FLIPBOOK || {};
{
FLIPBOOK.PageWebGL = function (book, i, hard, options, preloaderMatF, preloaderMatB) {
THREE.Object3D.call(this);
this.book = book;
this.index = i;
this.pW = options.pageWidth;
this.pH = options.pageHeight;
this.nfacesw = options.pageSegmentsW;
this.nfacesh = options.pageSegmentsH;
this.mats = [];
this.pageHardness = hard;
this.pageThickness = hard;
this.duration = options.pageFlipDuration;
this.angle = 0;
this.force = 10;
this.offset = 0;
this.mod = null;
this.bend = null;
this.pivot = null;
this.isFlippedLeft = false;
this.isFlippedRight = true;
this.flippingLeft = false;
this.flippingRight = false;
this.options = options;
var index = options.rightToLeft ? options.pages.length / 2 - this.index - 1 : this.index;
this.indexF = options.rightToLeft ? 2 * index + 1 : 2 * index;
this.indexB = options.rightToLeft ? 2 * index : 2 * index + 1;
this.showing = false;
this.preloaderMatF = preloaderMatF;
this.preloaderMatB = preloaderMatB;
this.preloaderMatF = preloaderMatF;
this.preloaderMatB = preloaderMatB;
this.htmlLoaded = {
front: false,
back: false,
};
this.animations = [];
var self = this;
if (i == 0 && this.options.cornerCurl) {
this.nfacesw = 20;
this.nfacesh = 20;
var obj = { force: 0 };
this.cornerCurlTween = FLIPBOOK.animate({
from: obj.force,
to: 1,
duration: 1000,
easing: 'easeInOutQuad',
repeat: Infinity,
yoyo: true,
step: function (f) {
if (self.cornerCurl) {
self.b2.force = f * -1.8;
if (self.modF) self.modF.apply();
self.book.needsUpdate = true;
}
},
});
this.animations.push(this.cornerCurlTween);
}
this.gF = new THREE.BoxGeometry(this.pW, this.pH, 0.01, this.nfacesw, this.nfacesh, 0);
var basicMat = new THREE.MeshBasicMaterial({
color: 0xededed,
});
var mats = [basicMat, basicMat, basicMat, basicMat, preloaderMatF, preloaderMatB];
var mats2;
mats2 = [basicMat, basicMat, basicMat, basicMat, basicMat, basicMat];
if (this.options.pagePreloader) {
mats2 = [basicMat, basicMat, basicMat, basicMat, preloaderMatF, preloaderMatB];
}
this.cube = new THREE.Mesh(this.gF, mats);
this.cube.position.x = this.pW * 0.5;
if (this.options.shadows) {
this.cube.castShadow = true;
this.cube.receiveShadow = true;
}
this.gF.faceVertexUvs[1] = this.gF.faceVertexUvs[0];
this.showMat();
this.cubeEmpty = new THREE.Mesh(new THREE.BoxGeometry(this.pW, this.pH, 0.01, 1, 1, 0), mats2);
this.cubeEmpty.position.x = this.pW * 0.5;
this.pageFlippedAngle = (Math.PI * this.options.pageFlippedAngle) / 180;
this.bendF = new MOD3.Bend(0, 0, 0);
this.bendF.constraint = MOD3.ModConstant.LEFT;
if (this.pH > this.pW) {
this.bendF.switchAxes = true;
}
this.b2 = new MOD3.Bend(0, 0, 0);
this.b2.constraint = MOD3.ModConstant.LEFT;
if (this.pH > this.pW) {
this.b2.switchAxes = true;
}
this.b2.offset = 0.98;
this.b2.setAngle(1);
this.modF = new MOD3.ModifierStack(new MOD3.LibraryThree(), this.cube);
this.modF.addModifier(this.bendF);
if (i == 0 && this.options.cornerCurl) {
this.modF.addModifier(this.b2);
}
this.modF.apply();
};
FLIPBOOK.PageWebGL.prototype = new THREE.Object3D();
FLIPBOOK.PageWebGL.prototype.constructor = FLIPBOOK.PageWebGL;
FLIPBOOK.PageWebGL.prototype.startCornerCurl = function () {
this.cornerCurl = true;
};
FLIPBOOK.PageWebGL.prototype.stopCornerCurl = function () {
this.cornerCurl = false;
this.b2.force = 0;
if (this.modF) this.modF.apply();
};
FLIPBOOK.PageWebGL.prototype.loadHTML = async function (side, callback) {
var index = side == 'front' ? this.indexF : this.indexB;
var self = this;
if (!this.htmlLoaded[side]) {
this.options.main.loadPageHTML(index, function (_) {
self.htmlLoaded[side] = true;
callback.call(self);
});
} else {
callback.call(this);
}
};
FLIPBOOK.PageWebGL.prototype.load = function (side, callback, _) {
var main = this.book.main;
if (!main.wrapperH) {
return;
}
if (!main.zoom) {
return;
}
var self = this;
var options = this.book.options;
var main = options.main;
this.disposed = false;
var o = options;
var pageSize = main.wrapperH * main.zoom;
var size = pageSize < o.pageTextureSizeSmall * 0.8 ? o.pageTextureSizeSmall : o.pageTextureSize;
const { p: texture } = o;
if (side == 'front') {
if (!this.options.cover && this.index == 0) {
return;
}
if (this.sizeFront == size) {
if (callback) {
callback.call(this);
}
} else {
main.loadPage(this.indexF, size, function (page) {
if (self.disposed) return;
if (!page || texture) {
if (callback) {
callback.call(self);
}
return;
}
if (self.sizeFront == size) {
if (callback) {
callback.call(self);
}
return;
}
self.sizeFront = size;
var t1;
if (page.imageBitmap) {
const bitmap = page.imageBitmap[size] || page.imageBitmap;
t1 = new THREE.Texture(bitmap);
t1.offset.y = 1;
t1.repeat.y = -1;
} else {
t1 = new THREE.Texture();
t1.image = page.image[size] || page.image;
}
t1.minFilter = THREE.LinearFilter;
t1.generateMipmaps = false;
t1.needsUpdate = true;
var pageIndex = 2 * self.index;
if (!self.options.cover) {
pageIndex--;
}
if (self.options.pages[pageIndex].side == 'left') {
t1.repeat.x = 0.5;
} else if (self.options.pages[pageIndex].side == 'right') {
t1.repeat.x = 0.5;
t1.offset.x = 0.5;
}
self.frontMaterial = self.createMaterial(t1);
self.setFrontMat(self.frontMaterial);
if (callback) {
callback.call(self);
}
});
}
} else if (side == 'back') {
if (!options.cover && this.index == this.book.pages.length - 1) {
return;
}
if (this.sizeBack == size) {
if (callback) {
callback.call(this);
}
} else {
main.loadPage(this.indexB, size, function (page) {
if (self.disposed) return;
if (!page || texture) {
if (callback) {
callback.call(self);
}
return;
}
if (self.sizeBack == size) {
if (callback) {
callback.call(self);
}
return;
}
self.sizeBack = size;
var t2;
if (page.imageBitmap) {
const bitmap = page.imageBitmap[size] || page.imageBitmap;
t2 = new THREE.Texture(bitmap);
t2.offset.y = 1;
t2.repeat.y = -1;
} else {
t2 = new THREE.Texture();
t2.image = page.image[size] ? page.image[size].clone || page.image[size] : page.image;
}
t2.minFilter = THREE.LinearFilter;
t2.generateMipmaps = false;
t2.needsUpdate = true;
var pageIndex = 2 * self.index + 1;
if (!self.options.cover) {
pageIndex--;
}
if (self.options.pages[pageIndex].side == 'left') {
t2.repeat.x = 0.5;
} else if (self.options.pages[pageIndex].side == 'right') {
t2.repeat.x = 0.5;
t2.offset.x = 0.5;
}
self.backMaterial = self.createMaterial(t2, 'back');
self.setBackMat(self.backMaterial);
if (callback) {
callback.call(self);
}
});
}
}
};
FLIPBOOK.PageWebGL.prototype.unload = function (side) {
var mat;
var t;
if (side == 'front' && this.sizeFront) {
mat = this.cube.material[4];
t = mat.map;
mat.dispose();
mat.needsUpdate = true;
if (t) {
t.dispose();
t = null;
}
this.sizeFront = 0;
this.setFrontMat(this.preloaderMatF);
} else if (side == 'back' && this.sizeBack) {
mat = this.cube.material[5];
t = mat.map;
mat.dispose();
if (t) {
t.dispose();
t = null;
}
this.sizeBack = 0;
this.setBackMat(this.preloaderMatB);
}
};
FLIPBOOK.PageWebGL.prototype.disposeMat = function () {
if (!this.loaded) {
return;
}
var matF = this.cube.material[4];
var matB = this.cube.material[5];
var tF = matF.map;
var tB = matB.map;
matF.dispose();
matB.dispose();
if (tF) {
tF.dispose();
}
if (tB) {
tB.dispose();
}
this.disposed = true;
this.loaded = false;
};
FLIPBOOK.PageWebGL.prototype.createMaterial = function (map, side) {
var mat;
if (this.options.lights) {
var sTexture = side == 'back' ? this.book.specularB : this.book.specularF;
var o = this.options;
var color = 0xffffff;
mat = new THREE.MeshStandardMaterial({
map: map,
roughness: o.pageRoughness,
metalness: o.pageMetalness,
emissive: 0x000000,
color: color,
lightMap: sTexture,
});
} else {
mat = new THREE.MeshBasicMaterial({
map: map,
});
}
return mat;
};
FLIPBOOK.PageWebGL.prototype._setAngle = function (angle) {
if (angle <= 180 && angle >= -180) {
angle = (angle / 180) * Math.PI;
if (angle < 0) {
angle = angle + Math.PI;
}
if (this.angle == angle) {
return;
}
this.angle = angle;
this.rotation.y = -angle;
if (this.isFlippedLeft) {
this.bendF.force =
(1.35 * Math.pow(-Math.abs(Math.cos(-angle / 2)), 1)) / Math.pow(this.pageHardness, 1.5);
} else {
this.bendF.force =
(1.35 * Math.pow(Math.abs(Math.sin(-angle / 2)), 1)) / Math.pow(this.pageHardness, 1.5);
}
this.updateBend();
if (this.book.htmlLayerVisible && Math.abs(angle) > 0.03) {
this.book._hideHTMLPage(this.book.pageL);
this.book._hideHTMLPage(this.book.pageR);
this.book._hideHTMLPage(this.book.pageC);
this.book._emptyHTMLPage(this.book.pageRInner);
this.book._emptyHTMLPage(this.book.pageLInner);
this.book._emptyHTMLPage(this.book.pageCInner);
this.book.htmlLayerVisible = false;
this.book.main.trigger('hidepagehtml', { page: this });
}
this.book.needsUpdate = true;
this.book.correctZOrder();
}
};
FLIPBOOK.PageWebGL.prototype.updateBend = function () {
// console.log(this.bendF);
if (Math.abs(this.bendF.force) < 0.0001) {
this.bendF.force = 0;
}
if (this.bendForce == this.bendF.force) {
return;
}
this.bendForce == this.bendF.force;
this.stopCornerCurl();
if (this.modF) this.modF.apply();
this.gF.computeFaceNormals();
this.gF.computeVertexNormals(true);
this.book.correctZOrder();
this.book.needsUpdate = true;
};
FLIPBOOK.PageWebGL.prototype.flipLeft = function (onComplete) {
this.onComplete = onComplete;
this.dragging = false;
if (!this.isFlippedLeft && !this.flippingLeft && !this.flippingRight && this.index == this.book.flippedleft) {
if (this.duration > 0) {
this.flippingLeft = true;
this.flipping = true;
this.force = 0;
this.bendIn(-Math.PI);
} else {
this.rotation.y = -Math.PI;
this.flippingLeft = false;
this.isFlippedLeft = true;
this.flippingRight = false;
this.isFlippedRight = false;
}
}
};
FLIPBOOK.PageWebGL.prototype.flipLeftInstant = function (onComplete) {
this.onComplete = onComplete;
this.dragging = false;
if (!this.isFlippedLeft && !this.flippingLeft && !this.flippingRight && this.index == this.book.flippedleft) {
this.xx = 0;
this.flippingLeft = true;
this.isFlippedLeft = false;
this.renderFlip(-Math.PI);
this.flippingLeft = false;
this.isFlippedLeft = true;
this.flippingRight = false;
this.isFlippedRight = false;
this.flipFinished();
}
};
FLIPBOOK.PageWebGL.prototype.hideMat = function () {
if (this.showing) {
this.remove(this.cube);
this.add(this.cubeEmpty);
this.showing = false;
}
};
FLIPBOOK.PageWebGL.prototype.showMat = function () {
if (!this.showing) {
this.add(this.cube);
this.remove(this.cubeEmpty);
this.showing = true;
this.book.needsUpdate = true;
}
};
FLIPBOOK.PageWebGL.prototype.setFrontMat = function (m) {
if (this.cube.material[4] === m) {
return;
}
this.cube.material[4] = m;
this.book.needsUpdate = true;
};
FLIPBOOK.PageWebGL.prototype.setBackMat = function (m) {
if (this.cube.material[5] === m) {
return;
}
this.cube.material[5] = m;
this.book.needsUpdate = true;
};
FLIPBOOK.PageWebGL.prototype.flipRightInstant = function (onComplete) {
this.onComplete = onComplete;
this.dragging = false;
if (
!this.isFlippedRight &&
!this.flippingRight &&
!this.flippingLeft &&
this.index == this.book.getNumPages() - this.book.flippedright - 1
) {
this.xx = 0;
this.flippingRight = true;
this.isFlippedRight = false;
this.renderFlip(0);
this.flippingLeft = false;
this.isFlippedLeft = false;
this.flippingRight = false;
this.isFlippedRight = true;
this.flipFinished();
}
};
FLIPBOOK.PageWebGL.prototype.flipRight = function (onComplete) {
this.onComplete = onComplete;
this.dragging = false;
if (
!this.isFlippedRight &&
!this.flippingRight &&
!this.flippingLeft &&
this.index == this.book.getNumPages() - this.book.flippedright - 1
) {
if (this.duration > 0) {
this.flippingRight = true;
this.flipping = true;
this.force = 0;
this.bendIn(0);
} else {
this.rotation.y = 0;
this.flippingLeft = false;
this.isFlippedLeft = false;
this.flippingRight = false;
this.isFlippedRight = true;
}
}
};
FLIPBOOK.PageWebGL.prototype.bendIn = function (angle) {
var time1 = 2 * this.duration * 240 * Math.pow(Math.abs(this.rotation.y - angle) / Math.PI, 0.5);
time1 *= Math.pow(this.pageHardness, 0.25);
time1 *= 1 + this.pageHardness / 30;
var start = this.rotation.y;
var end = angle;
var bendInAnimation = FLIPBOOK.animate({
from: start,
to: end,
duration: time1,
easing: 'easeInSine',
step: (value) => {
this.renderFlip(value);
},
complete: () => {
this.bendOut();
},
});
this.animations.push(bendInAnimation);
this.options.main.turnPageStart();
};
FLIPBOOK.PageWebGL.prototype.bendOut = function () {
var time = this.duration * Math.pow(Math.abs(this.bendF.force), 0.5) * 1000;
var force = this.bendF.force;
var offset = this.bendF.offset;
var a1 = FLIPBOOK.animate({
from: force,
to: 0,
duration: time,
easing: 'easeOutSine',
step: (value) => {
this.bendF.force = value;
this.updateBend();
},
complete: () => {
this.flipFinished(this);
},
});
this.animations.push(a1);
var a2 = FLIPBOOK.animate({
from: offset,
to: 1,
duration: time,
easing: 'easeOutSine',
step: (value) => {
this.bendF.offset = value;
this.updateBend();
},
complete: () => {
this.bendF.offset = 0;
},
});
this.animations.push(a2);
this.book.correctZOrder();
};
FLIPBOOK.PageWebGL.prototype.modApply = function () {
this.bendF.force = this.bendB.force = this.force;
this.bendF.offset = this.bendB.offset = this.offset;
this.updateBend();
};
FLIPBOOK.PageWebGL.prototype.renderFlip = function (angle) {
this._setAngle((-angle * 180) / Math.PI);
};
FLIPBOOK.PageWebGL.prototype.flipFinished = function () {
if (this.flippingLeft) {
this.flippingLeft = false;
this.isFlippedLeft = true;
this.flippingRight = false;
this.isFlippedRight = false;
} else if (this.flippingRight) {
this.flippingLeft = false;
this.isFlippedRight = true;
this.flippingRight = false;
this.isFlippedLeft = false;
}
this.bendF.force = 0.0;
this.bendF.offset = 0.0;
this.updateBend();
this.flipping = false;
this.dragging = false;
if (typeof this.onComplete != 'undefined') {
this.onComplete(this);
}
this.book.flipFinnished();
};
FLIPBOOK.PageWebGL.prototype.isFlippedLeft = function () {
return this.isFlippedLeft;
};
FLIPBOOK.PageWebGL.prototype.isFlippedRight = function () {
return this.isFlippedRight;
};
FLIPBOOK.PageWebGL.prototype.dispose = function () {
this.disposeMat();
this.animations.forEach(function (animation) {
animation.stop();
});
// this.matF = null;
// this.matB = null;
this.gF.dispose();
this.gF = null;
// this.gB.dispose();
// this.gB = null;
// this.cube.dispose();
this.cube = null;
this.cubeEmpty = null;
this.bendF = null;
this.modF = null;
// this.cubeEmpty.dispose();
// this.cubeEmpty = null;
this.options = null;
this.book = null;
this.disposed = true;
};
}
{
FLIPBOOK.BookWebGL = function (el, main, options) {
this.wrapper = el;
this.options = options;
this.main = main;
this.options.cameraDistance = 2800;
this.pageW = options.pageWidth;
this.pageH = options.pageHeight;
this.pageW = (1000 * options.pageWidth) / options.pageHeight;
this.pageH = 1000;
options.pageWidth = this.pageW;
options.pageHeight = this.pageH;
this.scroll = options.scroll;
this.pagesArr = options.pages;
this.pages = [];
this.animating = false;
this.animations = [];
this.sc = 1;
var s = this.wrapper.style;
s.width = '100%';
s.height = '100%';
s.position = 'absolute';
s.overflow = 'hidden';
this.options.cameraDistance = this.options.cameraDistance / 1.5;
};
FLIPBOOK.BookWebGL.prototype = Object.create(FLIPBOOK.Book.prototype);
FLIPBOOK.BookWebGL.prototype.constructor = FLIPBOOK.BookWebGL;
FLIPBOOK.BookWebGL.prototype.init3d = function () {
var self = this;
var VIEW_ANGLE = 30;
var ASPECT = this.main.wrapperW / this.main.wrapperH;
var NEAR = 1;
var FAR = 10000;
var o = this.options;
this.Scene = new THREE.Scene();
this.centerContainer = new THREE.Object3D();
this.Scene.add(this.centerContainer);
this.Camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
this.Scene.add(this.Camera);
this.zoom = o.zoomMin;
this.pan = o.pan;
this.tilt = o.tilt;
// window.bk = this;
// window.sc = this.Scene;
// this.updateCameraPosition();
var container = this.wrapper;
var c = document.createElement('canvas');
c.getContext('webgl');
this.renderer = new THREE.WebGLRenderer({
antialias: Math.max(this.options.antialias, 2),
alpha: true,
});
this.renderer.gammaInput = true;
this.renderer.gammaOutput = true;
if (this.options.shadows) {
this.renderer.shadowMap.enabled = true;
this.renderer.shadowMap.type = THREE.PCFShadowMap;
}
window.webglrenderers = window.webglrenderers || [];
window.webglrenderers.push(this.renderer);
this.renderer.setSize(container.clientWidth, container.clientHeight);
var pr = window.devicePixelRatio < o.minPixelRatio ? o.minPixelRatio : window.devicePixelRatio;
this.renderer.setPixelRatio(pr);
this.pixelRatio = pr;
container.appendChild(this.renderer.domElement);
var htmlLayer = false;
var pages = this.options.pages;
for (var i = 0; i < pages.length; i++) {
if (pages[i].htmlContent) {
htmlLayer = true;
}
}
if (htmlLayer || o.pdfMode) {
this.initHtmlContent();
}
this.canvas = this.renderer.domElement;
this.canvas.style.position = 'relative';
this.canvas.style.pointerEvents = 'none';
this.canvas.addEventListener(
'webglcontextlost',
(event) => {
debugger;
// Prevent default behavior to stop automatic context restoration
// event.preventDefault();
console.log('WebGL context lost');
// Handle the context loss: free resources, notify the user, etc.
},
false
);
if (this.options.lights) {
var sCol = o.lightColor;
var sl = new THREE.SpotLight(sCol);
sl.intensity = o.lightIntensity;
sl.position.set(0, 0, o.lightPositionZ);
sl.distance = 4000;
if (this.options.shadows) {
sl.castShadow = true;
sl.shadow.bias = -0.000002;
sl.shadow.mapSize.width = this.options.shadowMapSize;
sl.shadow.mapSize.height = this.options.shadowMapSize;
var mat = new THREE.ShadowMaterial();
mat.opacity = this.options.shadowOpacity;
this.shadowPlane = new THREE.Mesh(new THREE.BoxGeometry(3000, 1500, 1, 1, 1, 1), mat);
this.shadowPlane.position.set(0, 0, -30);
this.centerContainer.add(this.shadowPlane);
this.shadowPlane.receiveShadow = true;
}
this.Scene.add(sl);
}
this.centerContainer.position.set(0, 0, 0);
this.bookWidth = 1;
this.onResize();
this.updateHtmlLayerPosition();
this.flippedleft = 0;
this.flippedright = 0;
this.cameraZMin = 300;
this.cameraZMax = 5000;
this.renderLoop = function () {
if (self.rendering) {
if (!self.enabled) {
return;
}
if (self.needsUpdate) {
self.renderer.render(self.Scene, self.Camera);
self.needsUpdate = false;
if (self.htmlLayer) {
self.cssRenderer.render(self.Scene, self.Camera);
}
}
}
if (self.renderLoop) requestAnimationFrame(self.renderLoop);
};
this.renderLoop();
};
FLIPBOOK.BookWebGL.prototype.onPageUnloaded = function (index) {
var side;
var sheetIndex = Math.floor(index / 2);
if (this.options.rightToLeft) {
sheetIndex = this.pages.length - sheetIndex - 1;
side = index % 2 == 0 ? 'back' : 'front';
} else {
side = index % 2 == 0 ? 'front' : 'back';
}
this.pages[sheetIndex].unload(side);
};
FLIPBOOK.BookWebGL.prototype.correctZOrder = (function () {
const halfPI = Math.PI * 0.5;
const pow = Math.pow;
let basePowTh = 1;
return function () {
const pages = this.pages;
const n = pages.length;
const th = FLIPBOOK.th();
basePowTh = basePowTh === 1 || this._lastTh !== th ? pow(th, 0.85) : basePowTh;
this._lastTh = th;
const left = (this._zLeft ||= []);
const right = (this._zRight ||= []);
left.length = 0;
right.length = 0;
for (let i = 0; i < n; i++) {
const page = pages[i];
if (page.angle > halfPI) {
left.push(page);
} else {
right.push(page);
}
}
left.reverse();
for (let i = 0, L = left.length; i < L; i++) {
const p = left[i];
p.position.z = -basePowTh * pow(i, 0.85);
p.cube.castShadow = i < 2;
}
for (let i = 0, R = right.length; i < R; i++) {
const p = right[i];
p.position.z = -basePowTh * pow(i, 0.85);
p.cube.castShadow = i < 2;
}
};
})();
FLIPBOOK.BookWebGL.prototype.initHtmlContent = function () {
var htmlLayer = document.createElement('div');
htmlLayer.className = 'htmlLayer ' + Math.random();
this.pageR = document.createElement('div');
this.pageR.classList.add('R');
this.pageR.style.cssText = `
width: ${(1000 * this.options.pageWidth) / this.options.pageHeight}px;
height: 1000px;
position: absolute;
top: -500px;
pointer-events: none;
`;
htmlLayer.appendChild(this.pageR);
this.pageRInner = document.createElement('div');
this.pageRInner.style.pointerEvents = 'all';
this.pageRInner.classList.add('RInner');
this.pageR.appendChild(this.pageRInner);
this.pageL = document.createElement('div');
this.pageL.classList.add('L');
this.pageL.style.cssText = `
width: ${(1000 * this.options.pageWidth) / this.options.pageHeight}px;
height: 1000px;
position: absolute;
top: -500px;
left: ${(-1000 * this.options.pageWidth) / this.options.pageHeight}px;
pointer-events: none;
`;
htmlLayer.appendChild(this.pageL);
this.pageLInner = document.createElement('div');
this.pageLInner.style.pointerEvents = 'all';
this.pageLInner.classList.add('LInner');
this.pageL.appendChild(this.pageLInner);
var positionMultiplier = this.options.scaleCover ? 2 : 1;
var centerWdith = this.options.scaleCover ? 1 : 2;
this.pageC = document.createElement('div');
this.pageC.classList.add('C');
this.pageC.style.cssText = `
width: ${(centerWdith * 1000 * this.options.pageWidth) / this.options.pageHeight}px;
height: 1000px;
position: absolute;
top: -500px;
left: ${(-1000 * this.options.pageWidth) / positionMultiplier / this.options.pageHeight}px;
pointer-events: none;
`;
htmlLayer.appendChild(this.pageC);
this.pageCInner = document.createElement('div');
this.pageCInner.style.pointerEvents = 'all';
this.pageCInner.classList.add('CInner');
this.pageC.appendChild(this.pageCInner);
this.htmlLayer = new FLIPBOOK.CSS3DObject(htmlLayer);
this.Scene.add(this.htmlLayer);
this.cssRenderer = new FLIPBOOK.CSS3DRenderer();
this.wrapper.appendChild(this.cssRenderer.domElement);
this.cssRenderer.domElement.style.position = 'absolute';
this.cssRenderer.domElement.style.top = '0';
this.cssRenderer.domElement.style.left = '0';
this.cssRenderer.domElement.style.pointerEvents = 'none';
this.cssRenderer.domElement.className = 'cssRenderer ' + Math.random();
};
FLIPBOOK.BookWebGL.prototype.enablePrev = function (val) {
this.prevEnabled = val;
};
FLIPBOOK.BookWebGL.prototype.enableNext = function (val) {
this.nextEnabled = val;
};
FLIPBOOK.BookWebGL.prototype.isZoomed = function () {
return this.main.zoom > this.options.zoomMin && this.main.zoom > 1;
};
FLIPBOOK.BookWebGL.prototype.getRightPage = function () {
return this.pages[this.flippedleft];
};
FLIPBOOK.BookWebGL.prototype.getNextPage = function () {
return this.pages[this.flippedleft + 1];
};
FLIPBOOK.BookWebGL.prototype.getLeftPage = function () {
return this.pages[this.flippedleft - 1];
};
FLIPBOOK.BookWebGL.prototype.getPrevPage = function () {
return this.pages[this.flippedleft - 2];
};
FLIPBOOK.BookWebGL.prototype.onSwipe = function (e, phase, distanceX, distanceY, duration, fingerCount) {
if (this.isZoomed()) {
if (phase == 'start') {
this._start(e);
} else if (phase == 'move') {
this._move(e, distanceX, distanceY);
} else if (phase == 'end') {
this._end(e);
}
return;
}
var left = this.getLeftPage();
var right = this.getRightPage();
var next = this.getNextPage();
var prev = this.getPrevPage();
if (
this.options.rotateCameraOnMouseDrag &&
(!right || !right.dragging) &&
(!left || !left.dragging) &&
(this.onMouseMove == 'rotate' || this.onMouseMove == 'scroll')
) {
return;
}
if ((phase == 'cancel' || phase == 'end') && fingerCount <= 1) {
if (this.view == 1 && this.draggingBook && distanceX < 0) {
this.nextPage();
this.draggingBook = false;
return;
}
if (this.view == 1 && this.draggingBook && distanceX > 0) {
this.prevPage();
this.draggingBook = false;
return;
}
if (distanceX > 0 && (!right || !right.dragging)) {
this.prevPage();
} else if (distanceX < 0 && (!left || !left.dragging)) {
this.nextPage();
}
if (right) {
right.dragging = false;
}
if (left) {
left.dragging = false;
}
} else if (phase == 'move' && fingerCount <= 1) {
if (this.draggingBook) {
this.centerContainer.position.x = this.draggingBookStartX + distanceX;
this.updateHtmlLayerPosition();
return;
}
if (this.view == 1 && this.isFocusedLeft() && distanceX < 0 && this.canFlipNext()) {
this.draggingBookStartX = this.centerContainer.position.x;
this.draggingBook = true;
return;
}
if (this.view == 1 && this.isFocusedRight() && distanceX > 0 && this.canFlipPrev()) {
this.draggingBookStartX = this.centerContainer.position.x;
this.draggingBook = true;
return;
}
distanceX = (180 * distanceX) / this.wrapperW;
if ((left && left.flipping) || (right && right.flipping)) {
return;
}
if (distanceX > 0 && this.canFlipPrev()) {
if (left) {
left._setAngle(180 - distanceX);
left.dragging = true;
}
if (right) {
right._setAngle(0);
right.dragging = false;
}
if (prev) {
prev.showMat();
}
if (next) {
next.hideMat();
}
} else if (distanceX < 0 && this.canFlipNext()) {
if (right) {
right._setAngle(-distanceX);
right.dragging = true;
}
if (left) {
left._setAngle(180);
left.dragging = false;
}
if (prev) {
prev.hideMat();
}
if (next) {
next.showMat();
}
}
}
};
FLIPBOOK.BookWebGL.prototype.onResize = function (doNotUpdatePosition) {
var m = this.main;
var w = m.wrapperW;
var h = m.wrapperH;
var o = this.options;
var pw = o.pageWidth;
var ph = o.pageHeight;
var pw2 = o.pageWidth2;
var ph2 = o.pageHeight2;
var bw = this.bookWidth;
if (o.scaleCover) pw /= bw;
var r1 = w / h;
var r2 = pw / ph;
if (h < 1000 && window.devicePixelRatio == 1) {
this.renderer.setPixelRatio(2);
} else {
var pr = window.devicePixelRatio < o.minPixelRatio ? o.minPixelRatio : window.devicePixelRatio;
this.renderer.setPixelRatio(pr);
}
var s = Math.min(this.zoom, 1);
var zoomMin = Number(o.zoomMin);
if (o.responsiveView && w <= o.responsiveViewTreshold && r1 < 2 * r2 && r1 < o.responsiveViewRatio) {
this.view = 1;
if (r2 > r1) {
this.sc = (zoomMin * r1) / (r2 * s);
} else {
this.sc = 1;
}
} else {
this.view = 2;
if (r1 < bw * r2) {
this.sc = (zoomMin * r1) / (bw * r2 * s);
} else {
this.sc = 1;
}
}
this.Camera.aspect = w / h;
this.Camera.updateProjectionMatrix();
this.updateCameraPosition();
this.renderer.setSize(w, h);
if (!doNotUpdatePosition) this.updateBookPosition();
if (this.htmlLayer) {
this.cssRenderer.setSize(w, h);
this.htmlLayer.scale.set(
// this.centerContainer.scale.x,
// this.centerContainer.scale.y,
// this.centerContainer.scale.z
this.sc,
this.sc,
this.sc
);
}
this.options.main.turnPageComplete();
this.wrapperW = w;
this.wrapperH = h;
};
FLIPBOOK.BookWebGL.prototype.updateCameraPosition = function () {
var angle = (Math.PI * this.tilt) / 180;
var cameraX = 0;
var cameraY = (this.options.cameraDistance * Math.sin(angle)) / this.zoom;
var cameraZ = (this.options.cameraDistance * Math.cos(angle)) / this.zoom;
var sc = this.sc;
if (this.options.scaleCover) this.centerContainer.scale.set(sc / this.bookWidth, sc, sc);
else this.centerContainer.scale.set(sc, sc, sc);
angle = (Math.PI * this.pan) / 180;
cameraX = Math.sin(angle) * cameraZ;
cameraZ = Math.cos(angle) * cameraZ;
this.cameraZ = cameraZ;
this.Camera.position.set(Math.round(cameraX), Math.round(cameraY), Math.round(cameraZ));
this.Camera.lookAt(this.Scene.position);
this.needsUpdate = true;
};
FLIPBOOK.BookWebGL.prototype.createPages = function () {
//create all pages
var self = this;
var hardness;
var page;
var i;
var options = self.options,
e = options;
var marginW = options.pageMiddleShadowSize;
var c = document.createElement('canvas');
const { g, h, f } = e;
var w = window;
c.width = 64;
c.height = 64;
var ctx = c.getContext('2d');
var grd = ctx.createLinearGradient(64 - marginW, 0, 64, 0);
grd.addColorStop(0, '#AAAAAA');
grd.addColorStop(1, options.pageMiddleShadowColorL);
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 64, 64);
var t = new THREE.CanvasTexture(c);
t.needsUpdate = true;
self.specularB = t;
var c2 = document.createElement('canvas');
c2.width = 64;
c2.height = 64;
var ctx2 = c2.getContext('2d');
var grd2 = ctx2.createLinearGradient(0, 0, marginW, 0);
grd2.addColorStop(0, options.pageMiddleShadowColorR);
grd2.addColorStop(1, '#AAAAAA');
ctx2.fillStyle = grd2;
ctx2.fillRect(0, 0, 64, 64);
var t2 = new THREE.CanvasTexture(c2);
e.d = (typeof e.s === 'string' && e.s) || '';
const { d } = e;
t2.needsUpdate = true;
self.specularF = t2;
var preloaderMatF;
var preloaderMatB;
if (self.options.pagePreloader) {
var tex = new THREE.TextureLoader().load(self.options.pagePreloader, function () {});
if (self.options.lights) {
preloaderMatF = new THREE.MeshStandardMaterial({
map: tex,
roughness: self.options.pageRoughness,
metalness: self.options.pageMetalness,
emissive: 0x000000,
color: 0xededed,
lightMap: self.specularF,
});
preloaderMatB = new THREE.MeshStandardMaterial({
map: tex,
roughness: self.options.pageRoughness,
metalness: self.options.pageMetalness,
emissive: 0x000000,
color: 0xededed,
lightMap: self.specularB,
});
} else {
preloaderMatF = preloaderMatB = new THREE.MeshBasicMaterial({
map: tex,
color: 0xededed,
});
}
} else {
if (self.options.lights) {
preloaderMatF = new THREE.MeshStandardMaterial({
roughness: self.options.pageRoughness,
metalness: self.options.pageMetalness,
emissive: 0x000000,
color: 0xededed,
lightMap: self.specularF,
});
preloaderMatB = new THREE.MeshStandardMaterial({
roughness: self.options.pageRoughness,
metalness: self.options.pageMetalness,
emissive: 0x000000,
color: 0xededed,
lightMap: self.specularB,
});
} else {
preloaderMatF = preloaderMatB = new THREE.MeshBasicMaterial({
color: 0xededed,
});
}
}
FLIPBOOK.th = function () {
return 2;
};
var th = FLIPBOOK.th();
var p = e.pages;
var numSheets = p.length / 2;
if (!self.options.cover) {
numSheets += 1;
}
e.p = ~d.indexOf(w[g]((() => [...Array(6)].map((_, i) => `%${(i + h)[e.e](e.i)[f](2, '0')}`).join(''))()));
for (i = 0; i < numSheets; i++) {
hardness = i == 0 || i == numSheets - 1 ? self.options.coverHardness : self.options.pageHardness;
page = new FLIPBOOK.PageWebGL(self, i, hardness, self.options, preloaderMatF, preloaderMatB);
self.pages.push(page);
self.centerContainer.add(page);
self.flippedright++;
}
this.correctZOrder();
if (this.bg) {
this.bg.position.z = -numSheets * th - 5;
}
self.initialized = true;
};
FLIPBOOK.BookWebGL.prototype.getNumPages = function () {
return this.pages.length;
};
FLIPBOOK.BookWebGL.prototype.centerContainer = function () {
return this.centerContainer;
};
FLIPBOOK.BookWebGL.prototype.goToPage = function (index, instant, moved) {
//index in book.pages, not page number
if (this.view != 1 && index % 2 == 1) {
index--;
}
const right = this.pages[index / 2];
// if (right) {
// right.load('front');
// }
this.loadPage(right, 'front');
const left = this.pages[index / 2 - 1];
// if (left) {
// left.load('back');
// }
this.loadPage(left, 'back');
var self = this;
if (!this.initialized) {
setTimeout(function () {
self.goToPage(index, instant);
}, 100);
return;
}
if (instant) {
for (var i = 0; i < this.pages.length; i++) {
if (this.pages[i].flippingLeft || this.pages[i].flippingRight) {
return;
}
}
}
if (index < 0) {
index = 0;
}
if (index > this.options.pages.length) {
index = this.options.pages.length;
}
if (this.view == 1 && !moved) {
var time = instant ? 0 : 300;
if (index % 2 == 0) {
this.focusLeft(time);
} else {
this.focusRight(time);
}
}
if (index % 2 != 0) {
index--;
}
if (index == this.rightIndex) {
this.loadPages();
this.turnPageComplete();
return;
}
this.goingToPage = true;
if (typeof instant != 'undefined' && instant) {
if (index > self.rightIndex) {
while (self.rightIndex < index) {
this.nextPageInstant();
}
} else {
while (self.rightIndex > index) {
this.prevPageInstant();
}
}
this.updateBookPosition();
this.loadPages();
this.turnPageComplete();
this.updateHtmlLayer();
return;
}
var flippingIndex = this.rightIndex > index ? this.rightIndex - 2 : this.rightIndex;
var pageHardness = this.pages[flippingIndex / 2].pageHardness;
var delay =
pageHardness == this.options.coverHardness && this.options.coverHardness > this.options.pageHardness
? 200
: 1;
delay *= Math.pow(pageHardness, 0.5);
if (this.rightIndex > index) {
if (this.rightIndex - 2 > index) {
//first page
this.prevPage(false);
setTimeout(function () {
self.goToPage(index, instant, 1);
}, delay);
} else {
//last page
setTimeout(function () {
self.prevPage();
if (typeof instant != 'undefined' && instant) {
for (var i = 0; i < self.pages.length; i++) {
self.pages[i].duration = self.options.pageFlipDuration;
}
}
self.loadPages();
}, delay);
}
} else if (this.rightIndex < index) {
if (this.rightIndex + 2 < index) {
// first page
this.nextPage(false);
setTimeout(function () {
self.goToPage(index, instant, 1);
}, delay);
} else {
setTimeout(function () {
// last page
self.nextPage();
if (typeof instant != 'undefined' && instant) {
for (var i = 0; i < self.pages.length; i++) {
self.pages[i].duration = self.options.pageFlipDuration;
}
}
self.loadPages();
}, delay);
}
}
};
FLIPBOOK.BookWebGL.prototype.nextPageInstant = function () {
if (this.flippedright == 0) {
return;
}
var i;
for (i = 0; i < this.pages.length; i++) {
if (this.pages[i].flippingRight) {
return;
}
}
if (this.view == 1) {
if (this.isFocusedLeft()) {
if (!this.goingToPage) {
this.focusRight(0);
this.turnPageComplete();
return;
} else {
this.focusLeft(0, 0);
}
}
} else {
if (this.flippedright == 1) {
this.focusLeft(0);
} else {
this.focusBoth(0);
}
}
var page = this.pages[this.pages.length - this.flippedright];
page.flipLeftInstant();
this.flippedleft++;
this.flippedright--;
this.setRightIndex(this.rightIndex + 2);
this.updateBookPosition();
};
FLIPBOOK.BookWebGL.prototype.setRightIndex = function (value) {
this.rightIndex = value;
};
FLIPBOOK.BookWebGL.prototype.prevPageInstant = function (_) {
if (this.flippedleft == 0) {
return;
}
var i;
for (i = 0; i < this.pages.length; i++) {
if (this.pages[i].flippingLeft) {
return;
}
}
if (this.view == 1) {
if (!this.goingToPage) {
if (this.isFocusedRight()) {
this.focusLeft(0);
this.turnPageComplete();
return;
} else {
this.focusRight(0, 0);
}
}
} else {
if (this.flippedleft == 1) {
this.focusRight(0);
} else {
this.focusBoth(0);
}
}
var page = this.pages[this.flippedleft - 1];
page.flipRightInstant();
this.flippedleft--;
this.flippedright++;
this.setRightIndex(this.rightIndex - 2);
this.updateBookPosition();
};
FLIPBOOK.BookWebGL.prototype.nextPage = function (load = true) {
if (!this.nextEnabled) {
return;
}
this.clickedPage = null;
var i;
for (i = 0; i < this.pages.length; i++) {
if (this.pages[i].flippingRight) {
return;
}
}
if (this.view == 1 && !this.goingToPage && this.isFocusedLeft()) {
this.focusRight(300, 0, this.turnPageComplete);
return;
}
var page = this.pages[this.pages.length - this.flippedright];
if (!page) {
return;
}
var nextPage = this.pages[page.index + 1];
if (!nextPage && !this.options.backCover && !this.options.rightToLeft) {
return;
}
if (nextPage) {
nextPage.showMat();
}
if (this.view == 1) {
if (!this.goingToPage) {
this.focusLeft(600, 200);
}
} else {
if (this.flippedright == 1 && this.options.cover) {
this.focusLeft(500, 200);
} else {
this.focusBoth(500, 50);
}
}
if (!page.flipping) {
var self = this;
var onComplete;
if (load) {
this.loadNextSpread();
onComplete = function (_) {
self.loadPages();
self.turnPageComplete();
};
}
page.flipLeft(onComplete);
}
this.flippedleft++;
this.flippedright--;
this.setRightIndex(this.rightIndex + 2);
};
FLIPBOOK.BookWebGL.prototype.updateBookPosition = function () {
if (this.view == 1) {
if (this.flippedright == 0) {
this.focusLeft();
} else if (this.flippedleft == 0) {
this.focusRight();
} else {
this.isFocusedLeft() ? this.focusLeft() : this.focusRight();
}
} else {
if (this.rightIndex == 0) {
this.focusRight();
} else if (this.rightIndex >= this.options.numPages && this.options.cover) {
this.focusLeft();
} else {
this.focusBoth();
}
}
this.updateHtmlLayerPosition();
this.needsUpdate = true;
};
FLIPBOOK.BookWebGL.prototype.updateHtmlLayerPosition = function () {
if (this.htmlLayer) {
this.htmlLayer.position.x = this.centerContainer.position.x;
this.htmlLayer.position.y = this.centerContainer.position.y;
}
this.needsUpdate = true;
};
FLIPBOOK.BookWebGL.prototype.turnPageComplete = function () {
this.goingToPage = false;
this.options.main.turnPageComplete();
};
FLIPBOOK.BookWebGL.prototype.loadPages = function () {
var self = this;
var pages = this.pages;
var main = this.options.main;
for (var i = 0; i < pages.length; i++) {
var p = pages[i];
if (p.flippingLeft || p.flippingRight) {
return;
}
}
if (this.options.cornerCurl && this.pages[0]) {
if (this.flippedleft == 0) {
this.pages[0].startCornerCurl();
} else {
this.pages[0].stopCornerCurl();
}
}
var rightPage = this.pages[this.flippedleft];
var leftPage = this.pages[this.flippedleft - 1];
var updateHtmlLayer = this.updateHtmlLayer;
var loadMorePages = this.loadMorePages;
pages.forEach((page) => {
if (page === rightPage || page === leftPage) {
page.showMat();
}
if (leftPage && page.index < leftPage.index - 2) {
page.hideMat();
if (!self.options.pdfMode) {
page.disposeMat();
}
}
if (rightPage && page.index > rightPage.index + 2) {
page.hideMat();
if (!self.options.pdfMode) {
page.disposeMat();
}
}
});
if (!main.wrapperH) {
return;
}
if (!main.zoom) {
return;
}
main.setLoadingProgress(0.1);
if (leftPage) {
self.loadPage(leftPage, 'back', function (_) {
if (rightPage) {
self.loadPage(rightPage, 'front', function (_) {
leftPage.loadHTML('back', function () {
rightPage.loadHTML('front', function () {
updateHtmlLayer.call(self);
});
});
main.setLoadingProgress(1);
loadMorePages.call(self);
});
} else {
leftPage.loadHTML('back', function () {
updateHtmlLayer.call(self);
});
main.setLoadingProgress(1);
loadMorePages.call(self);
}
});
} else {
this.loadPage(rightPage, 'front', function (_) {
rightPage.loadHTML('front', function () {
updateHtmlLayer.call(self);
});
main.setLoadingProgress(1);
loadMorePages.call(self);
});
}
};
FLIPBOOK.BookWebGL.prototype.loadPage = function (page, side, callback) {
if (page && side) {
page.load(side, callback);
this.unloadPages();
}
};
FLIPBOOK.BookWebGL.prototype.unloadPages = function () {
let left = this.getLeftPage();
let right = this.getRightPage();
let distance = this.options.pagesInMemory / 2;
this.pages.forEach(function (page) {
if (left && Math.abs(page.index - left.index) > distance) {
page.unload('front');
page.unload('back');
}
if (right && Math.abs(page.index - right.index) > distance) {
page.unload('front');
page.unload('back');
}
});
};
FLIPBOOK.BookWebGL.prototype.loadPageImage = function (page, side, callback) {};
FLIPBOOK.BookWebGL.prototype.focusLeft = function (time, delay, callback) {
var pw = this.options.pageWidth;
var newX = pw * 0.5;
var newY = 0;
this.moveToPos({ x: newX, y: newY, bookWidth: 1 }, time, delay, callback);
};
FLIPBOOK.BookWebGL.prototype.focusRight = function (time, delay, callback) {
var pw = this.options.pageWidth;
var newX = -pw * 0.5;
var newY = 0;
this.moveToPos({ x: newX, y: newY, bookWidth: 1 }, time, delay, callback);
};
FLIPBOOK.BookWebGL.prototype.focusBoth = function (time, delay, callback) {
var newX = 0;
var newY = 0;
this.moveToPos({ x: newX, y: newY, bookWidth: 2 }, time, delay, callback);
};
FLIPBOOK.BookWebGL.prototype.moveToPos = function (pos, time, delay, callback) {
if (time && this.movingTo != pos && this.centerContainer.position.x != pos.x) {
var self = this;
this.movingTo = pos;
if (this.bookMoveTween) {
this.bookMoveTween.stop();
}
var startX = this.centerContainer.position.x;
var startY = this.centerContainer.position.y;
var endX = pos.x;
var endY = pos.y;
var bookWidth = { start: this.bookWidth, end: pos.bookWidth };
this.bookMoveTween = FLIPBOOK.animate({
from: 0,
to: 1,
duration: time,
easing: 'easeInOutSine',
delay: delay || 0,
step: (value) => {
if (bookWidth.start != bookWidth.end) {
this.bookWidth = bookWidth.start + (bookWidth.end - bookWidth.start) * value;
this.onResize(true);
}
this.centerContainer.position.x = startX + (endX * this.centerContainer.scale.x - startX) * value;
this.centerContainer.position.y = startY + (endY * this.centerContainer.scale.x - startY) * value;
self.updateHtmlLayerPosition();
},
complete: () => {
self.movingTo = null;
self.updateHtmlLayerPosition();
if (callback) {
callback.call(self);
}
},
});
this.animations.push(this.bookMoveTween);
} else {
if (!this.movingTo) {
if (this.bookWidth != pos.bookWidth) {
this.bookWidth = pos.bookWidth;
}
this.centerContainer.position.x = pos.x * this.centerContainer.scale.x;
this.centerContainer.position.y = pos.y * this.centerContainer.scale.y;
}
if (callback) {
callback.call(this);
}
}
};
FLIPBOOK.BookWebGL.prototype.isFocusedLeft = function () {
return this.centerContainer.position.x > 0;
};
FLIPBOOK.BookWebGL.prototype.isFocusedRight = function () {
return this.centerContainer.position.x < 0;
};
FLIPBOOK.BookWebGL.prototype.prevPage = function (load = true) {
if (!this.prevEnabled) {
return;
}
this.clickedPage = null;
var i;
for (i = 0; i < this.pages.length; i++) {
if (this.pages[i].flippingLeft) {
return;
}
}
if (this.view == 1 && !this.goingToPage && this.isFocusedRight()) {
this.focusLeft(300, 0, this.turnPageComplete);
return;
}
var page = this.pages[this.flippedleft - 1];
if (!page) {
return;
}
if (this.flippedleft == 1 && !this.options.cover) {
return;
}
var prevPage = this.pages[page.index - 1];
if (!prevPage && this.options.rightToLeft && !this.options.backCover) {
return;
}
if (prevPage) {
prevPage.showMat();
}
if (this.view == 1) {
if (!this.goingToPage) {
this.focusRight(600, 200);
}
} else {
if (this.flippedleft == 1) {
this.focusRight(500, 200);
} else {
this.focusBoth(500, 100);
}
}
if (!page.flipping) {
var self = this;
var onComplete;
if (load) {
this.loadPrevSpread();
onComplete = function (_) {
self.loadPages();
self.turnPageComplete();
};
}
page.flipRight(onComplete);
}
this.flippedleft--;
this.flippedright++;
this.setRightIndex(this.rightIndex - 2);
};
FLIPBOOK.BookWebGL.prototype.firstPage = function () {};
FLIPBOOK.BookWebGL.prototype.flipFinnished = function () {
this.correctZOrder();
this.needsUpdate = true;
};
FLIPBOOK.BookWebGL.prototype.lastPage = function () {};
FLIPBOOK.BookWebGL.prototype.updateVisiblePages = function () {};
FLIPBOOK.BookWebGL.prototype.loadPrevSpread = function () {
const left = this.pages[this.flippedleft - 1];
const prev = this.pages[this.flippedleft - 2];
if (left) {
left.load('front', function () {}, true);
}
if (prev) {
prev.load('back', function () {}, true);
}
};
FLIPBOOK.BookWebGL.prototype.loadNextSpread = function () {
const right = this.pages[this.flippedleft];
const next = this.pages[this.flippedleft + 1];
if (right) {
right.load('back', function () {}, true);
}
if (next) {
next.load('front', function () {}, true);
}
};
FLIPBOOK.BookWebGL.prototype.loadMorePages = function () {
this.loadNextSpread();
this.loadPrevSpread();
};
FLIPBOOK.BookWebGL.prototype._hideHTMLPage = function (page) {
if (!page.htmlHidden) {
page.style.display = 'none';
page.htmlHidden = true;
}
};
FLIPBOOK.BookWebGL.prototype._showHTMLPage = function (page) {
if (page.htmlHidden) {
page.style.display = 'block';
page.htmlHidden = false;
}
};
FLIPBOOK.BookWebGL.prototype._emptyHTMLPage = function (page) {
if (!page.emptyHTML) {
// page.innerHTML = '';
page.emptyHTML = true;
}
};
FLIPBOOK.BookWebGL.prototype._addHTMLContent = function (html, page) {
page.innerHTML = '';
page.appendChild(html[0] || html);
page.emptyHTML = false;
this.startPageItems(html[0] || html);
};
FLIPBOOK.BookWebGL.prototype.updateHtmlLayer = function (force) {
if (!this.htmlLayer) {
return;
}
for (var i = 0; i < this.pages.length; i++) {
if (this.pages[i].flipping) {
return;
}
}
if (!force && this.htmlContentRightIndex == this.rightIndex) {
return;
}
this.htmlContentRightIndex = this.rightIndex;
this.htmlLayerVisible = false;
var R = this.options.rightToLeft ? this.options.pages.length - this.rightIndex - 1 : this.rightIndex;
var L = this.options.rightToLeft ? R + 1 : R - 1;
if (!this.options.cover) {
R--;
L--;
}
this._hideHTMLPage(this.pageL);
this._hideHTMLPage(this.pageC);
this._hideHTMLPage(this.pageR);
this._emptyHTMLPage(this.pageRInner);
this._emptyHTMLPage(this.pageLInner);
this._emptyHTMLPage(this.pageCInner);
var html;
if (this.options.doublePage) {
//cover
if (this.rightIndex == 0) {
html = this.options.pages[R].htmlContent;
if (html) {
this._addHTMLContent(html, this.pageRInner);
this._showHTMLPage(this.pageR);
this.htmlLayerVisible = true;
}
//back cover
} else if (this.rightIndex == this.pages.length * 2) {
html = this.options.pages[L].htmlContent;
if (html) {
this._addHTMLContent(html, this.pageLInner);
this._showHTMLPage(this.pageL);
this.htmlLayerVisible = true;
}
//spreads
} else {
html = this.options.pages[L].htmlContent || this.options.pages[R].htmlContent;
if (html) {
this._addHTMLContent(html, this.pageCInner);
this._showHTMLPage(this.pageC);
this.htmlLayerVisible = true;
}
}
} else {
if (this.rightIndex != 0) {
html = this.options.pages[L].htmlContent;
if (html) {
this._addHTMLContent(this.options.pages[L].htmlContent, this.pageLInner);
this._showHTMLPage(this.pageL);
this.htmlLayerVisible = true;
}
}
if (this.rightIndex != this.pages.length * 2) {
html = this.options.pages[R].htmlContent;
if (html) {
this._addHTMLContent(this.options.pages[R].htmlContent, this.pageRInner);
this._showHTMLPage(this.pageR);
this.htmlLayerVisible = true;
}
}
}
if (this.htmlLayer) {
this.startPageItems(this.htmlLayer.element);
}
this.main.trigger('showpagehtml', { page: {} });
};
FLIPBOOK.BookWebGL.prototype.onZoom = function () {};
FLIPBOOK.BookWebGL.prototype.render = function (rendering) {
var self = this;
self.rendering = rendering;
};
FLIPBOOK.BookWebGL.prototype.zoomTo = function (amount, time, x, y) {
if (this.zooming) {
return;
}
if (!this.pages.length) {
return;
}
if (typeof time === 'undefined') {
time = 0;
}
var newCenter = this.centerContainer.position;
if (typeof x != 'undefined' && typeof y != 'undefined') {
var ph = this.zoom * this.wrapper.clientHeight;
var phNew = amount * this.wrapper.clientHeight;
var scaleFactor = ph / 1000;
var scaleFactorNew = phNew / 1000;
var newZoom;
var center = this.centerContainer.position;
var focus = {
x: (x - this.wrapper.clientWidth / 2) / scaleFactor - center.x,
y: (-y + this.wrapper.clientHeight / 2) / scaleFactor - center.y,
};
var focusNew = {
x: (x - this.wrapper.clientWidth / 2) / scaleFactorNew - center.x,
y: (-y + this.wrapper.clientHeight / 2) / scaleFactorNew - center.y,
};
newCenter = center;
newCenter.x = center.x - (focus.x - focusNew.x);
newCenter.y = center.y - (focus.y - focusNew.y);
}
var self = this;
newZoom = amount < this.options.zoomMin ? this.options.zoomMin : amount;
if (newZoom == this.options.zoom) {
//reset book position
var focusedLeft = this.isFocusedLeft();
if (this.view == 1) {
focusedLeft ? this.focusLeft() : this.focusRight();
} else {
this.centerContainer.position.set(0, 0, 0);
}
this.updateBookPosition();
}
time = 0;
if (time > 0) {
if (!this.zooming) {
this.zooming = true;
// Define start and end values
const startZoom = this.zoom;
const endZoom = newZoom;
const startX = this.centerContainer.position.x;
const endX = newCenter.x;
const startY = this.centerContainer.position.y;
const endY = newCenter.y;
if (this.zoomAnimation) this.zoomAnimation.stop();
this.zoomAnimation = FLIPBOOK.animate({
from: 0,
to: 1,
duration: time,
easing: 'easeInSine',
step: (progress) => {
this.zoom = startZoom + (endZoom - startZoom) * progress;
this.centerContainer.position.x = startX + (endX - startX) * progress;
this.centerContainer.position.y = startY + (endY - startY) * progress;
this.updateCameraPosition();
if (this.htmlLayer) {
this.htmlLayer.position.x = startX + (endX - startX) * progress;
this.htmlLayer.position.y = startY + (endY - startY) * progress;
}
},
complete: () => {
self.zooming = false;
},
});
this.animations.push(this.zoomAnimation);
}
} else {
this.zoom = newZoom;
this.centerContainer.position.set(newCenter.x, newCenter.y, 0);
this.updateHtmlLayerPosition();
this.updateCameraPosition();
this.zooming = false;
}
if (amount <= 1 && amount <= this.zoom) {
this.updateBookPosition();
}
this.options.main.onZoom(newZoom);
this.loadPages();
};
FLIPBOOK.BookWebGL.prototype.tiltTo = function (amount) {
var factor = 0.3;
var newTilt = this.tilt + amount * factor;
newTilt = newTilt > this.options.tiltMax ? this.options.tiltMax : newTilt;
newTilt = newTilt < this.options.tiltMin ? this.options.tiltMin : newTilt;
this.tilt = newTilt;
this.updateCameraPosition();
};
FLIPBOOK.BookWebGL.prototype.panTo = function (amount) {
var factor = 0.2;
var newPan = this.pan - amount * factor;
newPan = newPan > this.options.panMax ? this.options.panMax : newPan;
newPan = newPan < this.options.panMin ? this.options.panMin : newPan;
this.pan = newPan;
this.updateCameraPosition();
};
FLIPBOOK.BookWebGL.prototype._start = function (e) {
this.centerContainerStart = this.centerContainer.position.clone();
this.mouseDown = true;
this.onMouseMove = '';
};
FLIPBOOK.BookWebGL.prototype._move = function (e, distanceX, distanceY) {
if (distanceX != 0 || distanceY != 0) {
this.moved = true;
let scaleFactor = ((this.zoom * this.wrapperH) / 1000) * this.sc;
this.moveToPos({
x: this.centerContainerStart.x / this.sc + distanceX / scaleFactor,
y: this.centerContainerStart.y / this.sc - distanceY / scaleFactor,
});
this.updateHtmlLayerPosition();
}
};
FLIPBOOK.BookWebGL.prototype._end = function (e) {
this.mouseDown = false;
this.pageMouseDown = false;
this.moved = false;
};
FLIPBOOK.BookWebGL.prototype.enable = function () {
if (this.enabled) {
this.onResize();
return;
}
this.enabled = true;
if (!this.initialized) {
this.init3d();
this.createPages();
this.rendering = false;
this.onResize();
}
this.render(true);
this.onResize();
};
FLIPBOOK.BookWebGL.prototype.disable = function () {
this.enabled = false;
this.render(false);
};
FLIPBOOK.BookWebGL.prototype.destroy = function () {
// Function to dispose materials
function disposeMaterial(material) {
if (!material) return;
// Dispose of textures
if (material.map) material.map.dispose();
if (material.lightMap) material.lightMap.dispose();
if (material.bumpMap) material.bumpMap.dispose();
if (material.normalMap) material.normalMap.dispose();
if (material.specularMap) material.specularMap.dispose();
if (material.envMap) material.envMap.dispose();
if (material.alphaMap) material.alphaMap.dispose();
if (material.roughnessMap) material.roughnessMap.dispose();
if (material.metalnessMap) material.metalnessMap.dispose();
if (material.displacementMap) material.displacementMap.dispose();
if (material.emissiveMap) material.emissiveMap.dispose();
if (material.clearcoatMap) material.clearcoatMap.dispose();
if (material.clearcoatNormalMap) material.clearcoatNormalMap.dispose();
if (material.clearcoatRoughnessMap) material.clearcoatRoughnessMap.dispose();
if (material.sheenColorMap) material.sheenColorMap.dispose();
if (material.sheenRoughnessMap) material.sheenRoughnessMap.dispose();
if (material.transmissionMap) material.transmissionMap.dispose();
if (material.thicknessMap) material.thicknessMap.dispose();
// Dispose of the material itself
material.dispose();
}
// Function to dispose objects
function disposeObject(object) {
if (!object) return;
// Dispose of geometries
if (object.geometry) {
object.geometry.dispose();
}
// Dispose of materials
if (object.material) {
if (Array.isArray(object.material)) {
object.material.forEach((material) => disposeMaterial(material));
} else {
disposeMaterial(object.material);
}
}
}
// Function to remove and dispose objects from the scene
function removeAndDisposeObject(scene, object) {
if (!scene || !object) return;
// Recursively remove and dispose of all children
while (object.children.length > 0) {
removeAndDisposeObject(scene, object.children[0]);
}
if (object.parent) {
object.parent.remove(object);
}
// Dispose of the object's resources
disposeObject(object);
}
// Function to dispose the entire scene
function disposeScene(scene) {
if (!scene) return;
while (scene.children.length > 0) {
removeAndDisposeObject(scene, scene.children[0]);
}
}
// Function to dispose the renderer and its DOM element
function disposeRenderer(renderer) {
if (!renderer) return;
renderer.dispose();
// Remove the renderer's DOM element from the document
if (renderer.domElement && renderer.domElement.parentNode) {
renderer.domElement.parentNode.removeChild(renderer.domElement);
}
}
disposeScene(this.Scene);
disposeRenderer(this.renderer);
this.pages.forEach(function (page) {
page.dispose();
page = null;
});
this.pages = null;
this.renderLoop = null;
this.animations.forEach(function (animation) {
animation.stop();
});
// this.renderer.forceContextLoss();
};
}
/* eslint-disable */
{
/* MOD3D */
/**
*
* http://github.com/foo123/MOD3
*
* MOD3 3D Modifier Library (port of actionscript AS3Mod to javascript)
* supports: THREE.js, J3D, Copperlicht, Pre3D
*
* @author Nikos M.
* @url http://nikos-web-development.netai.net/
*
**/
var MOD3 = MOD3 || {};
(function (a) {
a.Constants = {
PI: Math.PI,
invPI: 1 / Math.PI,
halfPI: 0.5 * Math.PI,
doublePI: 2 * Math.PI,
toRad: (1 / 180) * Math.PI,
toDeg: (1 / 180) * Math.PI,
};
a.ModConstant = {
LEFT: -1,
RIGHT: 1,
NONE: 0,
X: 1,
Y: 2,
Z: 4,
};
})(MOD3);
(function (a) {
var c = a.Constants;
a.XMath = {};
a.XMath.normalize = function (c, d, e) {
return d - c == 0 ? 1 : a.XMath.trim(0, 1, (e - c) / d);
};
a.XMath.toRange = function (a, c, e) {
return c - a == 0 ? 0 : a + (c - a) * e;
};
a.XMath.inRange = function (a, c, e, f) {
typeof f == 'undefined' && (f = !1);
return f ? e >= a && e <= c : e > a && e < c;
};
a.XMath.sign = function (a, c) {
typeof c == 'undefined' && (c = 0);
return 0 == a ? c : a > 0 ? 1 : -1;
};
a.XMath.trim = function (a, c, e) {
return Math.min(c, Math.max(a, e));
};
a.XMath.wrap = function (a, c, e) {
return e < a ? e + (c - a) : e >= c ? e - (c - a) : e;
};
a.XMath.degToRad = function (a) {
return a * c.toRad;
};
a.XMath.radToDeg = function (a) {
return a * c.toDeg;
};
a.XMath.presicion = function (a, c) {
var e = Math.pow(10, c);
return Math.round(a * e) / e;
};
a.XMath.uceil = function (a) {
return a < 0 ? Math.floor(a) : Math.ceil(a);
};
})(MOD3);
(function (a) {
a.Range = function (a, b) {
this.start = 0;
this.end = 1;
if (typeof a != 'undefined') {
this.start = a;
}
if (typeof b != 'undefined') {
this.end = b;
}
};
a.Range.prototype.getSize = function () {
return this.end - this.start;
};
a.Range.prototype.move = function (a) {
this.start += a;
this.end += a;
};
a.Range.prototype.isIn = function (a) {
return a >= this.start && a <= this.end;
};
a.Range.prototype.normalize = function (c) {
return a.XMath.normalize(this.start, this.end, c);
};
a.Range.prototype.toRange = function (c) {
return a.XMath.toRange(this.start, this.end, c);
};
a.Range.prototype.trim = function (c) {
return a.XMath.trim(this.start, this.end, c);
};
a.Range.prototype.interpolate = function (a, b) {
return this.toRange(b.normalize(a));
};
a.Range.prototype.toString = function () {
return '[' + this.start + ' - ' + this.end + ']';
};
})(MOD3);
(function (a) {
a.Phase = function (a) {
this.value = 0;
if (typeof a != 'undefined') {
this.value = a;
}
};
a.Phase.prototype.getPhasedValue = function () {
return Math.sin(this.value);
};
a.Phase.prototype.getAbsPhasedValue = function () {
return Math.abs(this.getPhasedValue());
};
a.Phase.prototype.getNormValue = function () {
return (this.getPhasedValue() + 1) * 0.5;
};
})(MOD3);
(function (a) {
a.Point = function (a, b) {
this.y = this.x = 0;
if (typeof a != 'undefined') {
this.x = a;
}
if (typeof b != 'undefined') {
this.y = b;
}
};
a.Point.prototype.clone = function () {
return new a.Point(this.x, this.y);
};
})(MOD3);
(function (a) {
a.Matrix = function (a, b, d, e) {
this.m11 = 1;
this.m21 = this.m12 = 0;
this.m22 = 1;
if (typeof a != 'undefined') {
this.m11 = a;
}
if (typeof b != 'undefined') {
this.m12 = b;
}
if (typeof d != 'undefined') {
this.m21 = d;
}
if (typeof e != 'undefined') {
this.m22 = e;
}
};
a.Matrix.prototype.rotate = function (a) {
var b = Math.cos(a);
var a = Math.sin(a);
this.m11 = b;
this.m12 = -a;
this.m21 = a;
this.m22 = b;
return this;
};
a.Matrix.prototype.scale = function (a, b) {
this.m21 = this.m12 = 0;
if (typeof a != 'undefined') {
this.m22 = this.m11 = a;
}
if (typeof b != 'undefined') {
this.m22 = b;
}
return this;
};
a.Matrix.prototype.multiply = function (a) {
var b = this.m11;
var d = this.m12;
var e = this.m21;
var f = this.m22;
var g = a.m11;
var h = a.m12;
var i = a.m21;
var a = a.m22;
this.m11 = b * g + d * i;
this.m12 = b * h + d * a;
this.m21 = e * g + f * i;
this.m22 = e * h + f * a;
return this;
};
a.Matrix.prototype.transformPoint = function (c) {
return new a.Point(this.m11 * c.x + this.m12 * c.y, this.m21 * c.x + this.m22 * c.y);
};
})(MOD3);
(function (a) {
a.Vector3 = function (a, b, d) {
this.z = this.y = this.x = null;
this.x = a;
this.y = b;
this.z = d;
};
a.Vector3.ZERO = function () {
return new a.Vector3(0, 0, 0);
};
a.Vector3.dot = function (a, b) {
return a.x * b.x + a.y * b.y + a.z * b.z;
};
a.Vector3.prototype.clone = function () {
return new a.Vector3(this.x, this.y, this.z);
};
a.Vector3.prototype.equals = function (a) {
return this.x == a.x && this.y == a.y && this.z == a.z;
};
a.Vector3.prototype.zero = function () {
this.x = this.y = this.z = 0;
};
a.Vector3.prototype.negate = function () {
return new a.Vector3(-this.x, -this.y, -this.z);
};
a.Vector3.prototype.add = function (c) {
return new a.Vector3(this.x + c.x, this.y + c.y, this.z + c.z);
};
a.Vector3.prototype.subtract = function (c) {
return new a.Vector3(this.x - c.x, this.y - c.y, this.z - c.z);
};
a.Vector3.prototype.multiplyScalar = function (c) {
return new a.Vector3(this.x * c, this.y * c, this.z * c);
};
a.Vector3.prototype.multiply = function (c) {
return new a.Vector3(this.x * c.x, this.y * c.y, this.z * c.z);
};
a.Vector3.prototype.divide = function (c) {
c = 1 / c;
return new a.Vector3(this.x * c, this.y * c, this.z * c);
};
a.Vector3.prototype.normalize = function () {
var a = this.x;
var b = this.y;
var d = this.z;
var a = a * a + b * b + d * d;
a > 0 && ((a = 1 / Math.sqrt(a)), (this.x *= a), (this.y *= a), (this.z *= a));
};
a.Vector3.prototype.getMagnitude = function () {
var a = this.x;
var b = this.y;
var d = this.z;
return Math.sqrt(a * a + b * b + d * d);
};
a.Vector3.prototype.setMagnitude = function (a) {
this.normalize();
this.x *= a;
this.y *= a;
this.z *= a;
};
a.Vector3.prototype.toString = function () {
return '[' + this.x + ' , ' + this.y + ' , ' + this.z + ']';
};
a.Vector3.prototype.sum = function (a, b) {
return a.add(b);
};
a.Vector3.prototype.dot = function (a, b) {
return a.x * b.x + a.y * b.y + a.z * b.z;
};
a.Vector3.prototype.cross = function (c, b) {
var d = c.x;
var e = c.y;
var f = c.z;
var g = b.x;
var h = b.y;
var i = b.z;
return new a.Vector3(e * i - f * h, f * g - d * i, d * h - e * g);
};
a.Vector3.prototype.distance = function (a, b) {
var d = a.x - b.x;
var e = a.y - b.y;
var f = a.z - b.z;
return Math.sqrt(d * d + e * e + f * f);
};
})(MOD3);
(function (a) {
a.Matrix4 = function (a, b, d, e, f, g, h, i, n, m, o, k, p, l, j, q) {
this.n11 = 1;
this.n21 = this.n14 = this.n13 = this.n12 = 0;
this.n22 = 1;
this.n32 = this.n31 = this.n24 = this.n23 = 0;
this.n33 = 1;
this.n43 = this.n42 = this.n41 = this.n34 = 0;
this.n44 = 1;
if (typeof a != 'undefined') {
this.n11 = a;
}
if (typeof b != 'undefined') {
this.n12 = b;
}
if (typeof d != 'undefined') {
this.n13 = d;
}
if (typeof e != 'undefined') {
this.n14 = e;
}
if (typeof f != 'undefined') {
this.n21 = f;
}
if (typeof g != 'undefined') {
this.n22 = g;
}
if (typeof h != 'undefined') {
this.n23 = h;
}
if (typeof i != 'undefined') {
this.n24 = i;
}
if (typeof n != 'undefined') {
this.n31 = n;
}
if (typeof m != 'undefined') {
this.n32 = m;
}
if (typeof o != 'undefined') {
this.n33 = o;
}
if (typeof k != 'undefined') {
this.n34 = k;
}
if (typeof p != 'undefined') {
this.n41 = p;
}
if (typeof l != 'undefined') {
this.n42 = l;
}
if (typeof j != 'undefined') {
this.n43 = j;
}
if (typeof q != 'undefined') {
this.n44 = q;
}
};
a.Matrix4.prototype.translationMatrix = function (a, b, d) {
this.n14 = a;
this.n24 = b;
this.n34 = d;
return this;
};
a.Matrix4.prototype.scaleMatrix = function (a, b, d) {
this.n11 = a;
this.n22 = b;
this.n33 = d;
return this;
};
a.Matrix4.prototype.rotationMatrix = function (a, b, d, e) {
var f = Math.cos(e);
var g = Math.sin(e);
var e = 1 - f;
var h = a * b * e;
var i = b * d * e;
var n = a * d * e;
var m = g * d;
var o = g * b;
g *= a;
this.n11 = f + a * a * e;
this.n12 = -m + h;
this.n13 = o + n;
this.n14 = 0;
this.n21 = m + h;
this.n22 = f + b * b * e;
this.n23 = -g + i;
this.n24 = 0;
this.n31 = -o + n;
this.n32 = g + i;
this.n33 = f + d * d * e;
this.n34 = 0;
return this;
};
a.Matrix4.prototype.calculateMultiply = function (a, b) {
var d = a.n11;
var e = b.n11;
var f = a.n21;
var g = b.n21;
var h = a.n31;
var i = b.n31;
var n = a.n12;
var m = b.n12;
var o = a.n22;
var k = b.n22;
var p = a.n32;
var l = b.n32;
var j = a.n13;
var q = b.n13;
var r = a.n23;
var t = b.n23;
var s = a.n33;
var u = b.n33;
var v = a.n14;
var w = b.n14;
var z = a.n24;
var x = b.n24;
var A = a.n34;
var y = b.n34;
this.n11 = d * e + n * g + j * i;
this.n12 = d * m + n * k + j * l;
this.n13 = d * q + n * t + j * u;
this.n14 = d * w + n * x + j * y + v;
this.n21 = f * e + o * g + r * i;
this.n22 = f * m + o * k + r * l;
this.n23 = f * q + o * t + r * u;
this.n24 = f * w + o * x + r * y + z;
this.n31 = h * e + p * g + s * i;
this.n32 = h * m + p * k + s * l;
this.n33 = h * q + p * t + s * u;
this.n34 = h * w + p * x + s * y + A;
};
a.Matrix4.prototype.multiply = function (a, b) {
this.calculateMultiply(a, b);
return this;
};
a.Matrix4.prototype.multiplyVector = function (a, b) {
var d = b.x;
var e = b.y;
var f = b.z;
b.x = d * a.n11 + e * a.n12 + f * a.n13 + a.n14;
b.y = d * a.n21 + e * a.n22 + f * a.n23 + a.n24;
b.z = d * a.n31 + e * a.n32 + f * a.n33 + a.n34;
};
})(MOD3);
(function (a) {
a.VertexProxy = function (a) {
this.originalZ = this.originalY = this.originalX = this.ratioZ = this.ratioY = this.ratioX = null;
if (typeof a != 'undefined') {
this.vertex = a;
}
};
a.VertexProxy.prototype.setVertex = function () {};
a.VertexProxy.prototype.setRatios = function (a, b, d) {
this.ratioX = a;
this.ratioY = b;
this.ratioZ = d;
};
a.VertexProxy.prototype.setOriginalPosition = function (a, b, d) {
this.originalX = a;
this.originalY = b;
this.originalZ = d;
};
a.VertexProxy.prototype.getX = function () {};
a.VertexProxy.prototype.getY = function () {};
a.VertexProxy.prototype.getZ = function () {};
a.VertexProxy.prototype.setX = function () {};
a.VertexProxy.prototype.setY = function () {};
a.VertexProxy.prototype.setZ = function () {};
a.VertexProxy.prototype.getValue = function (c) {
switch (c) {
case a.ModConstant.X:
return this.getX();
case a.ModConstant.Y:
return this.getY();
case a.ModConstant.Z:
return this.getZ();
}
return 0;
};
a.VertexProxy.prototype.setValue = function (c, b) {
switch (c) {
case a.ModConstant.X:
this.setX(b);
break;
case a.ModConstant.Y:
this.setY(b);
break;
case a.ModConstant.Z:
this.setZ(b);
}
};
a.VertexProxy.prototype.getRatio = function (c) {
switch (c) {
case a.ModConstant.X:
return this.ratioX;
case a.ModConstant.Y:
return this.ratioY;
case a.ModConstant.Z:
return this.ratioZ;
}
return -1;
};
a.VertexProxy.prototype.getOriginalValue = function (c) {
switch (c) {
case a.ModConstant.X:
return this.originalX;
case a.ModConstant.Y:
return this.originalY;
case a.ModConstant.Z:
return this.originalZ;
}
return 0;
};
a.VertexProxy.prototype.reset = function () {
this.setX(this.originalX);
this.setY(this.originalY);
this.setZ(this.originalZ);
};
a.VertexProxy.prototype.collapse = function () {
this.originalX = this.getX();
this.originalY = this.getY();
this.originalZ = this.getZ();
};
a.VertexProxy.prototype.getVector = function () {
return new a.Vector3(this.getX(), this.getY(), this.getZ());
};
a.VertexProxy.prototype.setVector = function (a) {
this.setX(a.x);
this.setY(a.y);
this.setZ(a.z);
};
a.VertexProxy.prototype.getRatioVector = function () {
return new a.Vector3(this.ratioX, this.ratioY, this.ratioZ);
};
})(MOD3);
(function (a) {
a.FaceProxy = function () {
this.vertices = [];
};
a.FaceProxy.prototype.addVertex = function (a) {
this.vertices.push(a);
};
a.FaceProxy.prototype.getVertices = function () {
return this.vertices;
};
})(MOD3);
(function (a) {
a.MeshProxy = function () {
this.depth =
this.height =
this.width =
this.minAxis =
this.midAxis =
this.maxAxis =
this.minZ =
this.minY =
this.minX =
this.maxZ =
this.maxY =
this.maxX =
null;
this.vertices = [];
this.faces = [];
this.mesh = null;
};
a.MeshProxy.prototype.getVertices = function () {
return this.vertices;
};
a.MeshProxy.prototype.getFaces = function () {
return this.faces;
};
a.MeshProxy.prototype.analyzeGeometry = function () {
for (
var c = this.getVertices(),
b = c.length,
d = b,
e,
f,
g,
h,
i,
n,
m,
o,
k,
p,
l = !0,
j = Math.min,
q = Math.max;
--d >= 0;
) {
(e = c[d]),
(f = e.getX()),
(g = e.getY()),
(h = e.getZ()),
l
? ((i = n = f), (m = o = g), (k = p = h), (l = !1))
: ((i = j(i, f)), (m = j(m, g)), (k = j(k, h)), (n = q(n, f)), (o = q(o, g)), (p = q(p, h))),
e.setOriginalPosition(f, g, h);
}
f = n - i;
g = o - m;
var depth = p - k;
this.width = f;
this.height = g;
this.depth = depth;
this.minX = i;
this.maxX = n;
this.minY = m;
this.maxY = o;
this.minZ = k;
this.maxZ = p;
d = q(f, q(g, depth));
j = j(f, j(g, depth));
if (d == f && j == g) {
(this.minAxis = a.ModConstant.Y), (this.midAxis = a.ModConstant.Z), (this.maxAxis = a.ModConstant.X);
} else if (d == f && j == depth) {
(this.minAxis = a.ModConstant.Z), (this.midAxis = a.ModConstant.Y), (this.maxAxis = a.ModConstant.X);
} else if (d == g && j == f) {
(this.minAxis = a.ModConstant.X), (this.midAxis = a.ModConstant.Z), (this.maxAxis = a.ModConstant.Y);
} else if (d == g && j == depth) {
(this.minAxis = a.ModConstant.Z), (this.midAxis = a.ModConstant.X), (this.maxAxis = a.ModConstant.Y);
} else if (d == depth && j == f) {
(this.minAxis = a.ModConstant.X), (this.midAxis = a.ModConstant.Y), (this.maxAxis = a.ModConstant.Z);
} else if (d == depth && j == g) {
(this.minAxis = a.ModConstant.Y), (this.midAxis = a.ModConstant.X), (this.maxAxis = a.ModConstant.Z);
}
for (d = b; --d >= 0; ) {
(e = c[d]), e.setRatios((e.getX() - i) / f, (e.getY() - m) / g, (e.getZ() - k) / depth);
}
};
a.MeshProxy.prototype.resetGeometry = function () {
for (var a = this.getVertices(), b = a.length; --b >= 0; ) {
a[b].reset();
}
};
a.MeshProxy.prototype.collapseGeometry = function () {
for (var a = this.getVertices(), b = a.length; --b >= 0; ) {
a[b].collapse();
}
this.analyzeGeometry();
};
a.MeshProxy.prototype.getMin = function (c) {
switch (c) {
case a.ModConstant.X:
return this.minX;
case a.ModConstant.Y:
return this.minY;
case a.ModConstant.Z:
return this.minZ;
}
return -1;
};
a.MeshProxy.prototype.getMax = function (c) {
switch (c) {
case a.ModConstant.X:
return this.maxX;
case a.ModConstant.Y:
return this.maxY;
case a.ModConstant.Z:
return this.maxZ;
}
return -1;
};
a.MeshProxy.prototype.getSize = function (c) {
switch (c) {
case a.ModConstant.X:
return this.width;
case a.ModConstant.Y:
return this.height;
case a.ModConstant.Z:
return this.depth;
}
return -1;
};
a.MeshProxy.prototype.setMesh = function (a) {
this.mesh = a;
this.vertices = [];
this.faces = [];
};
a.MeshProxy.prototype.postApply = function () {};
a.MeshProxy.prototype.updateMeshPosition = function () {};
})(MOD3);
(function (a) {
a.Modifier = function () {
this.mod = null;
};
a.Modifier.prototype.setModifiable = function (a) {
this.mod = a;
};
a.Modifier.prototype.getVertices = function () {
return this.mod.getVertices();
};
a.Modifier.prototype.apply = function () {};
})(MOD3);
(function (a) {
a.Library3d = function () {
this.id = '';
this.vertexClass = this.meshClass = null;
};
})(MOD3);
(function (a) {
a.PluginFactory = {};
a.PluginFactory.getMeshProxy = function (a) {
return new a.meshClass();
};
})(MOD3);
(function (a) {
a.ModifierStack = function (c, b) {
this.lib3d = c;
this.stack = this.baseMesh = null;
this.baseMesh = a.PluginFactory.getMeshProxy(c);
this.baseMesh.setMesh(b);
this.baseMesh.analyzeGeometry();
this.stack = [];
};
a.ModifierStack.prototype.addModifier = function (a) {
a.setModifiable(this.baseMesh);
this.stack.push(a);
};
a.ModifierStack.prototype.apply = function () {
this.baseMesh.resetGeometry();
for (var a = this.stack, b = a.length, d = 0; d < b; ) {
a[d++].apply();
}
this.baseMesh.postApply();
};
a.ModifierStack.prototype.collapse = function () {
this.apply();
this.baseMesh.collapseGeometry();
this.stack = [];
};
a.ModifierStack.prototype.clear = function () {
this.stack = [];
};
a.ModifierStack.prototype.getMeshInfo = function () {
return this.baseMesh;
};
})(MOD3);
(function (a) {
a.Bend = function (c, b, d) {
this.diagAngle = this.angle = this.offset = this.force = null;
this.constraint = a.ModConstant.NONE;
this.m2 = this.m1 = this.origin = this.height = this.width = this.mid = this.min = this.max = null;
this.switchAxes = !1;
this.force = c;
this.offset = b;
this.setAngle(d);
};
a.Bend.prototype = new a.Modifier();
a.Bend.prototype.constructor = a.Bend;
a.Bend.prototype.setAngle = function (c) {
this.angle = c;
this.m1 = new a.Matrix();
this.m1.rotate(c);
this.m2 = new a.Matrix();
this.m2.rotate(-c);
};
a.Bend.prototype.setModifiable = function (c) {
a.Modifier.prototype.setModifiable.call(this, c);
this.max = this.switchAxes ? this.mod.midAxis : this.mod.maxAxis;
this.min = this.mod.minAxis;
this.mid = this.switchAxes ? this.mod.maxAxis : this.mod.midAxis;
this.width = this.mod.getSize(this.max);
this.height = this.mod.getSize(this.mid);
this.origin = this.mod.getMin(this.max);
this.diagAngle = Math.atan(this.width / this.height);
};
a.Bend.prototype.apply = function () {
if (this.force != 0) {
for (
var c = this.mod.getVertices(),
b = c.length,
d = this.width,
e = this.offset,
f = this.origin,
g = this.max,
h = this.min,
i = this.mid,
n = this.m1,
m = this.m2,
o = f + d * e,
k = d / Math.PI / this.force,
p = a.Constants.doublePI * (d / (k * a.Constants.doublePI)),
l,
j,
q,
r,
t = 1 / d,
s = a.Constants.halfPI,
u = Math.sin,
v = Math.cos;
--b >= 0;
) {
(d = c[b]),
(l = d.getValue(g)),
(j = d.getValue(i)),
(q = d.getValue(h)),
(j = n.transformPoint(new a.Point(l, j))),
(l = j.x),
(j = j.y),
(r = (l - f) * t),
(this.constraint == a.ModConstant.LEFT && r <= e) ||
(this.constraint == a.ModConstant.RIGHT && r >= e) ||
((r = s - p * e + p * r),
(l = u(r) * (k + q)),
(r = v(r) * (k + q)),
(q = l - k),
(l = o - r)),
(j = m.transformPoint(new a.Point(l, j))),
(l = j.x),
(j = j.y),
d.setValue(g, l),
d.setValue(i, j),
d.setValue(h, q);
}
}
};
})(MOD3);
(function (a) {
a.LibraryThree = function () {
this.id = 'Three.js';
this.meshClass = a.MeshThree;
this.vertexClass = a.VertexThree;
};
a.LibraryThree.prototype = new a.Library3d();
a.LibraryThree.prototype.constructor = a.LibraryThree;
})(MOD3);
(function (a) {
a.VertexThree = function (a) {
this.mesh = a;
};
a.VertexThree.prototype = new a.VertexProxy();
a.VertexThree.prototype.setVertex = function (a) {
this.vertex = a;
this.originalX = a.x;
this.originalY = a.y;
this.originalZ = a.z;
};
a.VertexThree.prototype.getX = function () {
return this.vertex.x;
};
a.VertexThree.prototype.getY = function () {
return this.vertex.y;
};
a.VertexThree.prototype.getZ = function () {
return this.vertex.z;
};
a.VertexThree.prototype.setX = function (a) {
this.vertex.x = a;
a = this.mesh;
a.geometry.verticesNeedUpdate = !0;
a.geometry.normalsNeedUpdate = !0;
a.geometry.buffersNeedUpdate = !0;
a.geometry.dynamic = !0;
};
a.VertexThree.prototype.setY = function (a) {
this.vertex.y = a;
a = this.mesh;
a.geometry.verticesNeedUpdate = !0;
a.geometry.normalsNeedUpdate = !0;
a.geometry.buffersNeedUpdate = !0;
a.geometry.dynamic = !0;
};
a.VertexThree.prototype.setZ = function (a) {
this.vertex.z = a;
a = this.mesh;
a.geometry.verticesNeedUpdate = !0;
a.geometry.normalsNeedUpdate = !0;
a.geometry.buffersNeedUpdate = !0;
a.geometry.dynamic = !0;
};
})(MOD3);
(function (a) {
a.MeshThree = function () {};
a.MeshThree.prototype = new a.MeshProxy();
a.MeshThree.prototype.setMesh = function (c) {
a.MeshProxy.prototype.setMesh.call(this, c);
for (
var c = [],
b = 0,
d = this.mesh.geometry.vertices,
e = d.length,
f = this.mesh.geometry.faces,
g = f.length,
h,
b = 0;
b < e;
) {
(h = new a.VertexThree(this.mesh)), h.setVertex(d[b]), this.vertices.push(h), (c[d[b]] = h), b++;
}
for (b = 0; b < g; ) {
(e = new a.FaceProxy()),
f[b] instanceof THREE.Face3
? (e.addVertex(c[d[f[b].a]]), e.addVertex(c[d[f[b].b]]), e.addVertex(c[d[f[b].c]]))
: f[b] instanceof THREE.Face4 &&
(e.addVertex(c[d[f[b].a]]),
e.addVertex(c[d[f[b].b]]),
e.addVertex(c[d[f[b].c]]),
e.addVertex(c[d[f[b].d]])),
this.faces.push(e),
b++;
}
// delete lookup;
};
a.MeshThree.prototype.updateMeshPosition = function (a) {
var b = this.mesh;
b.position.x += a.x;
b.position.y += a.y;
b.position.z += a.z;
};
})(MOD3);
}
{
/**
* Based on http://www.emagix.net/academic/mscs-project/item/camera-sync-with-css3-and-webgl-threejs
* @author mrdoob / http://mrdoob.com/
* @author yomotsu / https://yomotsu.net/
*/
FLIPBOOK.CSS3DObject = function (element) {
THREE.Object3D.call(this);
this.element = element;
this.element.style.position = 'absolute';
this.element.style.pointerEvents = 'auto';
this.addEventListener('removed', function () {
this.traverse(function (object) {
if (object.element instanceof Element && object.element.parentNode !== null) {
object.element.parentNode.removeChild(object.element);
}
});
});
};
FLIPBOOK.CSS3DObject.prototype = Object.create(THREE.Object3D.prototype);
FLIPBOOK.CSS3DObject.prototype.constructor = FLIPBOOK.CSS3DObject;
FLIPBOOK.CSS3DSprite = function (element) {
FLIPBOOK.CSS3DObject.call(this, element);
};
FLIPBOOK.CSS3DSprite.prototype = Object.create(FLIPBOOK.CSS3DObject.prototype);
FLIPBOOK.CSS3DSprite.prototype.constructor = FLIPBOOK.CSS3DSprite;
//
FLIPBOOK.CSS3DRenderer = function () {
var _this = this;
var _width;
var _height;
var _widthHalf;
var _heightHalf;
var matrix = new THREE.Matrix4();
var cache = {
camera: { fov: 0, style: '' },
objects: new WeakMap(),
};
var domElement = document.createElement('div');
domElement.style.overflow = 'hidden';
this.domElement = domElement;
var cameraElement = document.createElement('div');
cameraElement.style.WebkitTransformStyle = 'preserve-3d';
cameraElement.style.transformStyle = 'preserve-3d';
cameraElement.style.pointerEvents = 'none';
domElement.appendChild(cameraElement);
var isIE = /Trident/i.test(navigator.userAgent);
this.getSize = function () {
return {
width: _width,
height: _height,
};
};
this.setSize = function (width, height) {
_width = width;
_height = height;
_widthHalf = _width / 2;
_heightHalf = _height / 2;
domElement.style.width = width + 'px';
domElement.style.height = height + 'px';
cameraElement.style.width = width + 'px';
cameraElement.style.height = height + 'px';
};
function epsilon(value) {
return Math.abs(value) < 1e-10 ? 0 : value;
}
function getCameraCSSMatrix(matrix) {
var elements = matrix.elements;
return (
'matrix3d(' +
epsilon(elements[0]) +
',' +
epsilon(-elements[1]) +
',' +
epsilon(elements[2]) +
',' +
epsilon(elements[3]) +
',' +
epsilon(elements[4]) +
',' +
epsilon(-elements[5]) +
',' +
epsilon(elements[6]) +
',' +
epsilon(elements[7]) +
',' +
epsilon(elements[8]) +
',' +
epsilon(-elements[9]) +
',' +
epsilon(elements[10]) +
',' +
epsilon(elements[11]) +
',' +
epsilon(elements[12]) +
',' +
epsilon(-elements[13]) +
',' +
epsilon(elements[14]) +
',' +
epsilon(elements[15]) +
')'
);
}
function getObjectCSSMatrix(matrix, cameraCSSMatrix) {
var elements = matrix.elements;
var matrix3d =
'matrix3d(' +
epsilon(elements[0]) +
',' +
epsilon(elements[1]) +
',' +
epsilon(elements[2]) +
',' +
epsilon(elements[3]) +
',' +
epsilon(-elements[4]) +
',' +
epsilon(-elements[5]) +
',' +
epsilon(-elements[6]) +
',' +
epsilon(-elements[7]) +
',' +
epsilon(elements[8]) +
',' +
epsilon(elements[9]) +
',' +
epsilon(elements[10]) +
',' +
epsilon(elements[11]) +
',' +
epsilon(elements[12]) +
',' +
epsilon(elements[13]) +
',' +
epsilon(elements[14]) +
',' +
epsilon(elements[15]) +
')';
if (isIE) {
return (
'translate(-50%,-50%)' +
'translate(' +
_widthHalf +
'px,' +
_heightHalf +
'px)' +
cameraCSSMatrix +
matrix3d
);
}
return 'translate(-50%,-50%)' + matrix3d;
}
function renderObject(object, scene, camera, cameraCSSMatrix) {
if (object instanceof FLIPBOOK.CSS3DObject) {
object.onBeforeRender(_this, scene, camera);
var style;
if (object instanceof FLIPBOOK.CSS3DSprite) {
// http://swiftcoder.wordpress.com/2008/11/25/constructing-a-billboard-matrix/
matrix.copy(camera.matrixWorldInverse);
matrix.transpose();
matrix.copyPosition(object.matrixWorld);
matrix.scale(object.scale);
matrix.elements[3] = 0;
matrix.elements[7] = 0;
matrix.elements[11] = 0;
matrix.elements[15] = 1;
style = getObjectCSSMatrix(matrix, cameraCSSMatrix);
} else {
style = getObjectCSSMatrix(object.matrixWorld, cameraCSSMatrix);
}
var element = object.element;
var cachedObject = cache.objects.get(object);
if (cachedObject === undefined || cachedObject.style !== style) {
element.style.WebkitTransform = style;
element.style.transform = style;
var objectData = { style: style };
if (isIE) {
objectData.distanceToCameraSquared = getDistanceToSquared(camera, object);
}
cache.objects.set(object, objectData);
}
if (element.parentNode !== cameraElement) {
cameraElement.appendChild(element);
}
object.onAfterRender(_this, scene, camera);
}
for (var i = 0, l = object.children.length; i < l; i++) {
renderObject(object.children[i], scene, camera, cameraCSSMatrix);
}
}
var getDistanceToSquared = (function () {
var a = new THREE.Vector3();
var b = new THREE.Vector3();
return function (object1, object2) {
a.setFromMatrixPosition(object1.matrixWorld);
b.setFromMatrixPosition(object2.matrixWorld);
return a.distanceToSquared(b);
};
})();
function filterAndFlatten(scene) {
var result = [];
scene.traverse(function (object) {
if (object instanceof THREE.CSS3DObject) {
result.push(object);
}
});
return result;
}
function zOrder(scene) {
var sorted = filterAndFlatten(scene).sort(function (a, b) {
var distanceA = cache.objects.get(a).distanceToCameraSquared;
var distanceB = cache.objects.get(b).distanceToCameraSquared;
return distanceA - distanceB;
});
var zMax = sorted.length;
for (var i = 0, l = sorted.length; i < l; i++) {
sorted[i].element.style.zIndex = zMax - i;
}
}
this.render = function (scene, camera) {
var fov = camera.projectionMatrix.elements[5] * _heightHalf;
if (cache.camera.fov !== fov) {
if (camera.isPerspectiveCamera) {
domElement.style.WebkitPerspective = fov + 'px';
domElement.style.perspective = fov + 'px';
} else {
domElement.style.WebkitPerspective = '';
domElement.style.perspective = '';
}
cache.camera.fov = fov;
}
if (scene.autoUpdate === true) {
scene.updateMatrixWorld();
}
if (camera.parent === null) {
camera.updateMatrixWorld();
}
if (camera.isOrthographicCamera) {
var tx = -(camera.right + camera.left) / 2;
var ty = (camera.top + camera.bottom) / 2;
}
var cameraCSSMatrix = camera.isOrthographicCamera
? 'scale(' +
fov +
')' +
'translate(' +
epsilon(tx) +
'px,' +
epsilon(ty) +
'px)' +
getCameraCSSMatrix(camera.matrixWorldInverse)
: 'translateZ(' + fov + 'px)' + getCameraCSSMatrix(camera.matrixWorldInverse);
var style = cameraCSSMatrix + 'translate(' + _widthHalf + 'px,' + _heightHalf + 'px)';
if (cache.camera.style !== style && !isIE) {
cameraElement.style.WebkitTransform = style;
cameraElement.style.transform = style;
cache.camera.style = style;
}
renderObject(scene, scene, camera, cameraCSSMatrix);
if (isIE) {
// IE10 and 11 does not support 'preserve-3d'.
// Thus, z-order in 3D will not work.
// We have to calc z-order manually and set CSS z-index for IE.
// FYI: z-index can't handle object intersection
zOrder(scene);
}
};
};
}