xl-pano
Version:
一个基于 Typescript 的,同时支持立方体和球体场景的轻量开源库。
1,452 lines (1,327 loc) • 116 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["XLPano"] = factory();
else
root["XLPano"] = factory();
})(self, function() {
return /******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ "./src/shader/cube/index.frag":
/*!************************************!*\
!*** ./src/shader/cube/index.frag ***!
\************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("precision mediump float;\n\nuniform sampler2D f_Sampler;\nuniform sampler2D r_Sampler;\nuniform sampler2D u_Sampler;\nuniform sampler2D l_Sampler;\nuniform sampler2D d_Sampler;\nuniform sampler2D b_Sampler;\nvarying vec2 v_TexCoord;\n// 标记每个面 0-f 1-r 2-u 3-l 4-d 5-b\nuniform int u_Face;\n\nvoid main() {\n if (u_Face == 0) {\n gl_FragColor = texture2D(f_Sampler, v_TexCoord);\n } else if (u_Face == 1) {\n gl_FragColor = texture2D(r_Sampler, v_TexCoord);\n } else if (u_Face == 2) {\n gl_FragColor = texture2D(u_Sampler, v_TexCoord);\n } else if (u_Face == 3) {\n gl_FragColor = texture2D(l_Sampler, v_TexCoord);\n } else if (u_Face == 4) {\n gl_FragColor = texture2D(d_Sampler, v_TexCoord);\n } else {\n gl_FragColor = texture2D(b_Sampler, v_TexCoord);\n }\n}\n");
/***/ }),
/***/ "./src/shader/cube/index.vert":
/*!************************************!*\
!*** ./src/shader/cube/index.vert ***!
\************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("attribute vec4 a_Position;\nattribute vec2 a_TexCoord;\nvarying vec2 v_TexCoord;\nuniform mat4 u_MvpMatrix;\n\nvoid main() {\n gl_Position = u_MvpMatrix * a_Position;\n v_TexCoord = a_TexCoord;\n}\n");
/***/ }),
/***/ "./src/shader/sphere/index.frag":
/*!**************************************!*\
!*** ./src/shader/sphere/index.frag ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("precision mediump float;\n\nuniform sampler2D u_Sampler;\nvarying vec2 v_TexCoord;\n\nvoid main() {\n gl_FragColor = texture2D(u_Sampler, v_TexCoord);\n}\n");
/***/ }),
/***/ "./src/shader/sphere/index.vert":
/*!**************************************!*\
!*** ./src/shader/sphere/index.vert ***!
\**************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("attribute vec4 a_Position;\nattribute vec2 a_TexCoord;\nvarying vec2 v_TexCoord;\nuniform mat4 u_MvpMatrix;\n\nvoid main() {\n gl_Position = u_MvpMatrix * a_Position;\n v_TexCoord = a_TexCoord;\n}\n");
/***/ }),
/***/ "./src/utils/webgl-debug.js":
/*!**********************************!*\
!*** ./src/utils/webgl-debug.js ***!
\**********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
const WebGLDebugUtils = function() {
/**
* Wrapped logging function.
* @param {string} msg Message to log.
*/
var log = function(msg) {
if (window.console && window.console.log) {
window.console.log(msg);
}
};
/**
* Which arguements are enums.
* @type {!Object.<number, string>}
*/
var glValidEnumContexts = {
// Generic setters and getters
'enable': { 0:true },
'disable': { 0:true },
'getParameter': { 0:true },
// Rendering
'drawArrays': { 0:true },
'drawElements': { 0:true, 2:true },
// Shaders
'createShader': { 0:true },
'getShaderParameter': { 1:true },
'getProgramParameter': { 1:true },
// Vertex attributes
'getVertexAttrib': { 1:true },
'vertexAttribPointer': { 2:true },
// Textures
'bindTexture': { 0:true },
'activeTexture': { 0:true },
'getTexParameter': { 0:true, 1:true },
'texParameterf': { 0:true, 1:true },
'texParameteri': { 0:true, 1:true, 2:true },
'texImage2D': { 0:true, 2:true, 6:true, 7:true },
'texSubImage2D': { 0:true, 6:true, 7:true },
'copyTexImage2D': { 0:true, 2:true },
'copyTexSubImage2D': { 0:true },
'generateMipmap': { 0:true },
// Buffer objects
'bindBuffer': { 0:true },
'bufferData': { 0:true, 2:true },
'bufferSubData': { 0:true },
'getBufferParameter': { 0:true, 1:true },
// Renderbuffers and framebuffers
'pixelStorei': { 0:true, 1:true },
'readPixels': { 4:true, 5:true },
'bindRenderbuffer': { 0:true },
'bindFramebuffer': { 0:true },
'checkFramebufferStatus': { 0:true },
'framebufferRenderbuffer': { 0:true, 1:true, 2:true },
'framebufferTexture2D': { 0:true, 1:true, 2:true },
'getFramebufferAttachmentParameter': { 0:true, 1:true, 2:true },
'getRenderbufferParameter': { 0:true, 1:true },
'renderbufferStorage': { 0:true, 1:true },
// Frame buffer operations (clear, blend, depth test, stencil)
'clear': { 0:true },
'depthFunc': { 0:true },
'blendFunc': { 0:true, 1:true },
'blendFuncSeparate': { 0:true, 1:true, 2:true, 3:true },
'blendEquation': { 0:true },
'blendEquationSeparate': { 0:true, 1:true },
'stencilFunc': { 0:true },
'stencilFuncSeparate': { 0:true, 1:true },
'stencilMaskSeparate': { 0:true },
'stencilOp': { 0:true, 1:true, 2:true },
'stencilOpSeparate': { 0:true, 1:true, 2:true, 3:true },
// Culling
'cullFace': { 0:true },
'frontFace': { 0:true },
};
/**
* Map of numbers to names.
* @type {Object}
*/
var glEnums = null;
/**
* Initializes this module. Safe to call more than once.
* @param {!WebGLRenderingContext} ctx A WebGL context. If
* you have more than one context it doesn't matter which one
* you pass in, it is only used to pull out constants.
*/
function init(ctx) {
if (glEnums == null) {
glEnums = { };
for (var propertyName in ctx) {
if (typeof ctx[propertyName] == 'number') {
glEnums[ctx[propertyName]] = propertyName;
}
}
}
}
/**
* Checks the utils have been initialized.
*/
function checkInit() {
if (glEnums == null) {
throw 'WebGLDebugUtils.init(ctx) not called';
}
}
/**
* Returns true or false if value matches any WebGL enum
* @param {*} value Value to check if it might be an enum.
* @return {boolean} True if value matches one of the WebGL defined enums
*/
function mightBeEnum(value) {
checkInit();
return (glEnums[value] !== undefined);
}
/**
* Gets an string version of an WebGL enum.
*
* Example:
* var str = WebGLDebugUtil.glEnumToString(ctx.getError());
*
* @param {number} value Value to return an enum for
* @return {string} The string version of the enum.
*/
function glEnumToString(value) {
checkInit();
var name = glEnums[value];
return (name !== undefined) ? name :
("*UNKNOWN WebGL ENUM (0x" + value.toString(16) + ")");
}
/**
* Returns the string version of a WebGL argument.
* Attempts to convert enum arguments to strings.
* @param {string} functionName the name of the WebGL function.
* @param {number} argumentIndx the index of the argument.
* @param {*} value The value of the argument.
* @return {string} The value as a string.
*/
function glFunctionArgToString(functionName, argumentIndex, value) {
var funcInfo = glValidEnumContexts[functionName];
if (funcInfo !== undefined) {
if (funcInfo[argumentIndex]) {
return glEnumToString(value);
}
}
return value.toString();
}
/**
* Given a WebGL context returns a wrapped context that calls
* gl.getError after every command and calls a function if the
* result is not gl.NO_ERROR.
*
* @param {!WebGLRenderingContext} ctx The webgl context to
* wrap.
* @param {!function(err, funcName, args): void} opt_onErrorFunc
* The function to call when gl.getError returns an
* error. If not specified the default function calls
* console.log with a message.
*/
function makeDebugContext(ctx, opt_onErrorFunc) {
init(ctx);
opt_onErrorFunc = opt_onErrorFunc || function(err, functionName, args) {
// apparently we can't do args.join(",");
var argStr = "";
for (var ii = 0; ii < args.length; ++ii) {
argStr += ((ii == 0) ? '' : ', ') +
glFunctionArgToString(functionName, ii, args[ii]);
}
log("WebGL error "+ glEnumToString(err) + " in "+ functionName +
"(" + argStr + ")");
};
// Holds booleans for each GL error so after we get the error ourselves
// we can still return it to the client app.
var glErrorShadow = { };
// Makes a function that calls a WebGL function and then calls getError.
function makeErrorWrapper(ctx, functionName) {
return function() {
var result = ctx[functionName].apply(ctx, arguments);
var err = ctx.getError();
if (err != 0) {
glErrorShadow[err] = true;
opt_onErrorFunc(err, functionName, arguments);
}
return result;
};
}
// Make a an object that has a copy of every property of the WebGL context
// but wraps all functions.
var wrapper = {};
for (var propertyName in ctx) {
if (typeof ctx[propertyName] == 'function') {
wrapper[propertyName] = makeErrorWrapper(ctx, propertyName);
} else {
wrapper[propertyName] = ctx[propertyName];
}
}
// Override the getError function with one that returns our saved results.
wrapper.getError = function() {
for (var err in glErrorShadow) {
if (glErrorShadow[err]) {
glErrorShadow[err] = false;
return err;
}
}
return ctx.NO_ERROR;
};
return wrapper;
}
function resetToInitialState(ctx) {
var numAttribs = ctx.getParameter(ctx.MAX_VERTEX_ATTRIBS);
var tmp = ctx.createBuffer();
ctx.bindBuffer(ctx.ARRAY_BUFFER, tmp);
for (var ii = 0; ii < numAttribs; ++ii) {
ctx.disableVertexAttribArray(ii);
ctx.vertexAttribPointer(ii, 4, ctx.FLOAT, false, 0, 0);
ctx.vertexAttrib1f(ii, 0);
}
ctx.deleteBuffer(tmp);
var numTextureUnits = ctx.getParameter(ctx.MAX_TEXTURE_IMAGE_UNITS);
for (var ii = 0; ii < numTextureUnits; ++ii) {
ctx.activeTexture(ctx.TEXTURE0 + ii);
ctx.bindTexture(ctx.TEXTURE_CUBE_MAP, null);
ctx.bindTexture(ctx.TEXTURE_2D, null);
}
ctx.activeTexture(ctx.TEXTURE0);
ctx.useProgram(null);
ctx.bindBuffer(ctx.ARRAY_BUFFER, null);
ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, null);
ctx.bindFramebuffer(ctx.FRAMEBUFFER, null);
ctx.bindRenderbuffer(ctx.RENDERBUFFER, null);
ctx.disable(ctx.BLEND);
ctx.disable(ctx.CULL_FACE);
ctx.disable(ctx.DEPTH_TEST);
ctx.disable(ctx.DITHER);
ctx.disable(ctx.SCISSOR_TEST);
ctx.blendColor(0, 0, 0, 0);
ctx.blendEquation(ctx.FUNC_ADD);
ctx.blendFunc(ctx.ONE, ctx.ZERO);
ctx.clearColor(0, 0, 0, 0);
ctx.clearDepth(1);
ctx.clearStencil(-1);
ctx.colorMask(true, true, true, true);
ctx.cullFace(ctx.BACK);
ctx.depthFunc(ctx.LESS);
ctx.depthMask(true);
ctx.depthRange(0, 1);
ctx.frontFace(ctx.CCW);
ctx.hint(ctx.GENERATE_MIPMAP_HINT, ctx.DONT_CARE);
ctx.lineWidth(1);
ctx.pixelStorei(ctx.PACK_ALIGNMENT, 4);
ctx.pixelStorei(ctx.UNPACK_ALIGNMENT, 4);
ctx.pixelStorei(ctx.UNPACK_FLIP_Y_WEBGL, false);
ctx.pixelStorei(ctx.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
// TODO: Delete this IF.
if (ctx.UNPACK_COLORSPACE_CONVERSION_WEBGL) {
ctx.pixelStorei(ctx.UNPACK_COLORSPACE_CONVERSION_WEBGL, ctx.BROWSER_DEFAULT_WEBGL);
}
ctx.polygonOffset(0, 0);
ctx.sampleCoverage(1, false);
ctx.scissor(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.stencilFunc(ctx.ALWAYS, 0, 0xFFFFFFFF);
ctx.stencilMask(0xFFFFFFFF);
ctx.stencilOp(ctx.KEEP, ctx.KEEP, ctx.KEEP);
ctx.viewport(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight);
ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT | ctx.STENCIL_BUFFER_BIT);
// TODO: This should NOT be needed but Firefox fails with 'hint'
while(ctx.getError());
}
function makeLostContextSimulatingContext(ctx) {
var wrapper_ = {};
var contextId_ = 1;
var contextLost_ = false;
var resourceId_ = 0;
var resourceDb_ = [];
var onLost_ = undefined;
var onRestored_ = undefined;
var nextOnRestored_ = undefined;
// Holds booleans for each GL error so can simulate errors.
var glErrorShadow_ = { };
function isWebGLObject(obj) {
//return false;
return (obj instanceof WebGLBuffer ||
obj instanceof WebGLFramebuffer ||
obj instanceof WebGLProgram ||
obj instanceof WebGLRenderbuffer ||
obj instanceof WebGLShader ||
obj instanceof WebGLTexture);
}
function checkResources(args) {
for (var ii = 0; ii < args.length; ++ii) {
var arg = args[ii];
if (isWebGLObject(arg)) {
return arg.__webglDebugContextLostId__ == contextId_;
}
}
return true;
}
function clearErrors() {
var k = Object.keys(glErrorShadow_);
for (var ii = 0; ii < k.length; ++ii) {
delete glErrorShdow_[k];
}
}
// Makes a function that simulates WebGL when out of context.
function makeLostContextWrapper(ctx, functionName) {
var f = ctx[functionName];
return function() {
// Only call the functions if the context is not lost.
if (!contextLost_) {
if (!checkResources(arguments)) {
glErrorShadow_[ctx.INVALID_OPERATION] = true;
return;
}
var result = f.apply(ctx, arguments);
return result;
}
};
}
for (var propertyName in ctx) {
if (typeof ctx[propertyName] == 'function') {
wrapper_[propertyName] = makeLostContextWrapper(ctx, propertyName);
} else {
wrapper_[propertyName] = ctx[propertyName];
}
}
function makeWebGLContextEvent(statusMessage) {
return {statusMessage: statusMessage};
}
function freeResources() {
for (var ii = 0; ii < resourceDb_.length; ++ii) {
var resource = resourceDb_[ii];
if (resource instanceof WebGLBuffer) {
ctx.deleteBuffer(resource);
} else if (resource instanceof WebctxFramebuffer) {
ctx.deleteFramebuffer(resource);
} else if (resource instanceof WebctxProgram) {
ctx.deleteProgram(resource);
} else if (resource instanceof WebctxRenderbuffer) {
ctx.deleteRenderbuffer(resource);
} else if (resource instanceof WebctxShader) {
ctx.deleteShader(resource);
} else if (resource instanceof WebctxTexture) {
ctx.deleteTexture(resource);
}
}
}
wrapper_.loseContext = function() {
if (!contextLost_) {
contextLost_ = true;
++contextId_;
while (ctx.getError());
clearErrors();
glErrorShadow_[ctx.CONTEXT_LOST_WEBGL] = true;
setTimeout(function() {
if (onLost_) {
onLost_(makeWebGLContextEvent("context lost"));
}
}, 0);
}
};
wrapper_.restoreContext = function() {
if (contextLost_) {
if (onRestored_) {
setTimeout(function() {
freeResources();
resetToInitialState(ctx);
contextLost_ = false;
if (onRestored_) {
var callback = onRestored_;
onRestored_ = nextOnRestored_;
nextOnRestored_ = undefined;
callback(makeWebGLContextEvent("context restored"));
}
}, 0);
} else {
throw "You can not restore the context without a listener"
}
}
};
// Wrap a few functions specially.
wrapper_.getError = function() {
if (!contextLost_) {
var err;
while (err = ctx.getError()) {
glErrorShadow_[err] = true;
}
}
for (var err in glErrorShadow_) {
if (glErrorShadow_[err]) {
delete glErrorShadow_[err];
return err;
}
}
return ctx.NO_ERROR;
};
var creationFunctions = [
"createBuffer",
"createFramebuffer",
"createProgram",
"createRenderbuffer",
"createShader",
"createTexture"
];
for (var ii = 0; ii < creationFunctions.length; ++ii) {
var functionName = creationFunctions[ii];
wrapper_[functionName] = function(f) {
return function() {
if (contextLost_) {
return null;
}
var obj = f.apply(ctx, arguments);
obj.__webglDebugContextLostId__ = contextId_;
resourceDb_.push(obj);
return obj;
};
}(ctx[functionName]);
}
var functionsThatShouldReturnNull = [
"getActiveAttrib",
"getActiveUniform",
"getBufferParameter",
"getContextAttributes",
"getAttachedShaders",
"getFramebufferAttachmentParameter",
"getParameter",
"getProgramParameter",
"getProgramInfoLog",
"getRenderbufferParameter",
"getShaderParameter",
"getShaderInfoLog",
"getShaderSource",
"getTexParameter",
"getUniform",
"getUniformLocation",
"getVertexAttrib"
];
for (var ii = 0; ii < functionsThatShouldReturnNull.length; ++ii) {
var functionName = functionsThatShouldReturnNull[ii];
wrapper_[functionName] = function(f) {
return function() {
if (contextLost_) {
return null;
}
return f.apply(ctx, arguments);
}
}(wrapper_[functionName]);
}
var isFunctions = [
"isBuffer",
"isEnabled",
"isFramebuffer",
"isProgram",
"isRenderbuffer",
"isShader",
"isTexture"
];
for (var ii = 0; ii < isFunctions.length; ++ii) {
var functionName = isFunctions[ii];
wrapper_[functionName] = function(f) {
return function() {
if (contextLost_) {
return false;
}
return f.apply(ctx, arguments);
}
}(wrapper_[functionName]);
}
wrapper_.checkFramebufferStatus = function(f) {
return function() {
if (contextLost_) {
return ctx.FRAMEBUFFER_UNSUPPORTED;
}
return f.apply(ctx, arguments);
};
}(wrapper_.checkFramebufferStatus);
wrapper_.getAttribLocation = function(f) {
return function() {
if (contextLost_) {
return -1;
}
return f.apply(ctx, arguments);
};
}(wrapper_.getAttribLocation);
wrapper_.getVertexAttribOffset = function(f) {
return function() {
if (contextLost_) {
return 0;
}
return f.apply(ctx, arguments);
};
}(wrapper_.getVertexAttribOffset);
wrapper_.isContextLost = function() {
return contextLost_;
};
function wrapEvent(listener) {
if (typeof(listener) == "function") {
return listener;
} else {
return function(info) {
listener.handleEvent(info);
}
}
}
wrapper_.registerOnContextLostListener = function(listener) {
onLost_ = wrapEvent(listener);
};
wrapper_.registerOnContextRestoredListener = function(listener) {
if (contextLost_) {
nextOnRestored_ = wrapEvent(listener);
} else {
onRestored_ = wrapEvent(listener);
}
}
return wrapper_;
}
return {
/**
* Initializes this module. Safe to call more than once.
* @param {!WebGLRenderingContext} ctx A WebGL context. If
* you have more than one context it doesn't matter which one
* you pass in, it is only used to pull out constants.
*/
'init': init,
/**
* Returns true or false if value matches any WebGL enum
* @param {*} value Value to check if it might be an enum.
* @return {boolean} True if value matches one of the WebGL defined enums
*/
'mightBeEnum': mightBeEnum,
/**
* Gets an string version of an WebGL enum.
*
* Example:
* WebGLDebugUtil.init(ctx);
* var str = WebGLDebugUtil.glEnumToString(ctx.getError());
*
* @param {number} value Value to return an enum for
* @return {string} The string version of the enum.
*/
'glEnumToString': glEnumToString,
/**
* Converts the argument of a WebGL function to a string.
* Attempts to convert enum arguments to strings.
*
* Example:
* WebGLDebugUtil.init(ctx);
* var str = WebGLDebugUtil.glFunctionArgToString('bindTexture', 0, gl.TEXTURE_2D);
*
* would return 'TEXTURE_2D'
*
* @param {string} functionName the name of the WebGL function.
* @param {number} argumentIndx the index of the argument.
* @param {*} value The value of the argument.
* @return {string} The value as a string.
*/
'glFunctionArgToString': glFunctionArgToString,
/**
* Given a WebGL context returns a wrapped context that calls
* gl.getError after every command and calls a function if the
* result is not NO_ERROR.
*
* You can supply your own function if you want. For example, if you'd like
* an exception thrown on any GL error you could do this
*
* function throwOnGLError(err, funcName, args) {
* throw WebGLDebugUtils.glEnumToString(err) + " was caused by call to" +
* funcName;
* };
*
* ctx = WebGLDebugUtils.makeDebugContext(
* canvas.getContext("webgl"), throwOnGLError);
*
* @param {!WebGLRenderingContext} ctx The webgl context to wrap.
* @param {!function(err, funcName, args): void} opt_onErrorFunc The function
* to call when gl.getError returns an error. If not specified the default
* function calls console.log with a message.
*/
'makeDebugContext': makeDebugContext,
/**
* Given a WebGL context returns a wrapped context that adds 4
* functions.
*
* ctx.loseContext:
* simulates a lost context event.
*
* ctx.restoreContext:
* simulates the context being restored.
*
* ctx.registerOnContextLostListener(listener):
* lets you register a listener for context lost. Use instead
* of addEventListener('webglcontextlostevent', listener);
*
* ctx.registerOnContextRestoredListener(listener):
* lets you register a listener for context restored. Use
* instead of addEventListener('webglcontextrestored',
* listener);
*
* @param {!WebGLRenderingContext} ctx The webgl context to wrap.
*/
'makeLostContextSimulatingContext': makeLostContextSimulatingContext,
/**
* Resets a context to the initial state.
* @param {!WebGLRenderingContext} ctx The webgl context to
* reset.
*/
'resetToInitialState': resetToInitialState
};
}();
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (WebGLDebugUtils);
/***/ }),
/***/ "./src/utils/webgl-utils.js":
/*!**********************************!*\
!*** ./src/utils/webgl-utils.js ***!
\**********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
const WebGLUtils = function() {
/**
* Creates the HTLM for a failure message
* @param {string} canvasContainerId id of container of th
* canvas.
* @return {string} The html.
*/
var makeFailHTML = function(msg) {
return '' +
'<div style="margin: auto; width:500px;z-index:10000;margin-top:20em;text-align:center;">' + msg + '</div>';
return '' +
'<table style="background-color: #8CE; width: 100%; height: 100%;"><tr>' +
'<td align="center">' +
'<div style="display: table-cell; vertical-align: middle;">' +
'<div style="">' + msg + '</div>' +
'</div>' +
'</td></tr></table>';
};
/**
* Mesasge for getting a webgl browser
* @type {string}
*/
var GET_A_WEBGL_BROWSER = '' +
'This page requires a browser that supports WebGL.<br/>' +
'<a href="http://get.webgl.org">Click here to upgrade your browser.</a>';
/**
* Mesasge for need better hardware
* @type {string}
*/
var OTHER_PROBLEM = '' +
"It doesn't appear your computer can support WebGL.<br/>" +
'<a href="http://get.webgl.org">Click here for more information.</a>';
/**
* Creates a webgl context. If creation fails it will
* change the contents of the container of the <canvas>
* tag to an error message with the correct links for WebGL.
* @param {Element} canvas. The canvas element to create a
* context from.
* @param {WebGLContextCreationAttirbutes} opt_attribs Any
* creation attributes you want to pass in.
* @param {function:(msg)} opt_onError An function to call
* if there is an error during creation.
* @return {WebGLRenderingContext} The created context.
*/
var setupWebGL = function(canvas, opt_attribs, opt_onError) {
function handleCreationError(msg) {
var container = document.getElementsByTagName("body")[0];
//var container = canvas.parentNode;
if (container) {
var str = window.WebGLRenderingContext ?
OTHER_PROBLEM :
GET_A_WEBGL_BROWSER;
if (msg) {
str += "<br/><br/>Status: " + msg;
}
container.innerHTML = makeFailHTML(str);
}
};
opt_onError = opt_onError || handleCreationError;
if (canvas.addEventListener) {
canvas.addEventListener("webglcontextcreationerror", function(event) {
opt_onError(event.statusMessage);
}, false);
}
var context = create3DContext(canvas, opt_attribs);
if (!context) {
if (!window.WebGLRenderingContext) {
opt_onError("");
} else {
opt_onError("");
}
}
return context;
};
/**
* Creates a webgl context.
* @param {!Canvas} canvas The canvas tag to get context
* from. If one is not passed in one will be created.
* @return {!WebGLContext} The created context.
*/
var create3DContext = function(canvas, opt_attribs) {
var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
var context = null;
for (var ii = 0; ii < names.length; ++ii) {
try {
context = canvas.getContext(names[ii], opt_attribs);
} catch(e) {}
if (context) {
break;
}
}
return context;
}
return {
create3DContext: create3DContext,
setupWebGL: setupWebGL
};
}();
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (WebGLUtils);
/***/ }),
/***/ "./src/config/index.ts":
/*!*****************************!*\
!*** ./src/config/index.ts ***!
\*****************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "DefaultYRange": () => (/* binding */ DefaultYRange),
/* harmony export */ "DefaultFovy": () => (/* binding */ DefaultFovy),
/* harmony export */ "DefaultAnimDuration": () => (/* binding */ DefaultAnimDuration),
/* harmony export */ "DefaultMovingRate": () => (/* binding */ DefaultMovingRate)
/* harmony export */ });
// 默认俯仰可视范围角度
var DefaultYRange = [-86, 86];
// 默认静态可视范围角度
var DefaultFovy = 60;
// 所有动画默认执行时间
var DefaultAnimDuration = 500;
// 移动灵敏度
var DefaultMovingRate = 1.5;
/***/ }),
/***/ "./src/lib/CubeScene.ts":
/*!******************************!*\
!*** ./src/lib/CubeScene.ts ***!
\******************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _utils_process__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/process */ "./src/utils/process.ts");
/* harmony import */ var _resource__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./resource */ "./src/lib/resource.ts");
/* harmony import */ var _interface_BaseScene__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./interface/BaseScene */ "./src/lib/interface/BaseScene.ts");
var __extends = (undefined && undefined.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
/**
* 场景类,提供全景画面
* 立方体
* v6----- v5
* /| /|
* v1------v0|
* | | | |
* | |v7---|-|v4
* |/ |/
* v2------v3
* */
var CubeScene = /** @class */ (function (_super) {
__extends(CubeScene, _super);
/**
* @constructor 构造函数
* @param {string[]} textures 六个面的纹理图片,按照 f r u l d b 的顺序
* @param {SceneAngle} defaultAngle 默认展示角度
* */
function CubeScene(textures, defaultAngle) {
var _this = _super.call(this) || this;
/**
* @property {TextureSource[]} textures 六个面的纹理图片,按照 f r u l d b 的顺序
* */
_this.textures = [];
_this.textures = textures;
if (defaultAngle) {
var pitch = defaultAngle.pitch, yaw = defaultAngle.yaw;
if (pitch)
_this.pitch = pitch;
if (yaw)
_this.yaw = yaw;
}
return _this;
}
/**
* 将每个面的纹理贴图赋值给每个面的 sampler
* @param {WebGLRenderingContextWithProgram} gl WebGL 上下文
* @param {TexImageSource} image 图像资源
* @param {number} unit 每个面的编号 0-f 1-r 2-u 3-l 4-d 5-b
* */
CubeScene.initTexture = function (gl, image, unit) {
var texture = gl.createTexture();
if (!texture) {
throw new Error('创建纹理对象失败');
}
var texUnit = gl.TEXTURE0;
var samplerPrefix = 'f';
switch (unit) {
case 0:
texUnit = gl.TEXTURE0;
samplerPrefix = 'f';
break;
case 1:
texUnit = gl.TEXTURE1;
samplerPrefix = 'r';
break;
case 2:
texUnit = gl.TEXTURE2;
samplerPrefix = 'u';
break;
case 3:
texUnit = gl.TEXTURE3;
samplerPrefix = 'l';
break;
case 4:
texUnit = gl.TEXTURE4;
samplerPrefix = 'd';
break;
case 5:
texUnit = gl.TEXTURE5;
samplerPrefix = 'b';
break;
default:
break;
}
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
gl.activeTexture(texUnit);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
var u_Sampler = gl.getUniformLocation(gl.program, samplerPrefix + "_Sampler");
if (!u_Sampler) {
throw new Error("\u83B7\u53D6 " + u_Sampler + " \u5730\u5740\u5931\u8D25");
}
gl.uniform1i(u_Sampler, unit);
};
/**
* 获取 u_Face 缓存
* @param {WebGLRenderingContextWithProgram} gl WebGL 上下文
* @return {WebGLUniformLocation} u_Face 地址
* */
CubeScene.getUFaceLocation = function (gl) {
if (!CubeScene.u_Face) {
var u_Face = gl.getUniformLocation(gl.program, 'u_Face');
if (!u_Face) {
throw new Error('获取 u_Face 地址失败');
}
CubeScene.u_Face = u_Face;
}
return CubeScene.u_Face;
};
/**
* 渲染立方体
* */
CubeScene.prototype.drawModel = function () {
var _this = this;
CubeScene.allFacesIndices.forEach(function (faceIndices, index) {
_this.renderFace(faceIndices, index);
});
};
/**
* 加载纹理贴图
* @return {Promise<TexImageSource[]>} 图像资源
* */
CubeScene.prototype.loadTextures = function () {
// 交换前后,左右
var _a = this.textures, f = _a[0], r = _a[1], u = _a[2], l = _a[3], d = _a[4], b = _a[5];
var sourceOrder = [b, r, u, l, d, f];
// 删选出资源地址类型的,然后加载图片
var srcSources = [];
sourceOrder.forEach(function (source, index) {
if (typeof source === 'string') {
srcSources.push({
src: source,
index: index,
});
}
});
return (0,_resource__WEBPACK_IMPORTED_MODULE_1__.getTexImageSource)(srcSources.map(function (item) { return item.src; })).then(function (images) {
// 拼接返回所有的 TexImageSource 类型
return sourceOrder.map(function (source) {
if (typeof source === 'string') {
return images.shift();
}
else {
return source;
}
});
});
};
/**
* 渲染立方体的其中一面
* @param {Uint8Array} indices 该面的顶点索引
* @param {Unit} unit 每个面的编号
* */
CubeScene.prototype.renderFace = function (indices, unit) {
var gl = this.pano.gl;
var indexBuffer = gl.createBuffer();
if (!indexBuffer) {
throw new Error('创建索引缓冲区对象失败');
}
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
gl.uniform1i(CubeScene.getUFaceLocation(gl), unit);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_BYTE, 0);
};
/**
* 更改纹理重新渲染
* @param {TextureSource[]} textures 纹理资源集合,按照 f r u l d b 的顺序
* */
CubeScene.prototype.replaceTextures = function (textures) {
this.textures = textures;
this.render(this.pano);
};
/**
* 渲染到 pano
* @param {Pano} pano 父容器
* */
CubeScene.prototype.render = function (pano) {
var _this = this;
_super.prototype.render.call(this, pano);
var gl = this.pano.gl;
(0,_utils_process__WEBPACK_IMPORTED_MODULE_0__.initArrayBuffer)(gl, CubeScene.vertices, 3, gl.FLOAT, 'a_Position');
(0,_utils_process__WEBPACK_IMPORTED_MODULE_0__.initArrayBuffer)(gl, CubeScene.texs, 2, gl.FLOAT, 'a_TexCoord');
this.loadTextures().then(function (images) {
// [imgF, imgR, imgU, imgL, imgD, imgB]
images.forEach(function (img, index) {
if (index <= 5)
CubeScene.initTexture(gl, img, index);
});
_this.draw();
});
};
/**
* @static {Float32Array} vertices 立方体顶点坐标
* */
CubeScene.vertices = new Float32Array([
1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0,
1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0,
1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0,
-1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0,
-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0,
1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0 // v4-v7-v6-v5 back
]);
/**
* @static {Float32Array} texs 顶点对应的纹理坐标
* */
CubeScene.texs = new Float32Array([
0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0,
1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0,
1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0,
]);
/**
* @static {Uint8Array[]} allFacesIndices 六个面的顶点索引数组
* */
CubeScene.allFacesIndices = [
new Uint8Array([0, 1, 2, 0, 2, 3]),
new Uint8Array([4, 5, 6, 4, 6, 7]),
new Uint8Array([8, 9, 10, 8, 10, 11]),
new Uint8Array([12, 13, 14, 12, 14, 15]),
new Uint8Array([16, 17, 18, 16, 18, 19]),
new Uint8Array([20, 21, 22, 20, 22, 23]), // b
];
return CubeScene;
}(_interface_BaseScene__WEBPACK_IMPORTED_MODULE_2__["default"]));
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CubeScene);
/***/ }),
/***/ "./src/lib/HotSpot.ts":
/*!****************************!*\
!*** ./src/lib/HotSpot.ts ***!
\****************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _utils_math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/math */ "./src/utils/math.ts");
/* harmony import */ var _config_index__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../config/index */ "./src/config/index.ts");
/**
* 热点
* */
var HotSpot = /** @class */ (function () {
/**
* @constructor
* @param {HTMLElement} dom 热点元素
* @param {{pitch?: number, yaw?: number, target?: number}} options 可选参数:pitch 位置-俯仰角-角度,范围是 (-90, 90);yaw 位置-偏航角-角度;target 转场目标场景索引
* */
function HotSpot(dom, options) {
if (options === void 0) { options = {}; }
var _a = options.pitch, pitch = _a === void 0 ? 0 : _a, _b = options.yaw, yaw = _b === void 0 ? 0 : _b, target = options.target;
// 强制 dom 绝对定位
dom.style.position = 'absolute';
dom.style.cursor = 'pointer';
this.dom = dom;
this.pitch = pitch;
this.yaw = yaw;
this.target = target;
this.originOnClick = dom.onclick;
}
/**
* 把热点图像插入到容器内
* @param deltaPitch {number} 场景的俯仰角偏移值
* @param deltaYaw {number} 场景的偏航角偏移值
* @param {Pano} pano 爷爷容器
* @param {Scene} scene 父容器
* */
HotSpot.prototype.render = function (deltaPitch, deltaYaw, pano, scene) {
var _this = this;
this.pano = pano;
this.scene = scene;
var container = this.pano.container;
// target 有值的时候,给 click 添加默认场景切换操作
if (this.target || this.target === 0) {
this.dom.onclick = function (ev) {
_this.scene.onHotSpotClick(_this);
if (_this.originOnClick)
_this.originOnClick(ev);
};
}
container.append(this.dom);
var _a = this.dom.getBoundingClientRect(), width = _a.width, height = _a.height;
var centerX = (container.offsetWidth - width) / 2;
var centerY = (container.offsetHeight - height) / 2;
var offsetWidth = container.offsetWidth, offsetHeight = container.offsetHeight;
this.pitch += deltaPitch;
this.yaw -= deltaYaw;
/**
* tan(|pitch|) = deltaTop / 1
* pitch 的绝对值的正切:y 方向偏移量 / 深度(1)
* pitch 的绝对值不超过配置的范围
* deltaTop 的计算结果是归一化的,换算成像素值:* canvas.height / 2
* ------ 上面的计算是基于 fovy 是 90 度的情况,当 fovy 非 90 时,需要乘以比例 --------
* */
var deltaTop = Math.tan((0,_utils_math__WEBPACK_IMPORTED_MODULE_0__.angle2PI)(Math.abs(this.pitch))) * (container.offsetHeight / 2) * (90 / _config_index__WEBPACK_IMPORTED_MODULE_1__.DefaultFovy);
var top = this.pitch > 0 ? centerY - deltaTop : centerY + deltaTop;
this.dom.style.top = top + "px";
/**
* yaw 先转换到 [0, 360),再区分 [0, 90, 180, 270, 360) 各个区间计算
* 只要处理 [0, 90) 和 (270, 360)
* 90 和 270 是无穷大,(90, 270) 范围在视线背面
*
* [0, 90): tan(yaw) = deltaLeft / 1
* (270, 360): tan(360 - yaw) = deltaLeft / 1
*
* 横向偏移量还和 canvas 的宽高比还有关系,但是垂直方向的偏移量和宽高比没关系???
* ------ 上面的计算是基于 fovy 是 90 度的情况,当 fovy 非 90 时,需要乘以比例 --------
* */
this.yaw = (0,_utils_math__WEBPACK_IMPORTED_MODULE_0__.angleIn360)(this.yaw);
var deltaLeft;
if (this.yaw >= 0 && this.yaw < 90) {
deltaLeft = Math.tan((0,_utils_math__WEBPACK_IMPORTED_MODULE_0__.angle2PI)(this.yaw));
}
else if (this.yaw > 270) {
deltaLeft = -Math.tan((0,_utils_math__WEBPACK_IMPORTED_MODULE_0__.angle2PI)(360 - this.yaw));
}
else {
// 直接给一个画布的宽度值,偏移到外面不显示
deltaLeft = 4;
}
deltaLeft *= ((container.offsetWidth / 2) * (offsetHeight / offsetWidth) * (90 / _config_index__WEBPACK_IMPORTED_MODULE_1__.DefaultFovy));
this.dom.style.left = centerX + deltaLeft + "px";
};
/**
* 销毁
* */
HotSpot.prototype.destroy = function () {
// 移除图片
if (this.pano.container)
this.pano.container.removeChild(this.dom);
};
return HotSpot;
}());
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (HotSpot);
/***/ }),
/***/ "./src/lib/Pano.ts":
/*!*************************!*\
!*** ./src/lib/Pano.ts ***!
\*************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _utils_cuon_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils/cuon-utils */ "./src/utils/cuon-utils.ts");
/* harmony import */ var _shader_cube_index_vert__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../shader/cube/index.vert */ "./src/shader/cube/index.vert");
/* harmony import */ var _shader_cube_index_frag__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../shader/cube/index.frag */ "./src/shader/cube/index.frag");
/* harmony import */ var _shader_sphere_index_vert__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../shader/sphere/index.vert */ "./src/shader/sphere/index.vert");
/* harmony import */ var _shader_sphere_index_frag__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../shader/sphere/index.frag */ "./src/shader/sphere/index.frag");
/* harmony import */ var _resource__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./resource */ "./src/lib/resource.ts");
/* harmony import */ var _CubeScene__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./CubeScene */ "./src/lib/CubeScene.ts");
/* harmony import */ var _SphereScene__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./SphereScene */ "./src/lib/SphereScene.ts");
/**
* 容器
* */
var Pano = /** @class */ (function () {
/**
* @constructor
* @param {string} containerId 容器节点id
* @param {boolean} debug 是否开启debug
* */
function Pano(containerId, debug) {
var _this = this;
/**
* @property {Scene[]} scenes 场景列表
* */
this.scenes = [];
/**
* @property {number} sceneIndex 当前场景
* */
this.sceneIndex = 0;
/**
* 是否已经渲染
* */
this.rendered = false;
/**
* 场景变化的回调函数
* */
this.sceneChangeCallbacks = [];
/**
* 切换场景
* @param {number} sceneIndex 切换后的场景
* */
this.switchScene = function (sceneIndex) {
if (sceneIndex === _this.sceneIndex)
return;
var currentScene = _this.scenes[_this.sceneIndex];
if (currentScene)
currentScene.destroy();
_this.sceneIndex = sceneIndex;
_this.render();
// 执行回调
_this.sceneChangeCallbacks.forEach(function (callback) {
callback(_this.scenes[_this.sceneIndex], _this.sceneIndex);
});
};
var container = document.getElementById(containerId);
if (!container) {
throw new Error('找不到容器,请确认 id 是否正确');
}
this.container = container;
var canvas = document.createElement('canvas');
this.canvas = canvas;
container.append(canvas);
this.gl = (0,_utils_cuon_utils__WEBPACK_IMPORTED_MODULE_0__.getWebGLContext)(canvas, debug);
this.setStyle();
this.onContainerResize();
}
/**
* 初始化着色器程序
* */
Pano.prototype.initShader = function () {
var scene = this.scenes[this.sceneIndex];
if (scene instanceof _CubeScene__WEBPACK_IMPORTED_MODULE_6__["default"]) {
if (!Pano.CubeGLProgram)
Pano.CubeGLProgram = (0,_utils_cuon_utils__WEBPACK_IMPORTED_MODULE_0__.createProgram)(this.gl, _shader_cube_index_vert__WEBPACK_IMPORTED_MODULE_1__["default"], _shader_cube_index_frag__WEBPACK_IMPORTED_MODULE_2__["default"]);
(0,_utils_cuon_utils__WEBPACK_IMPORTED_MODULE_0__.useProgram)(this.gl, Pano.CubeGLProgram);
}
else if (scene instanceof _SphereScene__WEBPACK_IMPORTED_MODULE_7__["default"]) {
if (!Pano.SphereGLProgram)
Pano.SphereGLProgram = (0,_utils_cuon_utils__WEBPACK_IMPORTED_MODULE_0__.createProgram)(this.gl, _shader_sphere_index_vert__WEBPACK_IMPORTED_MODULE_3__["default"], _shader_sphere_index_frag__WEBPACK_IMPORTED_MODULE_4__["default"]);
(0,_utils_cuon_utils__WEBPACK_IMPORTED_MODULE_0__.useProgram)(this.gl, Pano.SphereGLProgram);
}
else {
throw new Error('当前场景非法');
}
};
/**
* 设置样式
* */
Pano.prototype.setStyle = function () {
var _a = this, container = _a.container, canvas = _a.canvas;
container.style.overflow = 'hidden';
// 如果 container 的 position 不是 absolute 和 fixed,则统一设置成 relative
var containerPosition = container.style.position;
if (containerPosition !== 'absolute' && containerPosition !== 'fixed') {
container.style.position = 'relative';
}
// 开启 HiDPI
var desiredCSSWidth = container.offsetWidth;
var desiredCSSHeight = container.offsetHeight;
var devicePixelRatio = window.devicePixelRatio || 1;
canvas.width = desiredCSSWidth * devicePixelRatio;
canvas.height = desiredCSSHeight * devicePixelRatio;
canvas.style.width = desiredCSSWidth + "px";
canvas.style.height = desiredCSSHeight + "px";
// canvas 大小变化后,即时改变 gl 的 viewport
this.gl.viewport(0, 0, canvas.width, canvas.height);
canvas.style.cursor = 'grab';
};
/**
* container 尺寸变化监听,重新渲染
* */
Pano.prototype.onContainerResize = function () {
var _this = this;
if (ResizeObserver) {
var observer = new ResizeObserver(function () {
if (_this.rendered) {
_this.setStyle();
_this.render();
}
});
observer.observe(this.container);
}
};
/**
* 添加回调函数
* @param {ListenerType} type 监听类型,预定义好的
* @param {ListenerCallback} callback 回调函数
* */
Pano.prototype.addListener = function (type, callback) {
switch (type) {
case "sceneChange":
this.sceneChangeCallbacks.push(callback);
break;
default:
break;
}
};
/**
* 添加回调函数
* @param {ListenerType} type 监听类型,预定义好的
* @param {ListenerCallback} callback 回调函数
* */
Pano.prototype.removeListener = function (type, callback) {
switch (type) {
case "sceneChange":
this.sceneChangeCallbacks = this.sceneChangeCallbacks.filter(function (item) { return item !== callback; });
break;
default:
break;
}
};
/**
* 移除所有监听
* */
Pano.prototype.removeAllListeners = function () {
this.sceneChangeCallbacks = [];
};
/**
* 添加场景
* @param {Scene} scene 场景
* */
Pano.prototype.addScene = function (scene) {
this.scene