瀏覽代碼

Merge remote-tracking branch 'refs/remotes/origin/master' into tour-adoptions

pull/880/head
Nico Höllerich 6 年之前
父節點
當前提交
24e55d8f0b
共有 11 個文件被更改,包括 185 次插入44 次删除
  1. +3
    -0
      .gitignore
  2. +1
    -1
      COPYING
  3. +1
    -1
      VERSION
  4. +75
    -0
      changelog.md
  5. +19
    -1
      doc/json-config-parameters.md
  6. +1
    -1
      package.json
  7. +1
    -0
      src/css/pannellum.css
  8. +34
    -17
      src/js/libpannellum.js
  9. +48
    -21
      src/js/pannellum.js
  10. +1
    -1
      utils/multires/generate.py
  11. +1
    -1
      utils/video/videojs-pannellum-plugin.js

+ 3
- 0
.gitignore 查看文件

@@ -6,3 +6,6 @@ build/**

# Ignore generated docs
utils/doc/generated_docs

# Ignore IntelliJ Files
.idea

+ 1
- 1
COPYING 查看文件

@@ -1,4 +1,4 @@
Copyright (c) 2011-2017 Matthew Petroff
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


+ 1
- 1
VERSION 查看文件

@@ -1 +1 @@
2.3.2
2.4.1

+ 75
- 0
changelog.md 查看文件

@@ -2,6 +2,81 @@ Changelog
=========


Changes in Pannellum 2.4.1
--------------------------

Bugfixes:

- Fix touch input issue in Chrome
- The API's `loadScene` method now works when no scenes have been loaded yet


Changes in Pannellum 2.4.0
--------------------------

New Features:

- Translation support
- Event for when scene change fade completes (`scenechangefadedone`)
- Events for touch starts and ends (`touchstart` and `touchend`)
- Added ability to set custom animation timing
function (`animationTimingFunction` parameter)
- Added option for only enable mouse wheel zoom while in
fullscreen (`mouseZoom` parameter)
- Added option to set title and author displayed while the load button
is displayed (`previewTitle` and `previewAuthor` parameters)
- Mouse and touch dragging can now be disabled (`draggable` parameter)
- Added option to disable keyboard controls (`disableKeyboardCtrl` parameter)
- CORS setting can now be configured

New API functions:

- Check if image is loaded (`isLoaded`)
- Method to update viewer after it is resized (`resize`)
- Set horizon pitch and roll (`setPose`)
- Turn device orientation control on and off, check if it is supported, and
check if it is activated (`startOrientation`, `stopOrientation`,
`isOrientationSupported`, and `isOrientationActive`)
- Method to retrieve viewer's container element (`getContainer`)

Improvements:

- Double-clicking now causes the viewer to zoom in (and back out when
double-clicking while zoomed in)
- New lines are now allowed in hot spot text
- Support for HTML in configuration strings can be enabled when using
the API (`escapeHTML` parameter)
- Fallback cursor is provided for browsers that don't support SVG data URIs
- Image type configuration parameter is now validated
- Optional callbacks added to `lookAt`, `setPitch`, `setYaw`, and `setHfov`
API functions
- Scroll events are now only captured when they're being used
- Viewer object is now assigned to a variable in the standalone viewer
- Hot spots can now be added with API before panorama is loaded
- Viewer UI is now created in a container element

Bugfixes:

- Fixed race condition when scene change hot spot is double-clicked
- Fixed bug with preview image absolute URLs
- Removed redundant constraints on yaw in API
- Tabbing now works, and only events for keys that are used are captured
- Fixed bug in HTML escaping
- Fixed bug that sometimes occurred when `orientationOnByDefault` was `true`
- Yaw no longer changes when device orientation mode is activated
- Fixed iOS 10 canvas size too big issue
- Fixed iOS 10 NPOT cube map issue
- Hot spots added via API are now permanent between scene changes
- Fixed multiple bugs with removing event listeners
- Fixed bug with multiresolution tile loading
- Fixed `sameAzimuth` target yaw not working when `northOffset` wasn't set
- Fixed bug yaw out of bounds in `mouseEventToCoords`
- Fixed bug with `animateMove` function
- Fixed bug with scene change fade
- Yaw animation is now always in the shortest direction
- Fixed bug related to removing hot spots


Changes in Pannellum 2.3.2
--------------------------



+ 19
- 1
doc/json-config-parameters.md 查看文件

@@ -115,6 +115,11 @@ the fullscreen API.
If set to `false`, no controls are displayed. Defaults to `true`.


### `touchPanSpeedCoeffFactor` (number)

Adjusts panning speed from touch inputs. Defaults to `1`.


### `yaw` (number)

Sets the panorama's starting yaw position in degrees. Defaults to `0`.
@@ -198,6 +203,12 @@ the configuration is provided via the URL; it defaults to `false` but can be
set to `true` when using the API.


### `crossOrigin` (string)

This specifies the type of CORS request used and can be set to either
`anonymous` or `use-credentials`. Defaults to `anonymous`.


### `hotSpots` (array)

This specifies an array of hot spots that can be links to other scenes,
@@ -251,7 +262,9 @@ maintain the same direction with regard to north.

#### `targetHfov` (number)

Specifies the HFOV of the target scene, in degrees.
Specifies the HFOV of the target scene, in degrees. Can also be set to `same`,
which uses the current HFOV of the current scene as the initial HFOV of the
target scene.

#### `id`

@@ -285,6 +298,11 @@ Specifies the fade duration, in milliseconds, when transitioning between
scenes. Not defined by default. Only applicable for tours. Only works with
WebGL renderer.

### `capturedKeyNumbers` (array)

Specifies the key numbers that are captured in key events. Defaults to the
standard keys that are used by the viewer.



## `equirectangular` specific options


+ 1
- 1
package.json 查看文件

@@ -1,7 +1,7 @@
{
"name": "pannellum",
"description": "Pannellum is a lightweight, free, and open source panorama viewer for the web.",
"version": "2.3.2",
"version": "2.4.1",
"bugs": {
"url": "https://github.com/mpetroff/pannellum/issues"
},


+ 1
- 0
src/css/pannellum.css 查看文件

@@ -17,6 +17,7 @@
outline: 0;
line-height: 1.4;
contain: content;
touch-action: none;
}

.pnlm-container * {


+ 34
- 17
src/js/libpannellum.js 查看文件

@@ -1,6 +1,6 @@
/*
* libpannellum - A WebGL and CSS 3D transform based Panorama Renderer
* Copyright (c) 2012-2017 Matthew Petroff
* Copyright (c) 2012-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
@@ -42,6 +42,7 @@ function Renderer(container) {
var pose;
var image, imageType, dynamic;
var texCoordBuffer, cubeVertBuf, cubeVertTexCoordBuf, cubeVertIndBuf;
var globalParams;

/**
* Initialize renderer.
@@ -63,7 +64,7 @@ function Renderer(container) {
*/
this.init = function(_image, _imageType, _dynamic, haov, vaov, voffset, callback, params) {
// Default argument for image type
if (typeof _imageType === undefined)
if (_imageType === undefined)
_imageType = 'equirectangular';

if (_imageType != 'equirectangular' && _imageType != 'cubemap' &&
@@ -75,6 +76,7 @@ function Renderer(container) {
imageType = _imageType;
image = _image;
dynamic = _dynamic;
globalParams = params || {};

// Clear old data
if (program) {
@@ -204,6 +206,13 @@ function Renderer(container) {
// Draw image width duplicated edge pixels on canvas
faceContext.putImageData(imgData, 0, 0);
incLoaded();
};
var incLoaded = function() {
if (this.width != 0) // support partial fallback/cubemap image
fallbackImgSize = this.width;
if (loaded == 5 && this.width == 0) // support partial fallback/cubemap image
this.width = fallbackImgSize;
loaded++;
if (loaded == 6) {
fallbackImgSize = this.width;
@@ -213,9 +222,10 @@ function Renderer(container) {
};
for (s = 0; s < 6; s++) {
var faceImg = new Image();
faceImg.crossOrigin = 'anonymous';
faceImg.crossOrigin = globalParams.crossOrigin ? globalParams.crossOrigin : 'anonymous';
faceImg.side = s;
faceImg.onload = onLoad;
faceImg.onerror = incLoaded; // ignore missing face file to support partial fallback/cubemap image
if (imageType == 'multires') {
faceImg.src = encodeURI(path.replace('%s', sides[s]) + '.' + image.extension);
} else {
@@ -325,7 +335,7 @@ function Renderer(container) {

// Pass aspect ratio
program.aspectRatio = gl.getUniformLocation(program, 'u_aspectRatio');
gl.uniform1f(program.aspectRatio, canvas.clientWidth / canvas.clientHeight);
gl.uniform1f(program.aspectRatio, gl.drawingBufferWidth / gl.drawingBufferHeight);

// Locate psi, theta, focal length, horizontal extent, vertical extent, and vertical offset
program.psi = gl.getUniformLocation(program, 'u_psi');
@@ -534,22 +544,24 @@ function Renderer(container) {
r: 'translate3d(' + s + 'px, -' + (s + 2) + 'px, -' + (s + 2) + 'px) rotateY(270deg)'
};
focal = 1 / Math.tan(hfov / 2);
var zoom = focal * canvas.clientWidth / 2 + 'px';
var zoom = focal * gl.drawingBufferWidth / 2 + 'px';
var transform = 'perspective(' + zoom + ') translateZ(' + zoom + ') rotateX(' + pitch + 'rad) rotateY(' + yaw + 'rad) ';
// Apply face transforms
var faces = Object.keys(transforms);
for (i = 0; i < 6; i++) {
var face = world.querySelector('.pnlm-' + faces[i] + 'face').style;
face.webkitTransform = transform + transforms[faces[i]];
face.transform = transform + transforms[faces[i]];
var face = world.querySelector('.pnlm-' + faces[i] + 'face');
if (!face)
continue; // ignore missing face to support partial fallback/cubemap image
face.style.webkitTransform = transform + transforms[faces[i]];
face.style.transform = transform + transforms[faces[i]];
}
return;
}
if (imageType != 'multires') {
// Calculate focal length from vertical field of view
var vfov = 2 * Math.atan(Math.tan(hfov * 0.5) / (canvas.clientWidth / canvas.clientHeight));
var vfov = 2 * Math.atan(Math.tan(hfov * 0.5) / (gl.drawingBufferWidth / gl.drawingBufferHeight));
focal = 1 / Math.tan(vfov * 0.5);

// Pass psi, theta, roll, and focal length
@@ -571,7 +583,7 @@ function Renderer(container) {
} else {
// Create perspective matrix
var perspMatrix = makePersp(hfov, canvas.clientWidth / canvas.clientHeight, 0.1, 100.0);
var perspMatrix = makePersp(hfov, gl.drawingBufferWidth / gl.drawingBufferHeight, 0.1, 100.0);
// Find correct zoom level
checkZoom(hfov);
@@ -984,7 +996,7 @@ function Renderer(container) {
* @returns {number[]} Generated perspective matrix.
*/
function makePersp(hfov, aspect, znear, zfar) {
var fovy = 2 * Math.atan(Math.tan(hfov/2) * canvas.clientHeight / canvas.clientWidth);
var fovy = 2 * Math.atan(Math.tan(hfov/2) * gl.drawingBufferHeight / gl.drawingBufferWidth);
var f = 1 / Math.tan(fovy/2);
return [
f/aspect, 0, 0, 0,
@@ -1015,17 +1027,21 @@ function Renderer(container) {
var cacheTop = 4; // Maximum number of concurrents loads
var textureImageCache = {};
var pendingTextureRequests = [];
var crossOrigin;

function TextureImageLoader() {
var self = this;
this.texture = this.callback = null;
this.image = new Image();
this.image.crossOrigin = 'anonymous';
this.image.addEventListener('load', function() {
processLoadedTexture(self.image, self.texture);
this.image.crossOrigin = crossOrigin ? crossOrigin : 'anonymous';
var loadFn = (function() {
if (self.image.width > 0 && self.image.height > 0) // ignore missing tile to supporting partial image
processLoadedTexture(self.image, self.texture);
self.callback(self.texture);
releaseTextureImageLoader(self);
});
this.image.addEventListener('load', loadFn);
this.image.addEventListener('error', loadFn); // ignore missing tile file to support partial image, otherwise retry loop causes high CPU load
};

TextureImageLoader.prototype.loadTexture = function(src, texture, callback) {
@@ -1051,7 +1067,8 @@ function Renderer(container) {
for (var i = 0; i < cacheTop; i++)
textureImageCache[i] = new TextureImageLoader();

return function(src, callback) {
return function(src, callback, _crossOrigin) {
crossOrigin = _crossOrigin;
var texture = gl.createTexture();
if (cacheTop)
textureImageCache[--cacheTop].loadTexture(src, texture, callback);
@@ -1072,7 +1089,7 @@ function Renderer(container) {
loadTexture(encodeURI(node.path + '.' + image.extension), function(texture) {
node.texture = texture;
node.textureLoaded = true;
});
}, globalParams.crossOrigin);
}
}
@@ -1085,7 +1102,7 @@ function Renderer(container) {
// Find optimal level
var newLevel = 1;
while ( newLevel < image.maxLevel &&
canvas.width > image.tileResolution *
gl.drawingBufferWidth > image.tileResolution *
Math.pow(2, newLevel - 1) * Math.tan(hfov / 2) * 0.707 ) {
newLevel++;
}


+ 48
- 21
src/js/pannellum.js 查看文件

@@ -1,6 +1,6 @@
/*
* Pannellum - An HTML5 based Panorama Viewer
* Copyright (c) 2011-2017 Matthew Petroff
* 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
@@ -50,7 +50,7 @@ var config,
onPointerDownPitch = 0,
keysDown = new Array(10),
fullscreenActive = false,
loaded = false,
loaded,
error = false,
isTimedOut = false,
listenersAdded = false,
@@ -105,6 +105,9 @@ var defaultConfig = {
animationTimingFunction: timingFunction,
draggable: true,
disableKeyboardCtrl: false,
crossOrigin: 'anonymous',
touchPanSpeedCoeffFactor: 1,
capturedKeyNumbers: [16, 17, 27, 37, 38, 39, 40, 61, 65, 68, 83, 87, 107, 109, 173, 187, 189],
};

// Translatable / configurable strings
@@ -131,8 +134,6 @@ defaultConfig.strings = {
unknownError: 'Unknown error. Check developer console.',
}

var usedKeyNumbers = [16, 17, 27, 37, 38, 39, 40, 61, 65, 68, 83, 87, 107, 109, 173, 187, 189];

// Initialize container
container = typeof container === 'string' ? document.getElementById(container) : container;
container.classList.add('pnlm-container');
@@ -311,7 +312,7 @@ function init() {
panoImage = [];
for (i = 0; i < 6; i++) {
panoImage.push(new Image());
panoImage[i].crossOrigin = 'anonymous';
panoImage[i].crossOrigin = config.crossOrigin;
}
infoDisplay.load.lbox.style.display = 'block';
infoDisplay.load.lbar.style.display = 'none';
@@ -438,6 +439,7 @@ function init() {
}
xhr.responseType = 'blob';
xhr.setRequestHeader('Accept', 'image/*,*/*;q=0.9');
xhr.withCredentials = config.crossOrigin === 'use-credentials';
xhr.send();
}
}
@@ -498,13 +500,17 @@ function onImageLoad() {
container.addEventListener('blur', clearKeys, false);
}
document.addEventListener('mouseleave', onDocumentMouseUp, false);
dragFix.addEventListener('touchstart', onDocumentTouchStart, false);
dragFix.addEventListener('touchmove', onDocumentTouchMove, false);
dragFix.addEventListener('touchend', onDocumentTouchEnd, false);
dragFix.addEventListener('pointerdown', onDocumentPointerDown, false);
dragFix.addEventListener('pointermove', onDocumentPointerMove, false);
dragFix.addEventListener('pointerup', onDocumentPointerUp, false);
dragFix.addEventListener('pointerleave', onDocumentPointerUp, false);
if (document.documentElement.style.pointerAction === '' &&
document.documentElement.style.touchAction === '') {
dragFix.addEventListener('pointerdown', onDocumentPointerDown, false);
dragFix.addEventListener('pointermove', onDocumentPointerMove, false);
dragFix.addEventListener('pointerup', onDocumentPointerUp, false);
dragFix.addEventListener('pointerleave', onDocumentPointerUp, false);
} else {
dragFix.addEventListener('touchstart', onDocumentTouchStart, false);
dragFix.addEventListener('touchmove', onDocumentTouchMove, false);
dragFix.addEventListener('touchend', onDocumentTouchEnd, false);
}

// Deal with MS pointer events
if (window.navigator.pointerEnabled)
@@ -899,7 +905,7 @@ function onDocumentTouchMove(event) {
//
// Currently this seems to *roughly* keep initial drag/pan start position close to
// the user's finger while panning regardless of zoom level / config.hfov value.
var touchmovePanSpeedCoeff = config.hfov / 360;
var touchmovePanSpeedCoeff = (config.hfov / 360) * config.touchPanSpeedCoeffFactor;

var yaw = (onPointerDownPointerX - clientX) * touchmovePanSpeedCoeff + onPointerDownYaw;
speed.yaw = (yaw - config.yaw) % 360 * 0.2;
@@ -960,7 +966,7 @@ function onDocumentPointerMove(event) {
pointerCoordinates[i].clientY = event.clientY;
event.targetTouches = pointerCoordinates;
onDocumentTouchMove(event);
//event.preventDefault();
event.preventDefault();
return;
}
}
@@ -1045,8 +1051,8 @@ function onDocumentKeyPress(event) {
var keynumber = event.which || event.keycode;

// Override default action for keys that are used
if (usedKeyNumbers.indexOf(keynumber) < 0)
return
if (config.capturedKeyNumbers.indexOf(keynumber) < 0)
return;
event.preventDefault();
// If escape key is pressed
@@ -1081,8 +1087,8 @@ function onDocumentKeyUp(event) {
var keynumber = event.which || event.keycode;
// Override default action for keys that are used
if (usedKeyNumbers.indexOf(keynumber) < 0)
return
if (config.capturedKeyNumbers.indexOf(keynumber) < 0)
return;
event.preventDefault();
// Change key
@@ -1300,7 +1306,7 @@ function keyRepeat() {
}
// Stop movement if opposite controls are pressed
if (keysDown[0] && keysDown[0]) {
if (keysDown[0] && keysDown[1]) {
speed.hfov = 0;
}
if ((keysDown[2] || keysDown[6]) && (keysDown[3] || keysDown[7])) {
@@ -2272,6 +2278,7 @@ function load() {
// since it is a new scene and the error from previous maybe because of lacking
// memory etc and not because of a lack of WebGL support etc
clearError();
loaded = false;

controls.load.style.display = 'none';
infoDisplay.load.box.style.display = 'inline';
@@ -2399,7 +2406,7 @@ function escapeHTML(s) {
* @returns {boolean} `true` if a panorama is loaded, else `false`
*/
this.isLoaded = function() {
return loaded;
return Boolean(loaded);
};

/**
@@ -2821,7 +2828,7 @@ this.mouseEventToCoords = function(event) {
* @returns {Viewer} `this`
*/
this.loadScene = function(sceneId, pitch, yaw, hfov) {
if (loaded)
if (loaded !== false)
loadScene(sceneId, pitch, yaw, hfov);
return this;
}
@@ -2885,6 +2892,16 @@ this.getConfig = function() {
}

/**
* Get viewer's container element.
* @memberof Viewer
* @instance
* @returns {HTMLElement} Container `div` element
*/
this.getContainer = function() {
return container;
}

/**
* Add a new hot spot.
* @memberof Viewer
* @instance
@@ -2996,6 +3013,16 @@ this.startOrientation = function() {
}

/**
* Check if device orientation control is currently activated.
* @memberof Viewer
* @instance
* @returns {boolean} True if active, else false
*/
this.isOrientationActive = function() {
return Boolean(orientation);
}

/**
* Subscribe listener to specified event.
* @memberof Viewer
* @instance


+ 1
- 1
utils/multires/generate.py 查看文件

@@ -4,7 +4,7 @@
# and nona (from Hugin)

# generate.py - A multires tile set generator for Pannellum
# Copyright (c) 2014-2017 Matthew Petroff
# Copyright (c) 2014-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


+ 1
- 1
utils/video/videojs-pannellum-plugin.js 查看文件

@@ -1,6 +1,6 @@
/*
* Video.js plugin for Pannellum
* Copyright (c) 2015-2017 Matthew Petroff
* Copyright (c) 2015-2018 Matthew Petroff
* MIT License
*/



Loading…
取消
儲存