sphere-viewer
Advanced tools
Comparing version 1.0.7 to 1.1.0
(function webpackUniversalModuleDefinition(root, factory) { | ||
if(typeof exports === 'object' && typeof module === 'object') | ||
module.exports = factory(require("THREE"), require("jquery")); | ||
module.exports = factory(require("THREE"), require("$")); | ||
else if(typeof define === 'function' && define.amd) | ||
define(["THREE", "jquery"], factory); | ||
define(["THREE", "$"], factory); | ||
else if(typeof exports === 'object') | ||
exports["SphereViewer"] = factory(require("THREE"), require("jquery")); | ||
exports["SphereViewer"] = factory(require("THREE"), require("$")); | ||
else | ||
root["SphereViewer"] = factory(root["THREE"], root["jquery"]); | ||
root["SphereViewer"] = factory(root["THREE"], root["$"]); | ||
})(this, function(__WEBPACK_EXTERNAL_MODULE_0__, __WEBPACK_EXTERNAL_MODULE_4__) { | ||
@@ -19,5 +19,5 @@ return /******/ (function(modules) { // webpackBootstrap | ||
/******/ // Check if module is in cache | ||
/******/ if(installedModules[moduleId]) | ||
/******/ if(installedModules[moduleId]) { | ||
/******/ return installedModules[moduleId].exports; | ||
/******/ | ||
/******/ } | ||
/******/ // Create a new module (and put it into the cache) | ||
@@ -648,5 +648,5 @@ /******/ var module = installedModules[moduleId] = { | ||
/* all exports used */ | ||
/*!*************************!*\ | ||
!*** external "jquery" ***! | ||
\*************************/ | ||
/*!********************!*\ | ||
!*** external "$" ***! | ||
\********************/ | ||
/***/ (function(module, exports) { | ||
@@ -669,3 +669,3 @@ | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
@@ -688,29 +688,38 @@ exports.Viewer = undefined; | ||
function SphereViewer(imageUrls, config) { | ||
function SphereViewer(config) { | ||
this.isDisposed = false; | ||
this.config = config = config || {}; | ||
this.isDisposed = false; | ||
this.config = config = config || {}; | ||
this.initViewport(); | ||
this.initScene(); | ||
this.initSphere(imageUrls); | ||
this.initViewport(); | ||
this.initScene(); | ||
if (this.config.logo) { | ||
this.initLogo(this.config.logo, this.config.logoDistance === void 0 ? -15 : this.config.logoDistance); | ||
} | ||
if (this.config.sphere && !this.config.forceCube) { | ||
// IF image URLs are provided via a "sphere" param | ||
// AND cube geometry is not forced | ||
// > apply texture onto a sphere | ||
this.initSphere(); | ||
} else { | ||
// ELSE apply texture onto a cube/box | ||
this.initCube(); | ||
} | ||
if (this.config.hint) { | ||
this.showHint(this.config.hint); | ||
} | ||
if (this.config.logo) { | ||
this.initLogo(this.config.logo, this.config.logoDistance === void 0 ? -15 : this.config.logoDistance); | ||
} | ||
this.initControls(); | ||
if (this.config.hint) { | ||
this.showHint(this.config.hint); | ||
} | ||
// attaching a bound version of the method to the instance | ||
// > we'll need it to remove event listener | ||
this.onResize = this.onResize.bind(this); | ||
this.initControls(); | ||
window.addEventListener('resize', this.onResize, false); | ||
window.setTimeout(this.onResize, 1); | ||
// attaching a bound version of the method to the instance | ||
// > we'll need it to remove event listener | ||
this.onResize = this.onResize.bind(this); | ||
this.render(); | ||
window.addEventListener('resize', this.onResize, false); | ||
window.setTimeout(this.onResize, 1); | ||
this.render(); | ||
} /** | ||
@@ -727,35 +736,35 @@ * SphereViewer.js <https://github.com/knee-cola/SphereViewer.js> | ||
var nativeW = window.devicePixelRatio * window.screen.availWidth, | ||
scale = 1 / window.devicePixelRatio, | ||
viewportMeta = (0, _jquery2.default)('head meta[name="viewport"]'); | ||
var nativeW = window.devicePixelRatio * window.screen.availWidth, | ||
scale = 1 / window.devicePixelRatio, | ||
viewportMeta = (0, _jquery2.default)('head meta[name="viewport"]'); | ||
this.originalViewPortMeta = viewportMeta.attr('content'); | ||
viewportMeta.attr('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', user-scalable=0'); | ||
this.originalViewPortMeta = viewportMeta.attr('content'); | ||
viewportMeta.attr('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', user-scalable=0'); | ||
// na mobitelima pixel ration NIJE 1 | ||
var isMobile = window.devicePixelRatio !== 1; | ||
// na mobitelima pixel ration NIJE 1 | ||
var isMobile = window.devicePixelRatio !== 1; | ||
this.container = document.createElement('div'); | ||
this.container.className = 'sphere-container ' + (isMobile ? 'isMobile' : 'isDesktop'); | ||
this.container = document.createElement('div'); | ||
this.container.className = 'sphere-container ' + (isMobile ? 'isMobile' : 'isDesktop'); | ||
if (this.config.closeButtonHtml) { | ||
this.closeButton = document.createElement('i'); | ||
this.closeButton.innerHTML = this.config.closeButtonHtml; | ||
this.container.appendChild(this.closeButton); | ||
// attaching a bound version of the method to the instance | ||
// > we'll need it to remove event listener | ||
this.closeButton_onClick = this.closeButton_onClick.bind(this); | ||
this.closeButton.addEventListener('click', this.closeButton_onClick); | ||
} | ||
if (this.config.closeButtonHtml) { | ||
this.closeButton = document.createElement('i'); | ||
this.closeButton.innerHTML = this.config.closeButtonHtml; | ||
this.container.appendChild(this.closeButton); | ||
// attaching a bound version of the method to the instance | ||
// > we'll need it to remove event listener | ||
this.closeButton_onClick = this.closeButton_onClick.bind(this); | ||
this.closeButton.addEventListener('click', this.closeButton_onClick); | ||
} | ||
document.getElementsByTagName('body')[0].appendChild(this.container); | ||
document.getElementsByTagName('body')[0].appendChild(this.container); | ||
}; // proto.initViewport = function() {...} | ||
proto.closeButton_onClick = function () { | ||
this.dispose(); | ||
this.dispatchEvent({ type: 'closed' }); | ||
this.dispose(); | ||
this.dispatchEvent({ type: 'closed' }); | ||
}; | ||
proto.controls_onTap = function (ev) { | ||
// on first tap - hide the hint | ||
this.hideHint(); | ||
// on first tap - hide the hint | ||
this.hideHint(); | ||
}; | ||
@@ -765,48 +774,266 @@ | ||
var body = document.getElementsByTagName('body')[0]; | ||
var body = document.getElementsByTagName('body')[0]; | ||
this.renderer = new _three.WebGLRenderer(); | ||
this.renderer = new _three.WebGLRenderer(); | ||
this.renderer.setSize(body.scrollWidth, body.scrollHeight); | ||
this.container.appendChild(this.renderer.domElement); | ||
this.renderer.setSize(body.scrollWidth, body.scrollHeight); | ||
this.container.appendChild(this.renderer.domElement); | ||
this.scene = new _three.Scene(); | ||
this.scene = new _three.Scene(); | ||
var fieldOfView = 90, | ||
aspectRatio = 1, | ||
near = 1, | ||
far = 1000; | ||
var fieldOfView = 90, | ||
aspectRatio = 1, | ||
near = 1, | ||
far = 1000; | ||
this.camera = new _three.PerspectiveCamera(fieldOfView, aspectRatio, near, far); | ||
this.scene.add(this.camera); | ||
this.camera = new _three.PerspectiveCamera(fieldOfView, aspectRatio, near, far); | ||
this.scene.add(this.camera); | ||
}; // proto.initScene = function() {...} | ||
proto.initSphere = function (imageUrls) { | ||
proto.initCube = function (imgUrl) { | ||
var speherRadius = 100, | ||
sphere_H_segments = 64, | ||
sphere_V_segments = 64; | ||
var cubeSize = 100, | ||
materials; | ||
this.imgLoader = new _progressiveImgLoader.ProgressiveImgLoader(); | ||
if (this.config.sphere) { | ||
// IF a sphereicaql image is to be used | ||
// > convert it from spherical projection (equirectangulat) | ||
// to cubical projection (rectilinear) | ||
materials = this.loadEqui(); | ||
} else if (this.config.tiles) { | ||
// ELSE IF the texture is proveded as separate tiles | ||
// > load each tile separatley | ||
materials = this.loadTiles(); | ||
} else if (this.config.atlas) { | ||
// ELSE IF the texture is provided as a single Atlas image file | ||
// containing all the tiles | ||
// > load the atlas file and split it into tiles | ||
materials = this.loadAtlas(); | ||
} | ||
this.loader_onDone = this.loader_onDone.bind(this); | ||
this.mesh = new _three.Mesh(new _three.BoxGeometry(cubeSize, cubeSize, cubeSize), materials); | ||
this.mesh.scale.x = -1; // flipping sphere inside-out - not the texture is rendered on the inner side | ||
this.scene.add(this.mesh); | ||
this.imgLoader.addEventListener('done', this.loader_onDone); | ||
this.showLoader(); | ||
}; // proto.initCube = function(imgUrl) {...} | ||
var geometry = new _three.SphereGeometry(speherRadius, sphere_H_segments, sphere_V_segments); | ||
proto.loadTiles = function () { | ||
// check if a special UV mapping function should be used | ||
if (this.config.uvMapper) { | ||
this.config.uvMapper(geometry); | ||
} | ||
var self = this; | ||
var loadCounter = 0; | ||
var tiles = this.config.tiles; | ||
var image_placeholder = document.createElement('canvas'); | ||
this.sphere = new _three.Mesh(geometry, new _three.MeshBasicMaterial({ | ||
map: this.imgLoader.load(imageUrls), | ||
side: _three.FrontSide // displaying the texture on the outer side of the sphere | ||
})); | ||
// the order of faces in the following array is IMPORTANT | ||
var materials = ['right', 'left', 'top', 'bottom', 'back', 'front'].map(function (key) { | ||
var img = new Image(), | ||
texture = new _three.Texture(image_placeholder); | ||
this.sphere.scale.x = -1; // flipping sphere inside-out - not the texture is rendered on the inner side | ||
this.scene.add(this.sphere); | ||
img.onload = function () { | ||
console.log(tiles[key]); | ||
texture.image = img; | ||
texture.needsUpdate = true; | ||
this.showLoader(); | ||
if (++loadCounter === 6) { | ||
self.hideLoader(); | ||
} | ||
}; | ||
img.src = tiles[key]; | ||
return new _three.MeshBasicMaterial({ | ||
map: texture | ||
}); | ||
}); | ||
return materials; | ||
}; // proto.loadTiles = function() {...} | ||
proto.loadAtlas = function (imgUrl, materials, canvases) { | ||
var self = this; | ||
var imageObj = new Image(); | ||
var canvases = [0, 1, 2, 3, 4, 5].map(function (el) { | ||
return document.createElement("canvas"); | ||
}); | ||
var materials = canvases.map(function (canvas) { | ||
return new _three.MeshBasicMaterial({ | ||
map: new _three.Texture(canvas) | ||
}); | ||
}); | ||
var tile2canvasIx = { | ||
right: 0, | ||
left: 1, | ||
top: 2, | ||
bottom: 3, | ||
front: 4, | ||
back: 5 | ||
}; | ||
// if the property is not set, then set the default order | ||
var tileOrder = this.config.tileOrder || ['right', 'left', 'top', 'bottom', 'front', 'back']; | ||
// this needs to be set in order not to get "Tainted canvases may not be loaded." WebGL error | ||
imageObj.crossOrigin = "anonymous"; | ||
imageObj.onload = function () { | ||
var tileWidth = imageObj.height; | ||
tileOrder.forEach(function (key) { | ||
var ix = tile2canvasIx[key]; | ||
var canvas = canvases[ix]; | ||
canvas.height = tileWidth; | ||
canvas.width = tileWidth; | ||
var context = canvas.getContext('2d'); | ||
context.drawImage(imageObj, tileWidth * ix, 0, tileWidth, tileWidth, 0, 0, tileWidth, tileWidth); | ||
materials[ix].map.needsUpdate = true; | ||
}); | ||
self.hideLoader(); | ||
}; // imgObj.onload = function() {...} | ||
imageObj.src = this.config.atlas; | ||
return materials; | ||
}; // proto.loadAtlas = function() {...} | ||
proto.loadEqui = function () { | ||
var self = this; | ||
var imgObj = new Image(); | ||
var canvases = [0, 1, 2, 3, 4, 5].map(function (el) { | ||
return document.createElement("canvas"); | ||
}); | ||
var materials = canvases.map(function (canvas) { | ||
return new _three.MeshBasicMaterial({ | ||
map: new _three.Texture(canvas) | ||
}); | ||
}); | ||
// this needs to be sit in order not to get "Tainted canvases may not be loaded." WebGL error | ||
imgObj.crossOrigin = "anonymous"; | ||
imgObj.onload = function () { | ||
var srcWidth = imgObj.width, | ||
srcHeight = imgObj.height; | ||
// (3) when the image is loaded, start the conversion | ||
var inCanvas = document.createElement('canvas'); | ||
inCanvas.width = srcWidth; | ||
inCanvas.height = srcHeight; | ||
var inCtx = inCanvas.getContext("2d"); | ||
inCtx.drawImage(imgObj, 0, 0); | ||
var srcImg = inCtx.getImageData(0, 0, srcWidth, srcHeight); | ||
self.equi2recti(srcImg, materials, canvases); | ||
}; // imgObj.onload = function() {...} | ||
// (2) start loading the image | ||
imgObj.src = this.config.sphere; | ||
return materials; | ||
}; // proto.loadEqui = function() {...} | ||
proto.equi2recti = function (srcImg, materials, canvases) { | ||
var self = this, | ||
faceSize = srcImg.width / 4; | ||
var imgOut = new ImageData(faceSize, faceSize); | ||
var tileIx2canvasIx = { | ||
0: 5, // back | ||
1: 1, // left | ||
2: 4, // front | ||
3: 0, // right | ||
4: 2, // top | ||
5: 3 // bottom | ||
}; | ||
var loadCounter = 0; | ||
var onWorkerMessage = function onWorkerMessage(event) { | ||
// (4) as each image is converted apply it to canvas used as texture | ||
var faceIx = event.data.faceIx, | ||
canvasIx = tileIx2canvasIx[faceIx], | ||
oneCanvas = canvases[canvasIx]; | ||
oneCanvas.width = faceSize; | ||
oneCanvas.height = faceSize; | ||
oneCanvas.getContext("2d").putImageData(event.data.imgData, 0, 0); | ||
materials[canvasIx].map.needsUpdate = true; | ||
if (++loadCounter === 6) { | ||
self.hideLoader(); | ||
} | ||
}; | ||
if (self.config.multiWorker) { | ||
for (var i = 0; i < 6; i++) { | ||
var w = new Worker("../src/equi2recti-worker.js"); | ||
w.onmessage = onWorkerMessage; | ||
// begin converting the images | ||
w.postMessage({ | ||
srcImg: srcImg, | ||
imgOut: imgOut, | ||
faceIx: i | ||
}); | ||
} | ||
} else { | ||
var w = new Worker("../src/equi2recti-worker.js"); | ||
w.onmessage = onWorkerMessage; | ||
// begin converting the images | ||
w.postMessage({ | ||
srcImg: srcImg, | ||
imgOut: imgOut | ||
}); | ||
} | ||
}; // proto.equi2recti = function(srcImg, materials, canvases) {...} | ||
proto.initSphere = function () { | ||
var speherRadius = 100, | ||
sphere_H_segments = 64, | ||
sphere_V_segments = 64; | ||
this.imgLoader = new _progressiveImgLoader.ProgressiveImgLoader(); | ||
this.loader_onDone = this.loader_onDone.bind(this); | ||
this.imgLoader.addEventListener('done', this.loader_onDone); | ||
var geometry = new _three.SphereGeometry(speherRadius, sphere_H_segments, sphere_V_segments); | ||
// check if a special UV mapping function should be used | ||
if (this.config.uvMapper) { | ||
this.config.uvMapper(geometry); | ||
} | ||
this.mesh = new _three.Mesh(geometry, new _three.MeshBasicMaterial({ | ||
map: this.imgLoader.load(this.config.sphere), | ||
side: _three.FrontSide // displaying the texture on the outer side of the sphere | ||
})); | ||
this.mesh.scale.x = -1; // flipping sphere inside-out - not the texture is rendered on the inner side | ||
this.scene.add(this.mesh); | ||
this.showLoader(); | ||
}; // proto.initSphere = function(imageUrls) {...} | ||
@@ -816,20 +1043,20 @@ | ||
var texLoader = new _three.TextureLoader(), | ||
self = this; | ||
var texLoader = new _three.TextureLoader(), | ||
self = this; | ||
texLoader.crossOrigin = ''; | ||
texLoader.crossOrigin = ''; | ||
texLoader.load(logoUrl, function (texture) { | ||
self.logo = new _three.Mesh(new _three.PlaneGeometry(10, 10), new _three.MeshBasicMaterial({ | ||
map: texture, | ||
side: _three.FrontSide, | ||
transparent: true, | ||
opacity: 1 | ||
})); | ||
texLoader.load(logoUrl, function (texture) { | ||
self.logo = new _three.Mesh(new _three.PlaneGeometry(10, 10), new _three.MeshBasicMaterial({ | ||
map: texture, | ||
side: _three.FrontSide, | ||
transparent: true, | ||
opacity: 1 | ||
})); | ||
self.logo.position.set(0, logoDistance, 0); | ||
self.logo.rotation.x = -Math.PI / 2; | ||
self.logo.position.set(0, logoDistance, 0); | ||
self.logo.rotation.x = -Math.PI / 2; | ||
self.scene.add(self.logo); | ||
}); | ||
self.scene.add(self.logo); | ||
}); | ||
}; // proto.initLogo = function(imageUrls) {...} | ||
@@ -845,20 +1072,20 @@ | ||
var texLoader = new _three.TextureLoader(), | ||
self = this; | ||
var texLoader = new _three.TextureLoader(), | ||
self = this; | ||
texLoader.crossOrigin = ''; | ||
texLoader.crossOrigin = ''; | ||
texLoader.load(hintUrl, function (texture) { | ||
self.hint = new _three.Mesh(new _three.PlaneGeometry(10, 10), new _three.MeshBasicMaterial({ | ||
map: texture, | ||
side: _three.FrontSide, | ||
transparent: true, | ||
opacity: 1 | ||
})); | ||
texLoader.load(hintUrl, function (texture) { | ||
self.hint = new _three.Mesh(new _three.PlaneGeometry(10, 10), new _three.MeshBasicMaterial({ | ||
map: texture, | ||
side: _three.FrontSide, | ||
transparent: true, | ||
opacity: 1 | ||
})); | ||
self.hint.position.set(0, 0, -30); | ||
// self.hint.rotation.x = -Math.PI/4; | ||
self.hint.position.set(0, 0, -30); | ||
// self.hint.rotation.x = -Math.PI/4; | ||
self.camera.add(self.hint); | ||
}); | ||
self.camera.add(self.hint); | ||
}); | ||
}; // proto.showHint = function(imageUrls) {...} | ||
@@ -870,24 +1097,24 @@ | ||
proto.hideHint = function () { | ||
if (this.hint) { | ||
this.camera.remove(this.hint); | ||
this.hint = null; | ||
} | ||
if (this.hint) { | ||
this.camera.remove(this.hint); | ||
this.hint = null; | ||
} | ||
}; | ||
proto.initControls = function () { | ||
this.controls = new _sphereControls.SphereControls(this.camera, this.renderer.domElement, this.config.control); | ||
this.controls_onTap = this.controls_onTap.bind(this); | ||
this.controls.addEventListener('tap', this.controls_onTap); | ||
this.controls = new _sphereControls.SphereControls(this.camera, this.renderer.domElement, this.config.control); | ||
this.controls_onTap = this.controls_onTap.bind(this); | ||
this.controls.addEventListener('tap', this.controls_onTap); | ||
}; // proto.initControls = function() {...} | ||
proto.onResize = function (ev) { | ||
var width = this.container.offsetWidth; | ||
var height = this.container.offsetHeight; | ||
var width = this.container.offsetWidth; | ||
var height = this.container.offsetHeight; | ||
if (this.camera) { | ||
this.camera.aspect = width / height; | ||
this.camera.updateProjectionMatrix(); | ||
} | ||
if (this.camera) { | ||
this.camera.aspect = width / height; | ||
this.camera.updateProjectionMatrix(); | ||
} | ||
this.renderer.setSize(width, height); | ||
this.renderer.setSize(width, height); | ||
}; // proto.onResize = function(ev) {...} | ||
@@ -897,37 +1124,37 @@ | ||
if (this.isDisposed) { | ||
return; | ||
} | ||
if (this.isDisposed) { | ||
return; | ||
} | ||
requestAnimationFrame(this.render.bind(this)); | ||
requestAnimationFrame(this.render.bind(this)); | ||
this.dispatchEvent({ type: 'preRender', original: event }); | ||
this.dispatchEvent({ type: 'preRender', original: event }); | ||
if (this.controls) { | ||
this.controls.update(); | ||
} | ||
if (this.controls) { | ||
this.controls.update(); | ||
} | ||
if (this.spinLoader) { | ||
this.spinLoader.animate(); | ||
} | ||
if (this.spinLoader) { | ||
this.spinLoader.animate(); | ||
} | ||
this.renderer.render(this.scene, this.camera); | ||
this.renderer.render(this.scene, this.camera); | ||
}; // proto.render = function() {...} | ||
proto.showLoader = function () { | ||
this.spinLoader = new _ballSpinnerLoader.BallSpinnerLoader(this.config.spinner); | ||
this.camera.add(this.spinLoader.mesh); | ||
this.spinLoader.mesh.position.set(0, 0, -50); | ||
this.spinLoader = new _ballSpinnerLoader.BallSpinnerLoader(this.config.spinner); | ||
this.camera.add(this.spinLoader.mesh); | ||
this.spinLoader.mesh.position.set(0, 0, -50); | ||
}; // proto.showLoader = function() {...} | ||
proto.hideLoader = function () { | ||
if (this.spinLoader) { | ||
this.camera.remove(this.spinLoader.mesh); | ||
this.spinLoader = null; | ||
} | ||
if (this.spinLoader) { | ||
this.camera.remove(this.spinLoader.mesh); | ||
this.spinLoader = null; | ||
} | ||
}; // proto.hideLoader = function() { ... } | ||
proto.loader_onDone = function () { | ||
this.loader_onDone = null; // loader mi više nije potreban | ||
this.hideLoader(); | ||
this.loader_onDone = null; // loader mi više nije potreban | ||
this.hideLoader(); | ||
}; | ||
@@ -937,19 +1164,19 @@ | ||
window.removeEventListener('resize', this.onResize); | ||
window.removeEventListener('resize', this.onResize); | ||
if (this.closeButton) { | ||
this.closeButton.removeEventListener('click', this.closeButton_onClick); | ||
} | ||
if (this.closeButton) { | ||
this.closeButton.removeEventListener('click', this.closeButton_onClick); | ||
} | ||
this.controls.removeEventListener('tap', this.controls_onTap); | ||
this.controls.removeEventListener('tap', this.controls_onTap); | ||
this.imgLoader.dispose(); | ||
this.imgLoader.dispose(); | ||
this.isDisposed = true; | ||
this.container.remove(); | ||
this.isDisposed = true; | ||
this.container.remove(); | ||
// restoring original viewport meta | ||
(0, _jquery2.default)('head meta[name="viewport"]').attr('content', this.originalViewPortMeta); | ||
// restoring original viewport meta | ||
(0, _jquery2.default)('head meta[name="viewport"]').attr('content', this.originalViewPortMeta); | ||
this.loaderEl = this.imgLoader = this.closeButton = this.container = this.renderer = this.container = this.camera = this.scene = this.sphere = this.controls = null; | ||
this.loaderEl = this.imgLoader = this.closeButton = this.container = this.renderer = this.container = this.camera = this.scene = this.sphere = this.controls = null; | ||
}; // proto.dispose = function() {...} | ||
@@ -956,0 +1183,0 @@ |
@@ -1,1 +0,1 @@ | ||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("THREE"),require("jquery")):"function"==typeof define&&define.amd?define(["THREE","jquery"],e):"object"==typeof exports?exports.SphereViewer=e(require("THREE"),require("jquery")):t.SphereViewer=e(t.THREE,t.jquery)}(this,function(t,e){return function(t){function e(o){if(i[o])return i[o].exports;var n=i[o]={i:o,l:!1,exports:{}};return t[o].call(n.exports,n,n.exports,e),n.l=!0,n.exports}var i={};return e.m=t,e.c=i,e.i=function(t){return t},e.d=function(t,i,o){e.o(t,i)||Object.defineProperty(t,i,{configurable:!1,enumerable:!0,get:o})},e.n=function(t){var i=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(i,"a",i),i},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=5)}([function(e,i){e.exports=t},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.BallSpinnerLoader=void 0;var o=i(0),n=function(t){t=t||{},this.groupRadius=t.groupRadius||10,this.circleCount=t.circleCount||8,this.circleRadius=t.circleRadius||1,this.groupAngle=0,this.animationAmplitude=t.animationAmplitude||10,this.circles=[],this.mesh=this.initGroup()};n.prototype={makeCircle:function(t){t=t||{};var e=t.radius||5,i=t.segments||16,n=new o.CircleGeometry(e,i),s=new o.MeshBasicMaterial({color:16777215,transparent:!0,opacity:t.opacity,side:o.DoubleSide});return{mesh:new o.Mesh(n,s),opacityStep:t.opacityStep||.01}},addToScene:function(t){t.add(this.mesh)},initGroup:function(){for(var t=new o.Object3D,e=0,i=1/(this.circleCount/2+1),n=.02,s=0,a=2*Math.PI/this.circleCount,r=0;r<this.circleCount;r++){e+=i,e>1&&(e=1-i,i=-i,n=-n);var h=this.makeCircle({opacity:e,opacityStep:n,radius:this.circleRadius}),c=this.polar2cartesian({distance:this.groupRadius,radians:s});h.mesh.position.set(c.x,c.y,e*this.animationAmplitude),s+=a,t.add(h.mesh),this.circles.push(h)}return t},polar2cartesian:function(t){return{x:Math.round(t.distance*Math.cos(t.radians)*1e3)/1e3,y:Math.round(t.distance*Math.sin(t.radians)*1e3)/1e3}},animate:function(){this.mesh.rotation.z+=.02;for(var t=this.circles,e=(this.circleCount,0);e<t.length;e++){var i=t[e],o=i.mesh.material.opacity+i.opacityStep;i.mesh.geometry.radius;o>1?(o=1-i.opacityStep,i.opacityStep=-i.opacityStep):o<0&&(o=i.opacityStep,i.opacityStep=-i.opacityStep),i.mesh.material.opacity=o,i.mesh.position.z=o*this.animationAmplitude}}},e.BallSpinnerLoader=n},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ProgressiveImgLoader=void 0;var o=i(0),n=function(){},s=n.prototype=Object.create(o.EventDispatcher.prototype);s.load=function(t){var e=this,i=new o.Texture,n=e.imageObj=new Image,s=0;return n.crossOrigin="anonymous",n.onload=function(){e.imageObj&&(i.needsUpdate=!0,s<t.length?(e.dispatchEvent({type:"progress",imageIndex:s}),window.setTimeout(function(){n.src=t[s++]},1e3)):(e.dispatchEvent({type:"done"}),e.imageObj=null))},n.src=t[s++],i.image=n,i},s.dispose=function(){this.imageObj&&(this.imageObj.src=""),this.imageObj=null},e.ProgressiveImgLoader=n},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SphereControls=void 0;var o=i(0),n=function(t,e,i){function n(t){u.dispatchEvent({type:"tap",original:t}),t.preventDefault(),m=!0,d(),v.position.lon=o.Math.radToDeg(v.position.theta),v.position.lat=90-o.Math.radToDeg(v.position.phi),f.x=t.clientX,f.y=t.clientY,f.lon=v.position.lon,f.lat=v.position.lat}function s(t){!0===m&&(v.position.lon=.1*(f.x-t.clientX)+f.lon,v.position.lat=.1*(t.clientY-f.y)+f.lat),u.dispatchEvent({type:"mouseMove",original:t})}function a(t){m=!1,t.preventDefault(),l()}function r(e){t.fov+=.05*e.deltaY,t.updateProjectionMatrix()}function h(t){1==t.touches.length&&(m=!0,d(),u.dispatchEvent({type:"tap",original:t}),t.preventDefault(),t.stopPropagation(),f.x=t.touches[0].pageX,f.y=t.touches[0].pageY,v.position.lon=o.Math.radToDeg(v.position.theta),v.position.lat=90-o.Math.radToDeg(v.position.phi),f.lon=v.position.lon,f.lat=v.position.lat)}function c(t){1==t.touches.length&&(t.preventDefault(),t.stopPropagation(),v.position.lon=.1*(f.x-t.touches[0].pageX)+f.lon,v.position.lat=.1*(t.touches[0].pageY-f.y)+f.lat)}function p(t){m=!1,l()}function d(){M.suspended=!0,M.timeout&&window.clearTimeout(M.timeout)}function l(){M.enabled&&(M.timeout=window.setTimeout(function(){M.timeout=null,M.suspended=!1},M.delay))}var u=this;i=i||{},e=void 0!==e?e:document,e.addEventListener("mousedown",n,!1),e.addEventListener("mousemove",s,!1),e.addEventListener("mouseup",a,!1),e.addEventListener("wheel",r,!1),e.addEventListener("touchstart",h,!1),e.addEventListener("touchend",p,!1),e.addEventListener("touchmove",c,!1);var m=!1,f={x:null,y:null,lat:null,lon:null},v={position:{lon:90,lat:0,phi:Math.PI/2,theta:0},time:5},g={position:{phi:v.position.phi,theta:v.position.theta},time2:1},y=new o.Vector3,w={phi:0,theta:0},M={enabled:!!i.autoRotate,suspended:!i.autoRotate,speed:Math.max(0,Math.min(10,i.autoRotateSpeed||1))/1e3*(-1===i.autoRotateDirection?-1:1),delay:Math.max(i.autoRotateDelay||5e3,1e3),timeout:null};this.update=function(){if(m)v.position.lat=Math.max(-85,Math.min(85,v.position.lat)),v.position.phi=o.Math.degToRad(90-v.position.lat),v.position.theta=o.Math.degToRad(v.position.lon),w={phi:v.position.phi-g.position.phi,theta:v.position.theta-g.position.theta},v.time=5,g.time2=1;else{var e=v.time*v.time/60;v.time++,w.phi=w.phi*g.time2/e,w.theta=w.theta*g.time2/e,g.time2=e,M.suspended||(w.theta=M.speed<0?Math.min(w.theta,M.speed):Math.max(w.theta,M.speed)),v.position.phi+=w.phi,v.position.theta+=w.theta,v.position.phi>Math.PI?(v.position.phi=Math.PI,w.phi=-1*w.phi):v.position.phi<0&&(v.position.phi=0,w.phi=-1*w.phi)}g.position.phi=v.position.phi,g.position.theta=v.position.theta,y.x=500*Math.sin(v.position.phi)*Math.cos(v.position.theta),y.y=500*Math.cos(v.position.phi),y.z=500*Math.sin(v.position.phi)*Math.sin(v.position.theta),t.lookAt(y)}};n.prototype=Object.create(o.EventDispatcher.prototype),e.SphereControls=n},function(t,i){t.exports=e},function(t,e,i){"use strict";function o(t,e){this.isDisposed=!1,this.config=e=e||{},this.initViewport(),this.initScene(),this.initSphere(t),this.config.logo&&this.initLogo(this.config.logo,void 0===this.config.logoDistance?-15:this.config.logoDistance),this.config.hint&&this.showHint(this.config.hint),this.initControls(),this.onResize=this.onResize.bind(this),window.addEventListener("resize",this.onResize,!1),window.setTimeout(this.onResize,1),this.render()}Object.defineProperty(e,"__esModule",{value:!0}),e.Viewer=void 0;var n=i(0),s=i(4),a=function(t){return t&&t.__esModule?t:{default:t}}(s),r=i(3),h=i(2),c=i(1),p=o.prototype=Object.create(n.EventDispatcher.prototype);p.initViewport=function(){var t=(window.devicePixelRatio,window.screen.availWidth,1/window.devicePixelRatio),e=(0,a.default)('head meta[name="viewport"]');this.originalViewPortMeta=e.attr("content"),e.attr("content","initial-scale="+t+", maximum-scale="+t+", user-scalable=0");var i=1!==window.devicePixelRatio;this.container=document.createElement("div"),this.container.className="sphere-container "+(i?"isMobile":"isDesktop"),this.config.closeButtonHtml&&(this.closeButton=document.createElement("i"),this.closeButton.innerHTML=this.config.closeButtonHtml,this.container.appendChild(this.closeButton),this.closeButton_onClick=this.closeButton_onClick.bind(this),this.closeButton.addEventListener("click",this.closeButton_onClick)),document.getElementsByTagName("body")[0].appendChild(this.container)},p.closeButton_onClick=function(){this.dispose(),this.dispatchEvent({type:"closed"})},p.controls_onTap=function(t){this.hideHint()},p.initScene=function(){var t=document.getElementsByTagName("body")[0];this.renderer=new n.WebGLRenderer,this.renderer.setSize(t.scrollWidth,t.scrollHeight),this.container.appendChild(this.renderer.domElement),this.scene=new n.Scene;this.camera=new n.PerspectiveCamera(90,1,1,1e3),this.scene.add(this.camera)},p.initSphere=function(t){this.imgLoader=new h.ProgressiveImgLoader,this.loader_onDone=this.loader_onDone.bind(this),this.imgLoader.addEventListener("done",this.loader_onDone);var e=new n.SphereGeometry(100,64,64);this.config.uvMapper&&this.config.uvMapper(e),this.sphere=new n.Mesh(e,new n.MeshBasicMaterial({map:this.imgLoader.load(t),side:n.FrontSide})),this.sphere.scale.x=-1,this.scene.add(this.sphere),this.showLoader()},p.initLogo=function(t,e){var i=new n.TextureLoader,o=this;i.crossOrigin="",i.load(t,function(t){o.logo=new n.Mesh(new n.PlaneGeometry(10,10),new n.MeshBasicMaterial({map:t,side:n.FrontSide,transparent:!0,opacity:1})),o.logo.position.set(0,e,0),o.logo.rotation.x=-Math.PI/2,o.scene.add(o.logo)})},p.showHint=function(t){var e=new n.TextureLoader,i=this;e.crossOrigin="",e.load(t,function(t){i.hint=new n.Mesh(new n.PlaneGeometry(10,10),new n.MeshBasicMaterial({map:t,side:n.FrontSide,transparent:!0,opacity:1})),i.hint.position.set(0,0,-30),i.camera.add(i.hint)})},p.hideHint=function(){this.hint&&(this.camera.remove(this.hint),this.hint=null)},p.initControls=function(){this.controls=new r.SphereControls(this.camera,this.renderer.domElement,this.config.control),this.controls_onTap=this.controls_onTap.bind(this),this.controls.addEventListener("tap",this.controls_onTap)},p.onResize=function(t){var e=this.container.offsetWidth,i=this.container.offsetHeight;this.camera&&(this.camera.aspect=e/i,this.camera.updateProjectionMatrix()),this.renderer.setSize(e,i)},p.render=function(){this.isDisposed||(requestAnimationFrame(this.render.bind(this)),this.dispatchEvent({type:"preRender",original:event}),this.controls&&this.controls.update(),this.spinLoader&&this.spinLoader.animate(),this.renderer.render(this.scene,this.camera))},p.showLoader=function(){this.spinLoader=new c.BallSpinnerLoader(this.config.spinner),this.camera.add(this.spinLoader.mesh),this.spinLoader.mesh.position.set(0,0,-50)},p.hideLoader=function(){this.spinLoader&&(this.camera.remove(this.spinLoader.mesh),this.spinLoader=null)},p.loader_onDone=function(){this.loader_onDone=null,this.hideLoader()},p.dispose=function(){window.removeEventListener("resize",this.onResize),this.closeButton&&this.closeButton.removeEventListener("click",this.closeButton_onClick),this.controls.removeEventListener("tap",this.controls_onTap),this.imgLoader.dispose(),this.isDisposed=!0,this.container.remove(),(0,a.default)('head meta[name="viewport"]').attr("content",this.originalViewPortMeta),this.loaderEl=this.imgLoader=this.closeButton=this.container=this.renderer=this.container=this.camera=this.scene=this.sphere=this.controls=null},e.Viewer=o}])}); | ||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("THREE"),require("$")):"function"==typeof define&&define.amd?define(["THREE","$"],e):"object"==typeof exports?exports.SphereViewer=e(require("THREE"),require("$")):t.SphereViewer=e(t.THREE,t.$)}(this,function(t,e){return function(t){function e(o){if(i[o])return i[o].exports;var n=i[o]={i:o,l:!1,exports:{}};return t[o].call(n.exports,n,n.exports,e),n.l=!0,n.exports}var i={};return e.m=t,e.c=i,e.i=function(t){return t},e.d=function(t,i,o){e.o(t,i)||Object.defineProperty(t,i,{configurable:!1,enumerable:!0,get:o})},e.n=function(t){var i=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(i,"a",i),i},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=5)}([function(e,i){e.exports=t},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.BallSpinnerLoader=void 0;var o=i(0),n=function(t){t=t||{},this.groupRadius=t.groupRadius||10,this.circleCount=t.circleCount||8,this.circleRadius=t.circleRadius||1,this.groupAngle=0,this.animationAmplitude=t.animationAmplitude||10,this.circles=[],this.mesh=this.initGroup()};n.prototype={makeCircle:function(t){t=t||{};var e=t.radius||5,i=t.segments||16,n=new o.CircleGeometry(e,i),s=new o.MeshBasicMaterial({color:16777215,transparent:!0,opacity:t.opacity,side:o.DoubleSide});return{mesh:new o.Mesh(n,s),opacityStep:t.opacityStep||.01}},addToScene:function(t){t.add(this.mesh)},initGroup:function(){for(var t=new o.Object3D,e=0,i=1/(this.circleCount/2+1),n=.02,s=0,a=2*Math.PI/this.circleCount,r=0;r<this.circleCount;r++){e+=i,e>1&&(e=1-i,i=-i,n=-n);var h=this.makeCircle({opacity:e,opacityStep:n,radius:this.circleRadius}),c=this.polar2cartesian({distance:this.groupRadius,radians:s});h.mesh.position.set(c.x,c.y,e*this.animationAmplitude),s+=a,t.add(h.mesh),this.circles.push(h)}return t},polar2cartesian:function(t){return{x:Math.round(t.distance*Math.cos(t.radians)*1e3)/1e3,y:Math.round(t.distance*Math.sin(t.radians)*1e3)/1e3}},animate:function(){this.mesh.rotation.z+=.02;for(var t=this.circles,e=(this.circleCount,0);e<t.length;e++){var i=t[e],o=i.mesh.material.opacity+i.opacityStep;i.mesh.geometry.radius;o>1?(o=1-i.opacityStep,i.opacityStep=-i.opacityStep):o<0&&(o=i.opacityStep,i.opacityStep=-i.opacityStep),i.mesh.material.opacity=o,i.mesh.position.z=o*this.animationAmplitude}}},e.BallSpinnerLoader=n},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ProgressiveImgLoader=void 0;var o=i(0),n=function(){},s=n.prototype=Object.create(o.EventDispatcher.prototype);s.load=function(t){var e=this,i=new o.Texture,n=e.imageObj=new Image,s=0;return n.crossOrigin="anonymous",n.onload=function(){e.imageObj&&(i.needsUpdate=!0,s<t.length?(e.dispatchEvent({type:"progress",imageIndex:s}),window.setTimeout(function(){n.src=t[s++]},1e3)):(e.dispatchEvent({type:"done"}),e.imageObj=null))},n.src=t[s++],i.image=n,i},s.dispose=function(){this.imageObj&&(this.imageObj.src=""),this.imageObj=null},e.ProgressiveImgLoader=n},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.SphereControls=void 0;var o=i(0),n=function(t,e,i){function n(t){u.dispatchEvent({type:"tap",original:t}),t.preventDefault(),m=!0,d(),g.position.lon=o.Math.radToDeg(g.position.theta),g.position.lat=90-o.Math.radToDeg(g.position.phi),f.x=t.clientX,f.y=t.clientY,f.lon=g.position.lon,f.lat=g.position.lat}function s(t){!0===m&&(g.position.lon=.1*(f.x-t.clientX)+f.lon,g.position.lat=.1*(t.clientY-f.y)+f.lat),u.dispatchEvent({type:"mouseMove",original:t})}function a(t){m=!1,t.preventDefault(),l()}function r(e){t.fov+=.05*e.deltaY,t.updateProjectionMatrix()}function h(t){1==t.touches.length&&(m=!0,d(),u.dispatchEvent({type:"tap",original:t}),t.preventDefault(),t.stopPropagation(),f.x=t.touches[0].pageX,f.y=t.touches[0].pageY,g.position.lon=o.Math.radToDeg(g.position.theta),g.position.lat=90-o.Math.radToDeg(g.position.phi),f.lon=g.position.lon,f.lat=g.position.lat)}function c(t){1==t.touches.length&&(t.preventDefault(),t.stopPropagation(),g.position.lon=.1*(f.x-t.touches[0].pageX)+f.lon,g.position.lat=.1*(t.touches[0].pageY-f.y)+f.lat)}function p(t){m=!1,l()}function d(){M.suspended=!0,M.timeout&&window.clearTimeout(M.timeout)}function l(){M.enabled&&(M.timeout=window.setTimeout(function(){M.timeout=null,M.suspended=!1},M.delay))}var u=this;i=i||{},e=void 0!==e?e:document,e.addEventListener("mousedown",n,!1),e.addEventListener("mousemove",s,!1),e.addEventListener("mouseup",a,!1),e.addEventListener("wheel",r,!1),e.addEventListener("touchstart",h,!1),e.addEventListener("touchend",p,!1),e.addEventListener("touchmove",c,!1);var m=!1,f={x:null,y:null,lat:null,lon:null},g={position:{lon:90,lat:0,phi:Math.PI/2,theta:0},time:5},v={position:{phi:g.position.phi,theta:g.position.theta},time2:1},w=new o.Vector3,y={phi:0,theta:0},M={enabled:!!i.autoRotate,suspended:!i.autoRotate,speed:Math.max(0,Math.min(10,i.autoRotateSpeed||1))/1e3*(-1===i.autoRotateDirection?-1:1),delay:Math.max(i.autoRotateDelay||5e3,1e3),timeout:null};this.update=function(){if(m)g.position.lat=Math.max(-85,Math.min(85,g.position.lat)),g.position.phi=o.Math.degToRad(90-g.position.lat),g.position.theta=o.Math.degToRad(g.position.lon),y={phi:g.position.phi-v.position.phi,theta:g.position.theta-v.position.theta},g.time=5,v.time2=1;else{var e=g.time*g.time/60;g.time++,y.phi=y.phi*v.time2/e,y.theta=y.theta*v.time2/e,v.time2=e,M.suspended||(y.theta=M.speed<0?Math.min(y.theta,M.speed):Math.max(y.theta,M.speed)),g.position.phi+=y.phi,g.position.theta+=y.theta,g.position.phi>Math.PI?(g.position.phi=Math.PI,y.phi=-1*y.phi):g.position.phi<0&&(g.position.phi=0,y.phi=-1*y.phi)}v.position.phi=g.position.phi,v.position.theta=g.position.theta,w.x=500*Math.sin(g.position.phi)*Math.cos(g.position.theta),w.y=500*Math.cos(g.position.phi),w.z=500*Math.sin(g.position.phi)*Math.sin(g.position.theta),t.lookAt(w)}};n.prototype=Object.create(o.EventDispatcher.prototype),e.SphereControls=n},function(t,i){t.exports=e},function(t,e,i){"use strict";function o(t){this.isDisposed=!1,this.config=t=t||{},this.initViewport(),this.initScene(),this.config.sphere&&!this.config.forceCube?this.initSphere():this.initCube(),this.config.logo&&this.initLogo(this.config.logo,void 0===this.config.logoDistance?-15:this.config.logoDistance),this.config.hint&&this.showHint(this.config.hint),this.initControls(),this.onResize=this.onResize.bind(this),window.addEventListener("resize",this.onResize,!1),window.setTimeout(this.onResize,1),this.render()}Object.defineProperty(e,"__esModule",{value:!0}),e.Viewer=void 0;var n=i(0),s=i(4),a=function(t){return t&&t.__esModule?t:{default:t}}(s),r=i(3),h=i(2),c=i(1),p=o.prototype=Object.create(n.EventDispatcher.prototype);p.initViewport=function(){var t=(window.devicePixelRatio,window.screen.availWidth,1/window.devicePixelRatio),e=(0,a.default)('head meta[name="viewport"]');this.originalViewPortMeta=e.attr("content"),e.attr("content","initial-scale="+t+", maximum-scale="+t+", user-scalable=0");var i=1!==window.devicePixelRatio;this.container=document.createElement("div"),this.container.className="sphere-container "+(i?"isMobile":"isDesktop"),this.config.closeButtonHtml&&(this.closeButton=document.createElement("i"),this.closeButton.innerHTML=this.config.closeButtonHtml,this.container.appendChild(this.closeButton),this.closeButton_onClick=this.closeButton_onClick.bind(this),this.closeButton.addEventListener("click",this.closeButton_onClick)),document.getElementsByTagName("body")[0].appendChild(this.container)},p.closeButton_onClick=function(){this.dispose(),this.dispatchEvent({type:"closed"})},p.controls_onTap=function(t){this.hideHint()},p.initScene=function(){var t=document.getElementsByTagName("body")[0];this.renderer=new n.WebGLRenderer,this.renderer.setSize(t.scrollWidth,t.scrollHeight),this.container.appendChild(this.renderer.domElement),this.scene=new n.Scene;this.camera=new n.PerspectiveCamera(90,1,1,1e3),this.scene.add(this.camera)},p.initCube=function(t){var e;this.config.sphere?e=this.loadEqui():this.config.tiles?e=this.loadTiles():this.config.atlas&&(e=this.loadAtlas()),this.mesh=new n.Mesh(new n.BoxGeometry(100,100,100),e),this.mesh.scale.x=-1,this.scene.add(this.mesh),this.showLoader()},p.loadTiles=function(){var t=this,e=0,i=this.config.tiles,o=document.createElement("canvas");return["right","left","top","bottom","back","front"].map(function(s){var a=new Image,r=new n.Texture(o);return a.onload=function(){console.log(i[s]),r.image=a,r.needsUpdate=!0,6==++e&&t.hideLoader()},a.src=i[s],new n.MeshBasicMaterial({map:r})})},p.loadAtlas=function(t,e,i){var o=this,s=new Image,i=[0,1,2,3,4,5].map(function(t){return document.createElement("canvas")}),e=i.map(function(t){return new n.MeshBasicMaterial({map:new n.Texture(t)})}),a={right:0,left:1,top:2,bottom:3,front:4,back:5},r=this.config.tileOrder||["right","left","top","bottom","front","back"];return s.crossOrigin="anonymous",s.onload=function(){var t=s.height;r.forEach(function(o){var n=a[o],r=i[n];r.height=t,r.width=t,r.getContext("2d").drawImage(s,t*n,0,t,t,0,0,t,t),e[n].map.needsUpdate=!0}),o.hideLoader()},s.src=this.config.atlas,e},p.loadEqui=function(){var t=this,e=new Image,i=[0,1,2,3,4,5].map(function(t){return document.createElement("canvas")}),o=i.map(function(t){return new n.MeshBasicMaterial({map:new n.Texture(t)})});return e.crossOrigin="anonymous",e.onload=function(){var n=e.width,s=e.height,a=document.createElement("canvas");a.width=n,a.height=s;var r=a.getContext("2d");r.drawImage(e,0,0);var h=r.getImageData(0,0,n,s);t.equi2recti(h,o,i)},e.src=this.config.sphere,o},p.equi2recti=function(t,e,i){var o=this,n=t.width/4,s=new ImageData(n,n),a={0:5,1:1,2:4,3:0,4:2,5:3},r=0,h=function(t){var s=t.data.faceIx,h=a[s],c=i[h];c.width=n,c.height=n,c.getContext("2d").putImageData(t.data.imgData,0,0),e[h].map.needsUpdate=!0,6==++r&&o.hideLoader()};if(o.config.multiWorker)for(var c=0;c<6;c++){var p=new Worker("../src/equi2recti-worker.js");p.onmessage=h,p.postMessage({srcImg:t,imgOut:s,faceIx:c})}else{var p=new Worker("../src/equi2recti-worker.js");p.onmessage=h,p.postMessage({srcImg:t,imgOut:s})}},p.initSphere=function(){this.imgLoader=new h.ProgressiveImgLoader,this.loader_onDone=this.loader_onDone.bind(this),this.imgLoader.addEventListener("done",this.loader_onDone);var t=new n.SphereGeometry(100,64,64);this.config.uvMapper&&this.config.uvMapper(t),this.mesh=new n.Mesh(t,new n.MeshBasicMaterial({map:this.imgLoader.load(this.config.sphere),side:n.FrontSide})),this.mesh.scale.x=-1,this.scene.add(this.mesh),this.showLoader()},p.initLogo=function(t,e){var i=new n.TextureLoader,o=this;i.crossOrigin="",i.load(t,function(t){o.logo=new n.Mesh(new n.PlaneGeometry(10,10),new n.MeshBasicMaterial({map:t,side:n.FrontSide,transparent:!0,opacity:1})),o.logo.position.set(0,e,0),o.logo.rotation.x=-Math.PI/2,o.scene.add(o.logo)})},p.showHint=function(t){var e=new n.TextureLoader,i=this;e.crossOrigin="",e.load(t,function(t){i.hint=new n.Mesh(new n.PlaneGeometry(10,10),new n.MeshBasicMaterial({map:t,side:n.FrontSide,transparent:!0,opacity:1})),i.hint.position.set(0,0,-30),i.camera.add(i.hint)})},p.hideHint=function(){this.hint&&(this.camera.remove(this.hint),this.hint=null)},p.initControls=function(){this.controls=new r.SphereControls(this.camera,this.renderer.domElement,this.config.control),this.controls_onTap=this.controls_onTap.bind(this),this.controls.addEventListener("tap",this.controls_onTap)},p.onResize=function(t){var e=this.container.offsetWidth,i=this.container.offsetHeight;this.camera&&(this.camera.aspect=e/i,this.camera.updateProjectionMatrix()),this.renderer.setSize(e,i)},p.render=function(){this.isDisposed||(requestAnimationFrame(this.render.bind(this)),this.dispatchEvent({type:"preRender",original:event}),this.controls&&this.controls.update(),this.spinLoader&&this.spinLoader.animate(),this.renderer.render(this.scene,this.camera))},p.showLoader=function(){this.spinLoader=new c.BallSpinnerLoader(this.config.spinner),this.camera.add(this.spinLoader.mesh),this.spinLoader.mesh.position.set(0,0,-50)},p.hideLoader=function(){this.spinLoader&&(this.camera.remove(this.spinLoader.mesh),this.spinLoader=null)},p.loader_onDone=function(){this.loader_onDone=null,this.hideLoader()},p.dispose=function(){window.removeEventListener("resize",this.onResize),this.closeButton&&this.closeButton.removeEventListener("click",this.closeButton_onClick),this.controls.removeEventListener("tap",this.controls_onTap),this.imgLoader.dispose(),this.isDisposed=!0,this.container.remove(),(0,a.default)('head meta[name="viewport"]').attr("content",this.originalViewPortMeta),this.loaderEl=this.imgLoader=this.closeButton=this.container=this.renderer=this.container=this.camera=this.scene=this.sphere=this.controls=null},e.Viewer=o}])}); |
{ | ||
"name": "sphere-viewer", | ||
"version": "1.0.7", | ||
"version": "1.1.0", | ||
"description": "A simple JavaScript library for displaying spherical images on desktop and mobile browsers", | ||
@@ -32,6 +32,8 @@ "main": "dist/sphere-viewer.js", | ||
"babel-preset-env": "^1.3.2", | ||
"jquery": "^3.2.1", | ||
"jquery-slim": "^3.0.0", | ||
"three": "^0.84.0", | ||
"three": "^0.85.2", | ||
"three-canvas-renderer": "^1.0.1", | ||
"webpack": "^2.3.3" | ||
} | ||
} |
@@ -11,5 +11,8 @@ # SphereViewer.js | ||
* can display user instructions (PNG image) | ||
* configurable | ||
* supports vanilla JavaScript and AMD | ||
* supports UV mapping customization | ||
* texture can be provided in three different formats | ||
* as spherical image as produced by Ricoh Theta/Google Street View (equirectangular projection) | ||
* as serie of separate tile images (rectilinear projection)s | ||
* as tile atlas (single image containing all the images) | ||
@@ -20,3 +23,3 @@ ## Live Demo | ||
## Documentation | ||
There is none ... you can figure it out from example provided below and [live example at CodePen](http://codepen.io/knee-cola/pen/vxQYNL) | ||
There is none ... you can figure it out from provided example files in the **examples** folder. The code inside the HTML files is well documented. | ||
@@ -33,4 +36,4 @@ ## Installation | ||
<script src="//code.jquery.com/jquery-3.2.1.slim.js"></script> | ||
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/three.js/84/three.min.js"></script> | ||
<script type="text/javascript" src="//cdn.rawgit.com/knee-cola/SphereViewer/b2a8adf3/dist/sphereViewer.min.js"></script> | ||
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/three.js/85/three.min.js"></script> | ||
<script type="text/javascript" src="https://cdn.rawgit.com/knee-cola/SphereViewer/aea7cb88/dist/sphereViewer.min.js"></script> | ||
``` | ||
@@ -49,5 +52,9 @@ If you want to store files localy on yout server, you can download the minified file from [GitHub repository](https://github.com/knee-cola/SphereViewer/blob/master/dist/sphereViewer.min.js). | ||
var config = { | ||
// providing multiple images for the pre-loader | ||
sphere: ['img/sphere/preloader.jpg', 'img/sphere/hd.jpg'], | ||
// (if set) the logo will be displayed at the bottom | ||
// of the sphere, which is usefull for hiding the triopod | ||
logo:'img/logo.png', | ||
// (if set) the usage hint is displayed in the center of the screen | ||
@@ -81,7 +88,5 @@ // and is hidden after the user clicks/taps the screen | ||
var picUrls = ['img/sphere/preloader.jpg', 'img/sphere/hd.jpg'] | ||
// creating a new instance of the viewer | ||
// ... the viewer will automaticall be appended to <body> and displayed | ||
var viewer = new SphereViewer.Viewer(picUrls, controlConfig); | ||
var viewer = new SphereViewer.Viewer(config); | ||
@@ -88,0 +93,0 @@ // adding event handlers: |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
@@ -15,6 +15,11 @@ /** | ||
TextureLoader as THREE_TextureLoader, | ||
Texture as THREE_Texture, | ||
PlaneGeometry as THREE_PlaneGeometry, | ||
BoxGeometry as THREE_BoxGeometry, | ||
DoubleSide as THREE_DoubleSide, | ||
FrontSide as THREE_FrontSide, | ||
BackSide as THREE_BackSide | ||
BackSide as THREE_BackSide, | ||
Matrix4 as THREE_Matrix4 | ||
} from 'three' | ||
import $ from 'jquery' | ||
@@ -26,29 +31,38 @@ | ||
function SphereViewer(imageUrls, config) { | ||
function SphereViewer(config) { | ||
this.isDisposed = false; | ||
this.config = config = config || {}; | ||
this.isDisposed = false; | ||
this.config = config = config || {}; | ||
this.initViewport(); | ||
this.initScene(); | ||
this.initSphere(imageUrls); | ||
this.initViewport(); | ||
this.initScene(); | ||
if(this.config.sphere && !this.config.forceCube) { | ||
// IF image URLs are provided via a "sphere" param | ||
// AND cube geometry is not forced | ||
// > apply texture onto a sphere | ||
this.initSphere(); | ||
} else { | ||
// ELSE apply texture onto a cube/box | ||
this.initCube(); | ||
} | ||
if(this.config.logo) { | ||
this.initLogo(this.config.logo, this.config.logoDistance===void 0 ? -15 : this.config.logoDistance); | ||
} | ||
if(this.config.logo) { | ||
this.initLogo(this.config.logo, this.config.logoDistance===void 0 ? -15 : this.config.logoDistance); | ||
} | ||
if(this.config.hint) { | ||
this.showHint(this.config.hint); | ||
} | ||
if(this.config.hint) { | ||
this.showHint(this.config.hint); | ||
} | ||
this.initControls(); | ||
this.initControls(); | ||
// attaching a bound version of the method to the instance | ||
// > we'll need it to remove event listener | ||
this.onResize = this.onResize.bind(this); | ||
// attaching a bound version of the method to the instance | ||
// > we'll need it to remove event listener | ||
this.onResize = this.onResize.bind(this); | ||
window.addEventListener('resize', this.onResize, false); | ||
window.setTimeout(this.onResize, 1); | ||
window.addEventListener('resize', this.onResize, false); | ||
window.setTimeout(this.onResize, 1); | ||
this.render(); | ||
this.render(); | ||
}; | ||
@@ -117,4 +131,234 @@ | ||
proto.initSphere = function(imageUrls) { | ||
proto.initCube = function(imgUrl) { | ||
var cubeSize = 100, | ||
materials; | ||
if(this.config.sphere) { | ||
// IF a sphereicaql image is to be used | ||
// > convert it from spherical projection (equirectangulat) | ||
// to cubical projection (rectilinear) | ||
materials = this.loadEqui(); | ||
} else if(this.config.tiles) { | ||
// ELSE IF the texture is proveded as separate tiles | ||
// > load each tile separatley | ||
materials = this.loadTiles(); | ||
} else if(this.config.atlas) { | ||
// ELSE IF the texture is provided as a single Atlas image file | ||
// containing all the tiles | ||
// > load the atlas file and split it into tiles | ||
materials = this.loadAtlas(); | ||
} | ||
this.mesh = new THREE_Mesh( new THREE_BoxGeometry( cubeSize, cubeSize, cubeSize ), materials ); | ||
this.mesh.scale.x = -1; // flipping sphere inside-out - not the texture is rendered on the inner side | ||
this.scene.add(this.mesh); | ||
this.showLoader(); | ||
}; // proto.initCube = function(imgUrl) {...} | ||
proto.loadTiles = function() { | ||
var self = this; | ||
var loadCounter=0; | ||
var tiles = this.config.tiles; | ||
var image_placeholder = document.createElement( 'canvas' ); | ||
// the order of faces in the following array is IMPORTANT | ||
var materials = [ | ||
'right', | ||
'left', | ||
'top', | ||
'bottom', | ||
'back', | ||
'front', | ||
].map(function(key) { | ||
var img = new Image(), | ||
texture = new THREE_Texture(image_placeholder); | ||
img.onload = function() { | ||
console.log(tiles[key]); | ||
texture.image = img; | ||
texture.needsUpdate = true; | ||
if(++loadCounter===6) { | ||
self.hideLoader(); | ||
} | ||
}; | ||
img.src = tiles[key]; | ||
return(new THREE_MeshBasicMaterial({ | ||
map: texture | ||
})); | ||
}); | ||
return(materials); | ||
}; // proto.loadTiles = function() {...} | ||
proto.loadAtlas = function(imgUrl, materials, canvases) { | ||
var self = this; | ||
var imageObj=new Image(); | ||
var canvases = [0,1,2,3,4,5].map(function(el) { | ||
return(document.createElement("canvas")); | ||
}); | ||
var materials = canvases.map(function(canvas) { | ||
return(new THREE_MeshBasicMaterial({ | ||
map: new THREE_Texture(canvas), | ||
})); | ||
}); | ||
var tile2canvasIx = { | ||
right:0, | ||
left:1, | ||
top:2, | ||
bottom:3, | ||
front:4, | ||
back:5 | ||
}; | ||
// if the property is not set, then set the default order | ||
var tileOrder = this.config.tileOrder || ['right','left','top','bottom','front','back']; | ||
// this needs to be set in order not to get "Tainted canvases may not be loaded." WebGL error | ||
imageObj.crossOrigin = "anonymous"; | ||
imageObj.onload = function() { | ||
var tileWidth = imageObj.height; | ||
tileOrder.forEach(function(key) { | ||
var ix = tile2canvasIx[key]; | ||
var canvas = canvases[ix]; | ||
canvas.height = tileWidth; | ||
canvas.width = tileWidth; | ||
var context = canvas.getContext( '2d' ); | ||
context.drawImage( imageObj, tileWidth * ix, 0, tileWidth, tileWidth, 0, 0, tileWidth, tileWidth ); | ||
materials[ix].map.needsUpdate = true; | ||
}); | ||
self.hideLoader(); | ||
}; // imgObj.onload = function() {...} | ||
imageObj.src = this.config.atlas; | ||
return(materials); | ||
}; // proto.loadAtlas = function() {...} | ||
proto.loadEqui = function() { | ||
var self = this; | ||
var imgObj=new Image(); | ||
var canvases = [0,1,2,3,4,5].map(function(el) { | ||
return(document.createElement("canvas")); | ||
}); | ||
var materials = canvases.map(function(canvas) { | ||
return(new THREE_MeshBasicMaterial({ | ||
map: new THREE_Texture(canvas), | ||
})); | ||
}); | ||
// this needs to be sit in order not to get "Tainted canvases may not be loaded." WebGL error | ||
imgObj.crossOrigin = "anonymous"; | ||
imgObj.onload = function() { | ||
var srcWidth = imgObj.width, | ||
srcHeight = imgObj.height; | ||
// (3) when the image is loaded, start the conversion | ||
var inCanvas = document.createElement('canvas'); | ||
inCanvas.width = srcWidth; | ||
inCanvas.height = srcHeight; | ||
var inCtx=inCanvas.getContext("2d"); | ||
inCtx.drawImage(imgObj,0,0); | ||
var srcImg = inCtx.getImageData(0,0,srcWidth,srcHeight); | ||
self.equi2recti(srcImg, materials, canvases) | ||
}; // imgObj.onload = function() {...} | ||
// (2) start loading the image | ||
imgObj.src = this.config.sphere; | ||
return(materials); | ||
}; // proto.loadEqui = function() {...} | ||
proto.equi2recti = function(srcImg, materials, canvases) { | ||
var self = this, | ||
faceSize=srcImg.width/4; | ||
var imgOut = new ImageData(faceSize, faceSize); | ||
var tileIx2canvasIx = { | ||
0:5, // back | ||
1:1, // left | ||
2:4, // front | ||
3:0, // right | ||
4:2, // top | ||
5:3 // bottom | ||
}; | ||
var loadCounter = 0; | ||
var onWorkerMessage = function(event) { | ||
// (4) as each image is converted apply it to canvas used as texture | ||
var faceIx = event.data.faceIx, | ||
canvasIx = tileIx2canvasIx[faceIx], | ||
oneCanvas = canvases[canvasIx]; | ||
oneCanvas.width = faceSize; | ||
oneCanvas.height = faceSize; | ||
oneCanvas.getContext("2d").putImageData(event.data.imgData,0,0); | ||
materials[canvasIx].map.needsUpdate = true; | ||
if(++loadCounter===6) { | ||
self.hideLoader(); | ||
} | ||
}; | ||
if(self.config.multiWorker) { | ||
for(var i=0;i<6;i++) { | ||
var w = new Worker("../src/equi2recti-worker.js"); | ||
w.onmessage = onWorkerMessage; | ||
// begin converting the images | ||
w.postMessage({ | ||
srcImg: srcImg, | ||
imgOut: imgOut, | ||
faceIx:i | ||
}); | ||
} | ||
} else { | ||
var w = new Worker("../src/equi2recti-worker.js"); | ||
w.onmessage = onWorkerMessage; | ||
// begin converting the images | ||
w.postMessage({ | ||
srcImg: srcImg, | ||
imgOut: imgOut | ||
}); | ||
} | ||
} // proto.equi2recti = function(srcImg, materials, canvases) {...} | ||
proto.initSphere = function() { | ||
var speherRadius = 100, | ||
@@ -137,6 +381,6 @@ sphere_H_segments = 64, | ||
this.sphere = new THREE_Mesh( | ||
this.mesh = new THREE_Mesh( | ||
geometry, | ||
new THREE_MeshBasicMaterial({ | ||
map: this.imgLoader.load(imageUrls), | ||
map: this.imgLoader.load(this.config.sphere), | ||
side: THREE_FrontSide // displaying the texture on the outer side of the sphere | ||
@@ -146,7 +390,6 @@ }) | ||
this.sphere.scale.x = -1; // flipping sphere inside-out - not the texture is rendered on the inner side | ||
this.scene.add(this.sphere); | ||
this.mesh.scale.x = -1; // flipping sphere inside-out - not the texture is rendered on the inner side | ||
this.scene.add(this.mesh); | ||
this.showLoader(); | ||
}; // proto.initSphere = function(imageUrls) {...} | ||
@@ -153,0 +396,0 @@ |
@@ -32,3 +32,3 @@ const path = require('path'); | ||
"three": "THREE", | ||
"jquery": "jquery" | ||
"jquery": "$" | ||
}, | ||
@@ -35,0 +35,0 @@ module: { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
6922418
40
1977
93
8