Sfoglia il codice sorgente

Improvements suggested by JSHint.

tags/2.1.0
Matthew Petroff 10 anni fa
parent
commit
bb915a6287
2 ha cambiato i file con 96 aggiunte e 68 eliminazioni
  1. +28
    -20
      src/js/libpannellum.js
  2. +68
    -48
      src/js/pannellum.js

+ 28
- 20
src/js/libpannellum.js Vedi File

@@ -22,6 +22,9 @@
*/

window.libpannellum = (function(window, document, undefined) {

'use strict';

/* Image Type argument can be that of "equirectangular" or "cubemap".
* If "cubemap" is used, the image argument should be an array of images
* instead of a single image. They should be the order of:
@@ -41,6 +44,8 @@ function Renderer(container, image, imageType) {
var program, gl;

this.init = function(haov, vaov, voffset) {
var s;
// Enable WebGL on canvas
gl = this.canvas.getContext('experimental-webgl', {alpha: false, depth: false});
@@ -56,7 +61,7 @@ function Renderer(container, image, imageType) {
// Add images
var path = this.image.basePath + this.image.fallbackPath;
var sides = ['f', 'b', 'u', 'd', 'l', 'r'];
for (var s = 0; s < 6; s++) {
for (s = 0; s < 6; s++) {
this.world.querySelector('.' + sides[s] + 'face').style.backgroundImage = 'url("' + path.replace('%s',sides[s]) + '.' + this.image.extension + '")';
}
@@ -70,7 +75,7 @@ function Renderer(container, image, imageType) {
var vertices = this.createCube();
this.vtmp = [];
for ( var s = 0; s < 6; s++ ) {
for (s = 0; s < 6; s++) {
this.vtmp[s] = vertices.slice(s * 12, s * 12 + 12);
vertices = this.createCube();
}
@@ -206,17 +211,18 @@ function Renderer(container, image, imageType) {
// Check if there was an error
if (gl.getError() !== 0) {
var width, maxWidth;
console.log('Error: Something went wrong with WebGL!');
if (this.imageType == 'equirectangular') {
var width = Math.max(this.image.width, this.image.height);
var maxWidth = gl.getParameter(gl['MAX_TEXTURE_SIZE']);
width = Math.max(this.image.width, this.image.height);
maxWidth = gl.getParameter(gl.MAX_TEXTURE_SIZE);
if (width > maxWidth) {
console.log('Error: The image is too big; it\'s ' + width + 'px wide, but this device\'s maximum supported width is ' + maxWidth + 'px.');
throw {type: 'webgl size error', width: width, maxWidth: maxWidth};
}
} else if (this.imageType == 'cubemap') {
var width = this.image[0].width;
var maxWidth = gl.getParameter(gl['MAX_CUBE_MAP_TEXTURE_SIZE']);
width = this.image[0].width;
maxWidth = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE);
if (width > maxWidth) {
console.log('Error: The cube face image is too big; it\'s ' + width + 'px wide, but this device\'s maximum supported width is ' + maxWidth + 'px.');
throw {type: 'webgl size error', width: width, maxWidth: maxWidth};
@@ -227,9 +233,11 @@ function Renderer(container, image, imageType) {
};

this.render = function(pitch, yaw, hfov) {
var focal;
// If no WebGL
if (!gl && this.imageType == 'multires') {
var focal = 1 / Math.tan(hfov / 2);
focal = 1 / Math.tan(hfov / 2);
var zoom = focal * this.canvas.width / 2 + 'px';
var transform = 'translate3d(0px, 0px, ' + zoom + ') rotateX(' + pitch + 'rad) rotateY(' + yaw + 'rad) rotateZ(0rad)';
this.world.style.webkitTransform = transform;
@@ -242,7 +250,7 @@ function Renderer(container, image, imageType) {
if (this.imageType != 'multires') {
// Calculate focal length from vertical field of view
var vfov = 2 * Math.atan(Math.tan(hfov * 0.5) / (this.canvas.width / this.canvas.height));
var focal = 1 / Math.tan(vfov * 0.5);
focal = 1 / Math.tan(vfov * 0.5);
// Pass psi, theta, and focal length
gl.uniform1f(program.psi, yaw);
@@ -272,8 +280,8 @@ function Renderer(container, image, imageType) {
// Find current nodes
var rotPersp = this.rotatePersp(perspMatrix, matrix);
program.nodeCache.sort(this.multiresNodeSort);
if (program.nodeCache.length > 200
&& program.nodeCache.length > program.currentNodes.length + 50) {
if (program.nodeCache.length > 200 &&
program.nodeCache.length > program.currentNodes.length + 50) {
// Remove older nodes from cache
program.nodeCache.splice(200, program.nodeCache.length - 200);
}
@@ -384,12 +392,12 @@ function Renderer(container, image, imageType) {
// Add node to current nodes and load texture if needed
var inCurrent = false;
for (var i = 0; i < program.nodeCache.length; i++) {
if (program.nodeCache[i].path == node.path) {
for (var k = 0; k < program.nodeCache.length; k++) {
if (program.nodeCache[k].path == node.path) {
inCurrent = true;
program.nodeCache[i].timestamp = program.nodeCacheTimestamp++;
program.nodeCache[i].diff = node.diff;
program.currentNodes.push(program.nodeCache[i]);
program.nodeCache[k].timestamp = program.nodeCacheTimestamp++;
program.nodeCache[k].diff = node.diff;
program.currentNodes.push(program.nodeCache[k]);
break;
}
}
@@ -475,8 +483,8 @@ function Renderer(container, image, imageType) {
ntmp = new MultiresNode(vtmp, node.side, node.level + 1, node.x*2+1, node.y*2, this.image.fullpath);
children.push(ntmp);
}
if (!(node.x == numTiles && doubleTileSize < this.image.tileResolution)
&& !(node.y == numTiles && doubleTileSize < this.image.tileResolution)) {
if (!(node.x == numTiles && doubleTileSize < this.image.tileResolution) &&
!(node.y == numTiles && doubleTileSize < this.image.tileResolution)) {
vtmp = [v[0]*f1+v[6]*i1, v[1]*f2+v[7]*i2, v[2]*f3+v[8]*i3,
v[3]*f+v[6]*i, v[4]*f2+v[7]*i2, v[5]*f3+v[8]*i3,
v[6], v[7], v[8],
@@ -606,9 +614,9 @@ function Renderer(container, image, imageType) {
// Find optimal level
var newLevel = 1;
while ( newLevel < this.image.maxLevel &&
this.canvas.width > this.image.cubeResolution
* Math.pow(2, newLevel - this.image.maxLevel)
* hfov / (Math.PI / 2) * 0.9 ) {
this.canvas.width > this.image.cubeResolution *
Math.pow(2, newLevel - this.image.maxLevel) *
hfov / (Math.PI / 2) * 0.9 ) {
newLevel++;
}


+ 68
- 48
src/js/pannellum.js Vedi File

@@ -21,6 +21,8 @@
* THE SOFTWARE.
*/

'use strict';

// Display about information on right click
document.addEventListener('contextmenu', onRightClick, false);

@@ -76,9 +78,11 @@ processOptions();

// Initialize viewer
function init() {
var i, p;
if (config.type == 'cubemap') {
panoImage = [];
for (var i = 0; i < 6; i++) {
for (i = 0; i < 6; i++) {
panoImage.push(new Image());
panoImage[i].crossOrigin = 'anonymous';
}
@@ -131,14 +135,16 @@ function init() {
// Quick loading counter for synchronous loading
var itemsToLoad = 6;
for (var i = 0; i < panoImage.length; i++) {
panoImage[i].onload = function() {
itemsToLoad--;
if (itemsToLoad === 0) {
onImageLoad();
}
};
var p = config.cubeMap[i];
var onLoad = function() {
itemsToLoad--;
if (itemsToLoad === 0) {
onImageLoad();
}
};
for (i = 0; i < panoImage.length; i++) {
panoImage[i].onload = onLoad;
p = config.cubeMap[i];
if (config.basePath) {
p = config.basePath + p;
} else if (tourConfig.basePath) {
@@ -152,9 +158,9 @@ function init() {
panoImage.onload = function() {
window.URL.revokeObjectURL(this.src); // Clean up
onImageLoad();
}
};
var p = config.panorama;
p = config.panorama;
if (config.basePath) {
p = config.basePath + p;
} else if (tourConfig.basePath) {
@@ -165,9 +171,9 @@ function init() {
xhr.onloadend = function() {
var img = this.response;
parseGPanoXMP(img);
document.getElementById('lmsg').innerHTML = '';
};
xhr.onprogress = function(e) {
console.log(e.loaded + ' ' + e.total);
if (e.lengthComputable) {
// Display progress
var percent = e.loaded / e.total * 100;
@@ -207,27 +213,27 @@ function init() {
function parseGPanoXMP(image) {
var reader = new FileReader();
reader.addEventListener('loadend', function() {
img = reader.result;
var img = reader.result;
var start = img.indexOf('<x:xmpmeta');
if (start > -1 && config.ignoreGPanoXMP != true) {
if (start > -1 && config.ignoreGPanoXMP !== true) {
var xmpData = img.substring(start, img.indexOf('</x:xmpmeta>') + 12);
// Extract the requested tag from the XMP data
function getTag(tag) {
var getTag = function(tag) {
tag = xmpData.substring(xmpData.indexOf(tag + '="') + tag.length + 2);
return tag.substring(0, tag.indexOf('"'));
}
};
// Relevant XMP data
xmp = {
var xmp = {
fullWidth: Number(getTag('GPano:FullPanoWidthPixels')),
croppedWidth: Number(getTag('GPano:CroppedAreaImageWidthPixels')),
fullHeight: Number(getTag('GPano:FullPanoHeightPixels')),
croppedHeight: Number(getTag('GPano:CroppedAreaImageHeightPixels')),
topPixels: Number(getTag('GPano:CroppedAreaTopPixels')),
heading: Number(getTag('GPano:PoseHeadingDegrees'))
}
};
// Set up viewer using GPano XMP data
config.haov = xmp.croppedWidth / xmp.fullWidth * 360;
@@ -550,9 +556,6 @@ function keyRepeat() {
}
var diff = (newTime - prevTime) * config.hfov / 1700;
var pitch = config.pitch;
var yaw = config.yaw;
// If minus key is down
if (keysDown[0]) {
setHfov(config.hfov + (zoomSpeed * 0.8 + 0.2) * diff);
@@ -646,11 +649,12 @@ function animate() {
render();
if (isUserInteracting) {
requestAnimationFrame(animate);
} else if (keysDown[0] || keysDown[1] || keysDown[2] || keysDown[3]
|| keysDown[4] || keysDown[5] || keysDown[6] || keysDown[7]
|| keysDown[8] || keysDown[9] || config.autoRotate
|| Math.abs(yawSpeed) > 0.01 || Math.abs(pitchSpeed) > 0.01
|| Math.abs(zoomSpeed) > 0.01) {
} else if (keysDown[0] || keysDown[1] || keysDown[2] || keysDown[3] ||
keysDown[4] || keysDown[5] || keysDown[6] || keysDown[7] ||
keysDown[8] || keysDown[9] || config.autoRotate ||
Math.abs(yawSpeed) > 0.01 || Math.abs(pitchSpeed) > 0.01 ||
Math.abs(zoomSpeed) > 0.01) {
keyRepeat();
requestAnimationFrame(animate);
} else if (renderer && renderer.isLoading()) {
@@ -729,10 +733,10 @@ function renderInit() {
if (event.type == 'webgl error' || event.type == 'no webgl') {
anError();
} else if (event.type == 'webgl size error') {
anError('This panorama is too big for your device! It\'s '
+ event.width + 'px wide, but your device only supports images up to '
+ event.maxWidth + 'px wide. Try another device.'
+ ' (If you\'re the author, try scaling down the image.)');
anError('This panorama is too big for your device! It\'s ' +
event.width + 'px wide, but your device only supports images up to ' +
event.maxWidth + 'px wide. Try another device.' +
' (If you\'re the author, try scaling down the image.)');
}
}
}
@@ -750,8 +754,9 @@ function createHotSpots() {
var span = document.createElement('span');
span.innerHTML = hs.text;
var a;
if (hs.URL) {
var a = document.createElement('a');
a = document.createElement('a');
a.setAttribute('href', hs.URL);
a.setAttribute('target', '_blank');
document.getElementById('container').appendChild(a);
@@ -766,7 +771,7 @@ function createHotSpots() {
document.getElementById('container').appendChild(div);
span.appendChild(video);
} else if (hs.image) {
var a = document.createElement('a');
a = document.createElement('a');
a.setAttribute('href', hs.image);
a.setAttribute('target', '_blank');
span.appendChild(a);
@@ -865,10 +870,12 @@ function parseURLParameters() {
json += '}';
configFromURL = JSON.parse(json);
var request;
// Check for JSON configuration file
if (configFromURL.config) {
// Get JSON configuration file
var request = new XMLHttpRequest();
request = new XMLHttpRequest();
request.open('GET', configFromURL.config, false);
request.send();
var c = JSON.parse(request.responseText);
@@ -888,7 +895,7 @@ function parseURLParameters() {
var firstScene = null;
if (configFromURL.tour) {
// Get JSON configuration file
var request = new XMLHttpRequest();
request = new XMLHttpRequest();
request.open('GET', configFromURL.tour, false);
request.send();
tourConfig = JSON.parse(request.responseText);
@@ -910,29 +917,38 @@ function parseURLParameters() {

function mergeConfig(sceneId) {
config = {};
var k;
// Merge default config
for (var k in defaultConfig) {
config[k] = defaultConfig[k];
for (k in defaultConfig) {
if (defaultConfig.hasOwnProperty(k)) {
config[k] = defaultConfig[k];
}
}
// Merge default scene config
for (var k in tourConfig.default) {
config[k] = tourConfig.default[k];
for (k in tourConfig.default) {
if (tourConfig.hasOwnProperty(k)) {
config[k] = tourConfig.default[k];
}
}
// Merge current scene config
if ((sceneId !== null) && (sceneId !== '') && (tourConfig.scenes) && (tourConfig.scenes[sceneId])) {
var scene = tourConfig.scenes[sceneId];
for (var k in scene) {
config[k] = scene[k];
for (k in scene) {
if (scene.hasOwnProperty(k)) {
config[k] = scene[k];
}
}
config.activeScene = sceneId;
}
// Merge URL and config file
for (var k in configFromURL) {
config[k] = configFromURL[k];
for (k in configFromURL) {
if (configFromURL.hasOwnProperty(k)) {
config[k] = configFromURL[k];
}
}
}

@@ -941,7 +957,7 @@ function processOptions() {
// maximum number of connections to a server as can happen with cubic
// panoramas
if ('preview' in config) {
var p = config['preview'];
var p = config.preview;
if (config.basePath) {
p = config.basePath + p;
} else if (tourConfig.basePath) {
@@ -957,6 +973,7 @@ function processOptions() {
// Process other options
for (var key in config) {
if (config.hasOwnProperty(key)) {
switch(key) {
case 'title':
document.getElementById('title_box').innerHTML = config[key];
@@ -982,7 +999,7 @@ function processOptions() {
break;
case 'autoLoad':
if (config[key] == true) {
if (config[key] === true) {
// Show loading box
document.getElementById('load_box').style.display = 'inline';
// Hide load button
@@ -1019,8 +1036,9 @@ function processOptions() {
break;
case 'showFullscreenCtrl':
if (config[key] && ('fullscreen' in document || 'mozFullScreen' in document
|| 'webkitIsFullScreen' in document || 'msFullscreenElement' in document)) {
if (config[key] && ('fullscreen' in document || 'mozFullScreen' in document ||
'webkitIsFullScreen' in document || 'msFullscreenElement' in document)) {
// Show fullscreen control
document.getElementById('fullscreentoggle_button').style.display = 'block';
} else {
@@ -1029,6 +1047,7 @@ function processOptions() {
}
break;
}
}
}
}

@@ -1089,8 +1108,9 @@ function setHfov(i) {
// Keep field of view within bounds
if (i < config.minHfov && config.type != 'multires') {
config.hfov = config.minHfov;
} else if (config.type == 'multires' && i < canvas.width
/ (config.multiRes.cubeResolution / 90 * 0.9)) {
} else if (config.type == 'multires' && i < canvas.width /
(config.multiRes.cubeResolution / 90 * 0.9)) {
config.hfov = canvas.width / (config.multiRes.cubeResolution / 90 * 0.9);
} else if (i > config.maxHfov) {
config.hfov = config.maxHfov;


Caricamento…
Annulla
Salva