|
|
@@ -1,17 +1,17 @@ |
|
|
|
/* |
|
|
|
* Pannellum - An HTML5 based Panorama Viewer |
|
|
|
* Copyright (c) 2011-2018 Matthew Petroff |
|
|
|
* |
|
|
|
* |
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
|
|
* of this software and associated documentation files (the "Software"), to deal |
|
|
|
* in the Software without restriction, including without limitation the rights |
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
|
|
* copies of the Software, and to permit persons to whom the Software is |
|
|
|
* furnished to do so, subject to the following conditions: |
|
|
|
* |
|
|
|
* |
|
|
|
* The above copyright notice and this permission notice shall be included in |
|
|
|
* all copies or substantial portions of the Software. |
|
|
|
* |
|
|
|
* |
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
|
@@ -67,6 +67,7 @@ var config, |
|
|
|
externalEventListeners = {}, |
|
|
|
specifiedPhotoSphereExcludes = [], |
|
|
|
update = false, // Should we update when still to render dynamic content |
|
|
|
eps = 1e-6, |
|
|
|
hotspotsCreated = false; |
|
|
|
|
|
|
|
var defaultConfig = { |
|
|
@@ -304,7 +305,7 @@ function init() { |
|
|
|
origPitch = config.pitch; |
|
|
|
|
|
|
|
var i, p; |
|
|
|
|
|
|
|
|
|
|
|
if (config.type == 'cubemap') { |
|
|
|
panoImage = []; |
|
|
|
for (i = 0; i < 6; i++) { |
|
|
@@ -342,21 +343,21 @@ function init() { |
|
|
|
if (config.type == 'cubemap') { |
|
|
|
// Quick loading counter for synchronous loading |
|
|
|
var itemsToLoad = 6; |
|
|
|
|
|
|
|
|
|
|
|
var onLoad = function() { |
|
|
|
itemsToLoad--; |
|
|
|
if (itemsToLoad === 0) { |
|
|
|
onImageLoad(); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var onError = function(e) { |
|
|
|
var a = document.createElement('a'); |
|
|
|
a.href = e.target.src; |
|
|
|
a.textContent = a.href; |
|
|
|
anError(config.strings.fileAccessError.replace('%s', a.outerHTML)); |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < panoImage.length; i++) { |
|
|
|
p = config.cubeMap[i]; |
|
|
|
if (p == "null") { // support partial cubemap image with explicitly empty faces |
|
|
@@ -378,16 +379,16 @@ function init() { |
|
|
|
if (config.basePath) { |
|
|
|
p = config.basePath; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (config.dynamic !== true) { |
|
|
|
// Still image |
|
|
|
p = absoluteURL(config.panorama) ? config.panorama : p + config.panorama; |
|
|
|
|
|
|
|
|
|
|
|
panoImage.onload = function() { |
|
|
|
window.URL.revokeObjectURL(this.src); // Clean up |
|
|
|
onImageLoad(); |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
var xhr = new XMLHttpRequest(); |
|
|
|
xhr.onloadend = function() { |
|
|
|
if (xhr.status != 200) { |
|
|
@@ -439,7 +440,7 @@ function init() { |
|
|
|
xhr.send(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (config.draggable) |
|
|
|
uiContainer.classList.add('pnlm-grab'); |
|
|
|
uiContainer.classList.remove('pnlm-grabbing'); |
|
|
@@ -533,7 +534,7 @@ function parseGPanoXMP(image) { |
|
|
|
var start = img.indexOf('<x:xmpmeta'); |
|
|
|
if (start > -1 && config.ignoreGPanoXMP !== true) { |
|
|
|
var xmpData = img.substring(start, img.indexOf('</x:xmpmeta>') + 12); |
|
|
|
|
|
|
|
|
|
|
|
// Extract the requested tag from the XMP data |
|
|
|
var getTag = function(tag) { |
|
|
|
var result; |
|
|
@@ -549,7 +550,7 @@ function parseGPanoXMP(image) { |
|
|
|
} |
|
|
|
return null; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// Relevant XMP data |
|
|
|
var xmp = { |
|
|
|
fullWidth: getTag('GPano:FullPanoWidthPixels'), |
|
|
@@ -561,11 +562,11 @@ function parseGPanoXMP(image) { |
|
|
|
horizonPitch: getTag('GPano:PosePitchDegrees'), |
|
|
|
horizonRoll: getTag('GPano:PoseRollDegrees') |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
if (xmp.fullWidth !== null && xmp.croppedWidth !== null && |
|
|
|
xmp.fullHeight !== null && xmp.croppedHeight !== null && |
|
|
|
xmp.topPixels !== null) { |
|
|
|
|
|
|
|
|
|
|
|
// Set up viewer using GPano XMP data |
|
|
|
if (specifiedPhotoSphereExcludes.indexOf('haov') < 0) |
|
|
|
config.haov = xmp.croppedWidth / xmp.fullWidth * 360; |
|
|
@@ -586,11 +587,11 @@ function parseGPanoXMP(image) { |
|
|
|
if (specifiedPhotoSphereExcludes.indexOf('horizonRoll') < 0) |
|
|
|
config.horizonRoll = xmp.horizonRoll; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// TODO: add support for initial view settings |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Load panorama |
|
|
|
panoImage.src = window.URL.createObjectURL(image); |
|
|
|
}); |
|
|
@@ -658,8 +659,9 @@ function aboutMessage(event) { |
|
|
|
function mousePosition(event) { |
|
|
|
var bounds = container.getBoundingClientRect(); |
|
|
|
var pos = {}; |
|
|
|
pos.x = event.clientX - bounds.left; |
|
|
|
pos.y = event.clientY - bounds.top; |
|
|
|
// pageX / pageY needed for iOS |
|
|
|
pos.x = (event.clientX || event.pageX) - bounds.left; |
|
|
|
pos.y = (event.clientY || event.pageY) - bounds.top; |
|
|
|
return pos; |
|
|
|
} |
|
|
|
|
|
|
@@ -674,12 +676,12 @@ function onDocumentMouseDown(event) { |
|
|
|
event.preventDefault(); |
|
|
|
// But not all of it |
|
|
|
container.focus(); |
|
|
|
|
|
|
|
|
|
|
|
// Only do something if the panorama is loaded |
|
|
|
if (!loaded || !config.draggable) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Calculate mouse position relative to top left of viewer container |
|
|
|
var pos = mousePosition(event); |
|
|
|
|
|
|
@@ -689,7 +691,7 @@ function onDocumentMouseDown(event) { |
|
|
|
console.log('Pitch: ' + coords[0] + ', Yaw: ' + coords[1] + ', Center Pitch: ' + |
|
|
|
config.pitch + ', Center Yaw: ' + config.yaw + ', HFOV: ' + config.hfov); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Turn off auto-rotation if enabled |
|
|
|
stopAnimation(); |
|
|
|
|
|
|
@@ -700,16 +702,16 @@ function onDocumentMouseDown(event) { |
|
|
|
|
|
|
|
isUserInteracting = true; |
|
|
|
latestInteraction = Date.now(); |
|
|
|
|
|
|
|
|
|
|
|
onPointerDownPointerX = pos.x; |
|
|
|
onPointerDownPointerY = pos.y; |
|
|
|
|
|
|
|
|
|
|
|
onPointerDownYaw = config.yaw; |
|
|
|
onPointerDownPitch = config.pitch; |
|
|
|
|
|
|
|
|
|
|
|
uiContainer.classList.add('pnlm-grabbing'); |
|
|
|
uiContainer.classList.remove('pnlm-grab'); |
|
|
|
|
|
|
|
|
|
|
|
fireEvent('mousedown', event); |
|
|
|
animateInit(); |
|
|
|
} |
|
|
@@ -771,9 +773,9 @@ function onDocumentMouseMove(event) { |
|
|
|
var yaw = ((Math.atan(onPointerDownPointerX / canvasWidth * 2 - 1) - Math.atan(pos.x / canvasWidth * 2 - 1)) * 180 / Math.PI * config.hfov / 90) + onPointerDownYaw; |
|
|
|
speed.yaw = (yaw - config.yaw) % 360 * 0.2; |
|
|
|
config.yaw = yaw; |
|
|
|
|
|
|
|
|
|
|
|
var vfov = 2 * Math.atan(Math.tan(config.hfov/360*Math.PI) * canvasHeight / canvasWidth) * 180 / Math.PI; |
|
|
|
|
|
|
|
|
|
|
|
var pitch = ((Math.atan(pos.y / canvasHeight * 2 - 1) - Math.atan(onPointerDownPointerY / canvasHeight * 2 - 1)) * 180 / Math.PI * vfov / 90) + onPointerDownPitch; |
|
|
|
speed.pitch = (pitch - config.pitch) * 0.2; |
|
|
|
config.pitch = pitch; |
|
|
@@ -826,7 +828,7 @@ function onDocumentTouchStart(event) { |
|
|
|
|
|
|
|
onPointerDownPointerX = pos0.x; |
|
|
|
onPointerDownPointerY = pos0.y; |
|
|
|
|
|
|
|
|
|
|
|
if (event.targetTouches.length == 2) { |
|
|
|
// Down pointer is the center of the two fingers |
|
|
|
var pos1 = mousePosition(event.targetTouches[1]); |
|
|
@@ -837,7 +839,7 @@ function onDocumentTouchStart(event) { |
|
|
|
} |
|
|
|
isUserInteracting = true; |
|
|
|
latestInteraction = Date.now(); |
|
|
|
|
|
|
|
|
|
|
|
onPointerDownYaw = config.yaw; |
|
|
|
onPointerDownPitch = config.pitch; |
|
|
|
|
|
|
@@ -865,7 +867,7 @@ function onDocumentTouchMove(event) { |
|
|
|
var pos0 = mousePosition(event.targetTouches[0]); |
|
|
|
var clientX = pos0.x; |
|
|
|
var clientY = pos0.y; |
|
|
|
|
|
|
|
|
|
|
|
if (event.targetTouches.length == 2 && onPointerDownPointerDist != -1) { |
|
|
|
var pos1 = mousePosition(event.targetTouches[1]); |
|
|
|
clientX += (pos1.x - pos0.x) * 0.5; |
|
|
@@ -1023,7 +1025,7 @@ function onDocumentKeyPress(event) { |
|
|
|
if (config.capturedKeyNumbers.indexOf(keynumber) < 0) |
|
|
|
return; |
|
|
|
event.preventDefault(); |
|
|
|
|
|
|
|
|
|
|
|
// If escape key is pressed |
|
|
|
if (keynumber == 27) { |
|
|
|
// If in fullscreen mode |
|
|
@@ -1054,12 +1056,12 @@ function clearKeys() { |
|
|
|
function onDocumentKeyUp(event) { |
|
|
|
// Record key pressed |
|
|
|
var keynumber = event.which || event.keycode; |
|
|
|
|
|
|
|
|
|
|
|
// Override default action for keys that are used |
|
|
|
if (config.capturedKeyNumbers.indexOf(keynumber) < 0) |
|
|
|
return; |
|
|
|
event.preventDefault(); |
|
|
|
|
|
|
|
|
|
|
|
// Change key |
|
|
|
changeKey(keynumber, false); |
|
|
|
} |
|
|
@@ -1077,53 +1079,53 @@ function changeKey(keynumber, value) { |
|
|
|
case 109: case 189: case 17: case 173: |
|
|
|
if (keysDown[0] != value) { keyChanged = true; } |
|
|
|
keysDown[0] = value; break; |
|
|
|
|
|
|
|
|
|
|
|
// If plus key is released |
|
|
|
case 107: case 187: case 16: case 61: |
|
|
|
if (keysDown[1] != value) { keyChanged = true; } |
|
|
|
keysDown[1] = value; break; |
|
|
|
|
|
|
|
|
|
|
|
// If up arrow is released |
|
|
|
case 38: |
|
|
|
if (keysDown[2] != value) { keyChanged = true; } |
|
|
|
keysDown[2] = value; break; |
|
|
|
|
|
|
|
|
|
|
|
// If "w" is released |
|
|
|
case 87: |
|
|
|
if (keysDown[6] != value) { keyChanged = true; } |
|
|
|
keysDown[6] = value; break; |
|
|
|
|
|
|
|
|
|
|
|
// If down arrow is released |
|
|
|
case 40: |
|
|
|
if (keysDown[3] != value) { keyChanged = true; } |
|
|
|
keysDown[3] = value; break; |
|
|
|
|
|
|
|
|
|
|
|
// If "s" is released |
|
|
|
case 83: |
|
|
|
if (keysDown[7] != value) { keyChanged = true; } |
|
|
|
keysDown[7] = value; break; |
|
|
|
|
|
|
|
|
|
|
|
// If left arrow is released |
|
|
|
case 37: |
|
|
|
if (keysDown[4] != value) { keyChanged = true; } |
|
|
|
keysDown[4] = value; break; |
|
|
|
|
|
|
|
|
|
|
|
// If "a" is released |
|
|
|
case 65: |
|
|
|
if (keysDown[8] != value) { keyChanged = true; } |
|
|
|
keysDown[8] = value; break; |
|
|
|
|
|
|
|
|
|
|
|
// If right arrow is released |
|
|
|
case 39: |
|
|
|
if (keysDown[5] != value) { keyChanged = true; } |
|
|
|
keysDown[5] = value; break; |
|
|
|
|
|
|
|
|
|
|
|
// If "d" is released |
|
|
|
case 68: |
|
|
|
if (keysDown[9] != value) { keyChanged = true; } |
|
|
|
keysDown[9] = value; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (keyChanged && value) { |
|
|
|
if (typeof performance !== 'undefined' && performance.now()) { |
|
|
|
prevTime = performance.now(); |
|
|
@@ -1150,7 +1152,7 @@ function keyRepeat() { |
|
|
|
var prevPitch = config.pitch; |
|
|
|
var prevYaw = config.yaw; |
|
|
|
var prevZoom = config.hfov; |
|
|
|
|
|
|
|
|
|
|
|
var newTime; |
|
|
|
if (typeof performance !== 'undefined' && performance.now()) { |
|
|
|
newTime = performance.now(); |
|
|
@@ -1162,40 +1164,40 @@ function keyRepeat() { |
|
|
|
} |
|
|
|
var diff = (newTime - prevTime) * config.hfov / 1700; |
|
|
|
diff = Math.min(diff, 1.0); |
|
|
|
|
|
|
|
|
|
|
|
// If minus key is down |
|
|
|
if (keysDown[0] && config.keyboardZoom === true) { |
|
|
|
setHfov(config.hfov + (speed.hfov * 0.8 + 0.5) * diff); |
|
|
|
isKeyDown = true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// If plus key is down |
|
|
|
if (keysDown[1] && config.keyboardZoom === true) { |
|
|
|
setHfov(config.hfov + (speed.hfov * 0.8 - 0.2) * diff); |
|
|
|
isKeyDown = true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// If up arrow or "w" is down |
|
|
|
if (keysDown[2] || keysDown[6]) { |
|
|
|
// Pan up |
|
|
|
config.pitch += (speed.pitch * 0.8 + 0.2) * diff; |
|
|
|
isKeyDown = true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// If down arrow or "s" is down |
|
|
|
if (keysDown[3] || keysDown[7]) { |
|
|
|
// Pan down |
|
|
|
config.pitch += (speed.pitch * 0.8 - 0.2) * diff; |
|
|
|
isKeyDown = true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// If left arrow or "a" is down |
|
|
|
if (keysDown[4] || keysDown[8]) { |
|
|
|
// Pan left |
|
|
|
config.yaw += (speed.yaw * 0.8 - 0.2) * diff; |
|
|
|
isKeyDown = true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// If right arrow or "d" is down |
|
|
|
if (keysDown[5] || keysDown[9]) { |
|
|
|
// Pan right |
|
|
@@ -1216,7 +1218,7 @@ function keyRepeat() { |
|
|
|
yawDiff = (-config.autoRotate > 0 ? 1 : -1) * Math.min(Math.abs(config.autoRotate * timeDiff), Math.abs(yawDiff)); |
|
|
|
config.yaw += yawDiff; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Deal with stopping auto rotation after a set delay |
|
|
|
if (config.autoRotateStopDelay) { |
|
|
|
config.autoRotateStopDelay -= newTime - prevTime; |
|
|
@@ -1246,7 +1248,7 @@ function keyRepeat() { |
|
|
|
if (diff > 0 && !config.autoRotate) { |
|
|
|
// "Friction" |
|
|
|
var friction = 0.85; |
|
|
|
|
|
|
|
|
|
|
|
// Yaw |
|
|
|
if (!keysDown[4] && !keysDown[5] && !keysDown[8] && !keysDown[9] && !animatedMove.yaw) { |
|
|
|
config.yaw += speed.yaw * diff * friction; |
|
|
@@ -1266,14 +1268,14 @@ function keyRepeat() { |
|
|
|
speed.yaw = speed.yaw * 0.8 + (config.yaw - prevYaw) / diff * 0.2; |
|
|
|
speed.pitch = speed.pitch * 0.8 + (config.pitch - prevPitch) / diff * 0.2; |
|
|
|
speed.hfov = speed.hfov * 0.8 + (config.hfov - prevZoom) / diff * 0.2; |
|
|
|
|
|
|
|
|
|
|
|
// Limit speed |
|
|
|
var maxSpeed = config.autoRotate ? Math.abs(config.autoRotate) : 5; |
|
|
|
speed.yaw = Math.min(maxSpeed, Math.max(speed.yaw, -maxSpeed)); |
|
|
|
speed.pitch = Math.min(maxSpeed, Math.max(speed.pitch, -maxSpeed)); |
|
|
|
speed.hfov = Math.min(maxSpeed, Math.max(speed.hfov, -maxSpeed)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Stop movement if opposite controls are pressed |
|
|
|
if (keysDown[0] && keysDown[1]) { |
|
|
|
speed.hfov = 0; |
|
|
@@ -1300,11 +1302,7 @@ function animateMove(axis) { |
|
|
|
t.endPosition === t.startPosition) { |
|
|
|
result = t.endPosition; |
|
|
|
speed[axis] = 0; |
|
|
|
var callback = animatedMove[axis].callback, |
|
|
|
callbackArgs = animatedMove[axis].callbackArgs; |
|
|
|
delete animatedMove[axis]; |
|
|
|
if (typeof callback == 'function') |
|
|
|
callback(callbackArgs); |
|
|
|
} |
|
|
|
config[axis] = result; |
|
|
|
} |
|
|
@@ -1372,7 +1370,7 @@ function animate() { |
|
|
|
} else if (renderer && (renderer.isLoading() || (config.dynamic === true && update))) { |
|
|
|
requestAnimationFrame(animate); |
|
|
|
} else { |
|
|
|
fireEvent('animateFinished', {pitch: _this.getPitch(), yaw: _this.getYaw(), hfov: _this.getHfov()}); |
|
|
|
fireEvent('animatefinished', {pitch: _this.getPitch(), yaw: _this.getYaw(), hfov: _this.getHfov()}); |
|
|
|
animating = false; |
|
|
|
prevTime = undefined; |
|
|
|
var autoRotateStartTime = config.autoRotateInactivityDelay - |
|
|
@@ -1438,7 +1436,7 @@ function render() { |
|
|
|
} |
|
|
|
config.yaw = Math.max(minYaw, Math.min(maxYaw, config.yaw)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Check if we autoRotate in a limited by min and max yaw |
|
|
|
// If so reverse direction |
|
|
|
if (config.autoRotate !== false && tmpyaw != config.yaw && |
|
|
@@ -1462,11 +1460,11 @@ function render() { |
|
|
|
if (isNaN(maxPitch)) |
|
|
|
maxPitch = 90; |
|
|
|
config.pitch = Math.max(minPitch, Math.min(maxPitch, config.pitch)); |
|
|
|
|
|
|
|
|
|
|
|
renderer.render(config.pitch * Math.PI / 180, config.yaw * Math.PI / 180, config.hfov * Math.PI / 180, {roll: config.roll * Math.PI / 180}); |
|
|
|
|
|
|
|
|
|
|
|
renderHotSpots(); |
|
|
|
|
|
|
|
|
|
|
|
// Update compass |
|
|
|
if (config.compass) { |
|
|
|
compass.style.transform = 'rotate(' + (-config.yaw - config.northOffset) + 'deg)'; |
|
|
@@ -1603,7 +1601,7 @@ function renderInit() { |
|
|
|
} |
|
|
|
} catch(event) { |
|
|
|
// Panorama not loaded |
|
|
|
|
|
|
|
|
|
|
|
// Display error if there is a bad texture |
|
|
|
if (event.type == 'webgl error' || event.type == 'no webgl') { |
|
|
|
anError(); |
|
|
@@ -1634,17 +1632,17 @@ function renderInitCallback() { |
|
|
|
fireEvent('scenechangefadedone'); |
|
|
|
}, config.sceneFadeDuration); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Show compass if applicable |
|
|
|
if (config.compass) { |
|
|
|
compass.style.display = 'inline'; |
|
|
|
} else { |
|
|
|
compass.style.display = 'none'; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Show hotspots |
|
|
|
createHotSpots(); |
|
|
|
|
|
|
|
|
|
|
|
// Hide loading display |
|
|
|
infoDisplay.load.box.style.display = 'none'; |
|
|
|
if (preview !== undefined) { |
|
|
@@ -1654,7 +1652,7 @@ function renderInitCallback() { |
|
|
|
loaded = true; |
|
|
|
|
|
|
|
fireEvent('load'); |
|
|
|
|
|
|
|
|
|
|
|
animateInit(); |
|
|
|
} |
|
|
|
|
|
|
@@ -1853,14 +1851,14 @@ function mergeConfig(sceneId) { |
|
|
|
var k, s; |
|
|
|
var photoSphereExcludes = ['haov', 'vaov', 'vOffset', 'northOffset', 'horizonPitch', 'horizonRoll']; |
|
|
|
specifiedPhotoSphereExcludes = []; |
|
|
|
|
|
|
|
|
|
|
|
// Merge default config |
|
|
|
for (k in defaultConfig) { |
|
|
|
if (defaultConfig.hasOwnProperty(k)) { |
|
|
|
config[k] = defaultConfig[k]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Merge default scene config |
|
|
|
for (k in initialConfig.default) { |
|
|
|
if (initialConfig.default.hasOwnProperty(k)) { |
|
|
@@ -1878,7 +1876,7 @@ function mergeConfig(sceneId) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Merge current scene config |
|
|
|
if ((sceneId !== null) && (sceneId !== '') && (initialConfig.scenes) && (initialConfig.scenes[sceneId])) { |
|
|
|
var scene = initialConfig.scenes[sceneId]; |
|
|
@@ -1900,7 +1898,7 @@ function mergeConfig(sceneId) { |
|
|
|
} |
|
|
|
config.scene = sceneId; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Merge initial config |
|
|
|
for (k in initialConfig) { |
|
|
|
if (initialConfig.hasOwnProperty(k)) { |
|
|
@@ -1971,12 +1969,12 @@ function processOptions(isPreview) { |
|
|
|
infoDisplay.title.innerHTML = escapeHTML(config[key]); |
|
|
|
infoDisplay.container.style.display = 'inline'; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case 'author': |
|
|
|
infoDisplay.author.innerHTML = config.strings.bylineLabel.replace('%s', escapeHTML(config[key])); |
|
|
|
infoDisplay.container.style.display = 'inline'; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case 'fallback': |
|
|
|
var link = document.createElement('a'); |
|
|
|
link.href = sanitizeURL(config[key]); |
|
|
@@ -1989,11 +1987,11 @@ function processOptions(isPreview) { |
|
|
|
infoDisplay.errorMsg.innerHTML = ''; // Removes all children nodes |
|
|
|
infoDisplay.errorMsg.appendChild(message); |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case 'hfov': |
|
|
|
setHfov(Number(config[key])); |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case 'autoLoad': |
|
|
|
if (config[key] === true && renderer === undefined) { |
|
|
|
// Show loading box |
|
|
@@ -2004,7 +2002,7 @@ function processOptions(isPreview) { |
|
|
|
init(); |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case 'showZoomCtrl': |
|
|
|
if (config[key] && config.showControls != false) { |
|
|
|
// Show zoom controls |
|
|
@@ -2018,7 +2016,7 @@ function processOptions(isPreview) { |
|
|
|
case 'showFullscreenCtrl': |
|
|
|
if (config[key] && config.showControls != false && ('fullscreen' in document || 'mozFullScreen' in document || |
|
|
|
'webkitIsFullScreen' in document || 'msFullscreenElement' in document)) { |
|
|
|
|
|
|
|
|
|
|
|
// Show fullscreen control |
|
|
|
controls.fullscreen.style.display = 'block'; |
|
|
|
} else { |
|
|
@@ -2226,7 +2224,7 @@ function load() { |
|
|
|
function loadScene(sceneId, targetPitch, targetYaw, targetHfov, fadeDone) { |
|
|
|
loaded = false; |
|
|
|
animatedMove = {}; |
|
|
|
|
|
|
|
|
|
|
|
// Set up fade if specified |
|
|
|
var fadeImg, workingPitch, workingYaw, workingHfov; |
|
|
|
if (config.sceneFadeDuration && !fadeDone) { |
|
|
@@ -2246,7 +2244,7 @@ function loadScene(sceneId, targetPitch, targetYaw, targetHfov, fadeDone) { |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Set new pointing |
|
|
|
if (targetPitch === 'same') { |
|
|
|
workingPitch = config.pitch; |
|
|
@@ -2265,10 +2263,10 @@ function loadScene(sceneId, targetPitch, targetYaw, targetHfov, fadeDone) { |
|
|
|
} else { |
|
|
|
workingHfov = targetHfov; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Destroy hot spots from previous scene |
|
|
|
destroyHotSpots(); |
|
|
|
|
|
|
|
|
|
|
|
// Create the new config for the scene |
|
|
|
mergeConfig(sceneId); |
|
|
|
|
|
|
@@ -2387,16 +2385,22 @@ this.getPitch = function() { |
|
|
|
* @returns {Viewer} `this` |
|
|
|
*/ |
|
|
|
this.setPitch = function(pitch, animated, callback, callbackArgs) { |
|
|
|
latestInteraction = Date.now(); |
|
|
|
if (Math.abs(pitch - config.pitch) <= eps) { |
|
|
|
if (typeof callback == 'function') |
|
|
|
callback(callbackArgs); |
|
|
|
return this; |
|
|
|
} |
|
|
|
animated = animated == undefined ? 1000: Number(animated); |
|
|
|
if (animated) { |
|
|
|
animatedMove.pitch = { |
|
|
|
'startTime': Date.now(), |
|
|
|
'startPosition': config.pitch, |
|
|
|
'endPosition': pitch, |
|
|
|
'duration': animated, |
|
|
|
'callback': callback, |
|
|
|
'callbackArgs': callbackArgs |
|
|
|
'duration': animated |
|
|
|
} |
|
|
|
if (typeof callback == 'function') |
|
|
|
setTimeout(function(){callback(callbackArgs)}, animated); |
|
|
|
} else { |
|
|
|
config.pitch = pitch; |
|
|
|
} |
|
|
@@ -2448,6 +2452,12 @@ this.getYaw = function() { |
|
|
|
* @returns {Viewer} `this` |
|
|
|
*/ |
|
|
|
this.setYaw = function(yaw, animated, callback, callbackArgs) { |
|
|
|
latestInteraction = Date.now(); |
|
|
|
if (Math.abs(yaw - config.yaw) <= eps) { |
|
|
|
if (typeof callback == 'function') |
|
|
|
callback(callbackArgs); |
|
|
|
return this; |
|
|
|
} |
|
|
|
animated = animated == undefined ? 1000: Number(animated); |
|
|
|
yaw = ((yaw + 180) % 360) - 180 // Keep in bounds |
|
|
|
if (animated) { |
|
|
@@ -2461,10 +2471,10 @@ this.setYaw = function(yaw, animated, callback, callbackArgs) { |
|
|
|
'startTime': Date.now(), |
|
|
|
'startPosition': config.yaw, |
|
|
|
'endPosition': yaw, |
|
|
|
'duration': animated, |
|
|
|
'callback': callback, |
|
|
|
'callbackArgs': callbackArgs |
|
|
|
'duration': animated |
|
|
|
} |
|
|
|
if (typeof callback == 'function') |
|
|
|
setTimeout(function(){callback(callbackArgs)}, animated); |
|
|
|
} else { |
|
|
|
config.yaw = yaw; |
|
|
|
} |
|
|
@@ -2516,16 +2526,22 @@ this.getHfov = function() { |
|
|
|
* @returns {Viewer} `this` |
|
|
|
*/ |
|
|
|
this.setHfov = function(hfov, animated, callback, callbackArgs) { |
|
|
|
latestInteraction = Date.now(); |
|
|
|
if (Math.abs(hfov - config.hfov) <= eps) { |
|
|
|
if (typeof callback == 'function') |
|
|
|
callback(callbackArgs); |
|
|
|
return this; |
|
|
|
} |
|
|
|
animated = animated == undefined ? 1000: Number(animated); |
|
|
|
if (animated) { |
|
|
|
animatedMove.hfov = { |
|
|
|
'startTime': Date.now(), |
|
|
|
'startPosition': config.hfov, |
|
|
|
'endPosition': constrainHfov(hfov), |
|
|
|
'duration': animated, |
|
|
|
'callback': callback, |
|
|
|
'callbackArgs': callbackArgs |
|
|
|
'duration': animated |
|
|
|
} |
|
|
|
if (typeof callback == 'function') |
|
|
|
setTimeout(function(){callback(callbackArgs)}, animated); |
|
|
|
} else { |
|
|
|
setHfov(hfov); |
|
|
|
} |
|
|
@@ -2571,16 +2587,20 @@ this.setHfovBounds = function(bounds) { |
|
|
|
*/ |
|
|
|
this.lookAt = function(pitch, yaw, hfov, animated, callback, callbackArgs) { |
|
|
|
animated = animated == undefined ? 1000: Number(animated); |
|
|
|
if (pitch !== undefined) { |
|
|
|
if (pitch !== undefined && Math.abs(pitch - config.pitch) > eps) { |
|
|
|
this.setPitch(pitch, animated, callback, callbackArgs); |
|
|
|
callback = undefined; |
|
|
|
} |
|
|
|
if (yaw !== undefined) { |
|
|
|
if (yaw !== undefined && Math.abs(yaw - config.yaw) > eps) { |
|
|
|
this.setYaw(yaw, animated, callback, callbackArgs); |
|
|
|
callback = undefined; |
|
|
|
} |
|
|
|
if (hfov !== undefined) |
|
|
|
if (hfov !== undefined && Math.abs(hfov - config.hfov) > eps) { |
|
|
|
this.setHfov(hfov, animated, callback, callbackArgs); |
|
|
|
callback = undefined; |
|
|
|
} |
|
|
|
if (typeof callback == 'function') |
|
|
|
callback(callbackArgs); |
|
|
|
return this; |
|
|
|
} |
|
|
|
|
|
|
|