Spaces:
Running
Running
Update index_sans_gif.js
Browse files- index_sans_gif.js +40 -65
index_sans_gif.js
CHANGED
|
@@ -1,4 +1,23 @@
|
|
| 1 |
-
(function() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
// --- Outer scope variables for camera state ---
|
| 3 |
let cameraInstance = null;
|
| 4 |
let controlsInstance = null;
|
|
@@ -8,53 +27,36 @@
|
|
| 8 |
// Generate a unique identifier for this widget instance.
|
| 9 |
const instanceId = Math.random().toString(36).substr(2, 8);
|
| 10 |
|
| 11 |
-
//
|
| 12 |
-
|
| 13 |
-
var params = new URLSearchParams("");
|
| 14 |
-
if (document.currentScript && document.currentScript.src.indexOf('?') !== -1) {
|
| 15 |
-
var queryString = document.currentScript.src.split('?')[1];
|
| 16 |
-
params = new URLSearchParams(queryString);
|
| 17 |
-
} else {
|
| 18 |
-
params = new URLSearchParams(window.location.search);
|
| 19 |
-
}
|
| 20 |
-
return params.get(param);
|
| 21 |
-
}
|
| 22 |
-
|
| 23 |
-
// Read required URLs.
|
| 24 |
-
// The gifUrl is no longer used.
|
| 25 |
-
var plyUrl = getScriptQueryParam("ply_url");
|
| 26 |
-
|
| 27 |
-
// Read optional initial camera position (as a vector string "x,y,z").
|
| 28 |
-
var initialCameraPosParam = getScriptQueryParam("initialCameraPosition");
|
| 29 |
|
| 30 |
// Optional parameters for zoom and rotation limits.
|
| 31 |
// Defaults: zoom from 0 to 20; rotation from 0 to 360.
|
| 32 |
-
var minZoom = parseFloat(
|
| 33 |
-
var maxZoom = parseFloat(
|
| 34 |
-
var minAngle = parseFloat(
|
| 35 |
-
var maxAngle = parseFloat(
|
| 36 |
|
| 37 |
// Determine the aspect ratio.
|
| 38 |
// Default aspect: 1:1 (i.e. 100% padding-bottom)
|
| 39 |
var aspectPercent = "100%";
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
var parts = aspectParam.split(":");
|
| 44 |
var w = parseFloat(parts[0]);
|
| 45 |
var h = parseFloat(parts[1]);
|
| 46 |
if (!isNaN(w) && !isNaN(h) && w > 0) {
|
| 47 |
aspectPercent = (h / w * 100) + "%";
|
| 48 |
}
|
| 49 |
} else {
|
| 50 |
-
var aspectValue = parseFloat(
|
| 51 |
if (!isNaN(aspectValue) && aspectValue > 0) {
|
| 52 |
aspectPercent = (100 / aspectValue) + "%";
|
| 53 |
}
|
| 54 |
}
|
| 55 |
} else {
|
| 56 |
// If no aspect parameter is provided, compute the aspect ratio from the parent element.
|
| 57 |
-
var parentContainer =
|
| 58 |
var containerWidth = parentContainer.offsetWidth;
|
| 59 |
var containerHeight = parentContainer.offsetHeight;
|
| 60 |
if (containerWidth > 0 && containerHeight > 0) {
|
|
@@ -87,7 +89,6 @@
|
|
| 87 |
}
|
| 88 |
/* Viewer Container styling */
|
| 89 |
#viewer-container-${instanceId} {
|
| 90 |
-
/* Display the viewer by default */
|
| 91 |
display: block;
|
| 92 |
position: absolute;
|
| 93 |
top: 0;
|
|
@@ -104,7 +105,7 @@
|
|
| 104 |
height: 100%;
|
| 105 |
display: block;
|
| 106 |
}
|
| 107 |
-
/* Progress dialog styling
|
| 108 |
#progress-dialog-${instanceId} {
|
| 109 |
position: absolute;
|
| 110 |
top: 50%;
|
|
@@ -117,7 +118,7 @@
|
|
| 117 |
z-index: 1000;
|
| 118 |
display: none;
|
| 119 |
}
|
| 120 |
-
/* Menu
|
| 121 |
#menu-content-${instanceId} {
|
| 122 |
display: none;
|
| 123 |
position: absolute;
|
|
@@ -146,8 +147,7 @@
|
|
| 146 |
align-items: center;
|
| 147 |
justify-content: center;
|
| 148 |
}
|
| 149 |
-
/*
|
| 150 |
-
and reset camera below help */
|
| 151 |
#fullscreen-toggle-${instanceId} {
|
| 152 |
top: 17px;
|
| 153 |
right: 15px;
|
|
@@ -163,10 +163,8 @@
|
|
| 163 |
line-height: 1;
|
| 164 |
padding: 0;
|
| 165 |
}
|
| 166 |
-
/* Adjust the ⟲ icon position within the reset camera button */
|
| 167 |
.reset-icon {
|
| 168 |
display: inline-block;
|
| 169 |
-
transform: translateY(-3px);
|
| 170 |
}
|
| 171 |
`;
|
| 172 |
document.head.appendChild(styleEl);
|
|
@@ -175,7 +173,7 @@
|
|
| 175 |
var widgetContainer = document.createElement('div');
|
| 176 |
widgetContainer.id = 'ply-widget-container-' + instanceId;
|
| 177 |
widgetContainer.innerHTML = `
|
| 178 |
-
<!-- Viewer Container
|
| 179 |
<div id="viewer-container-${instanceId}">
|
| 180 |
<canvas id="canvas-${instanceId}"></canvas>
|
| 181 |
<div id="progress-dialog-${instanceId}">
|
|
@@ -193,9 +191,9 @@
|
|
| 193 |
</div>
|
| 194 |
</div>
|
| 195 |
`;
|
| 196 |
-
|
| 197 |
|
| 198 |
-
// Grab element references
|
| 199 |
var viewerContainer = document.getElementById('viewer-container-' + instanceId);
|
| 200 |
var fullscreenToggle = document.getElementById('fullscreen-toggle-' + instanceId);
|
| 201 |
var helpToggle = document.getElementById('help-toggle-' + instanceId);
|
|
@@ -209,11 +207,7 @@
|
|
| 209 |
|
| 210 |
fullscreenToggle.addEventListener('click', function() {
|
| 211 |
if (isIOS) {
|
| 212 |
-
|
| 213 |
-
widgetContainer.classList.add('fake-fullscreen');
|
| 214 |
-
} else {
|
| 215 |
-
widgetContainer.classList.remove('fake-fullscreen');
|
| 216 |
-
}
|
| 217 |
fullscreenToggle.textContent = widgetContainer.classList.contains('fake-fullscreen') ? '⇲' : '⇱';
|
| 218 |
} else {
|
| 219 |
if (!document.fullscreenElement) {
|
|
@@ -235,11 +229,7 @@
|
|
| 235 |
});
|
| 236 |
|
| 237 |
document.addEventListener('fullscreenchange', function() {
|
| 238 |
-
|
| 239 |
-
fullscreenToggle.textContent = '⇲';
|
| 240 |
-
} else {
|
| 241 |
-
fullscreenToggle.textContent = '⇱';
|
| 242 |
-
}
|
| 243 |
});
|
| 244 |
|
| 245 |
helpToggle.addEventListener('click', function(e) {
|
|
@@ -270,21 +260,6 @@
|
|
| 270 |
const camera = new SPLAT.Camera();
|
| 271 |
const controls = new SPLAT.OrbitControls(camera, canvas);
|
| 272 |
|
| 273 |
-
// If an initial camera position was provided, parse and assign it.
|
| 274 |
-
if (initialCameraPosParam) {
|
| 275 |
-
var parts = initialCameraPosParam.split(",");
|
| 276 |
-
if (parts.length === 3) {
|
| 277 |
-
var camX = parseFloat(parts[0]);
|
| 278 |
-
var camY = parseFloat(parts[1]);
|
| 279 |
-
var camZ = parseFloat(parts[2]);
|
| 280 |
-
if (!isNaN(camX) && !isNaN(camY) && !isNaN(camZ)) {
|
| 281 |
-
camera.position.x = camX;
|
| 282 |
-
camera.position.y = camY;
|
| 283 |
-
camera.position.z = camZ;
|
| 284 |
-
}
|
| 285 |
-
}
|
| 286 |
-
}
|
| 287 |
-
|
| 288 |
cameraInstance = camera;
|
| 289 |
controlsInstance = controls;
|
| 290 |
initialCameraPosition = camera.position.clone();
|
|
@@ -327,6 +302,6 @@
|
|
| 327 |
requestAnimationFrame(frame);
|
| 328 |
}
|
| 329 |
|
| 330 |
-
//
|
| 331 |
initializeViewer();
|
| 332 |
})();
|
|
|
|
| 1 |
+
(async function() {
|
| 2 |
+
// Get the script tag and its config attribute.
|
| 3 |
+
const scriptTag = document.currentScript;
|
| 4 |
+
const configUrl = scriptTag.getAttribute("data-config");
|
| 5 |
+
let config = {};
|
| 6 |
+
|
| 7 |
+
// Load configuration from the JSON file.
|
| 8 |
+
if (configUrl) {
|
| 9 |
+
try {
|
| 10 |
+
const response = await fetch(configUrl);
|
| 11 |
+
config = await response.json();
|
| 12 |
+
} catch (error) {
|
| 13 |
+
console.error("Error loading config file:", error);
|
| 14 |
+
return;
|
| 15 |
+
}
|
| 16 |
+
} else {
|
| 17 |
+
console.error("No config file provided. Please set a data-config attribute on the script tag.");
|
| 18 |
+
return;
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
// --- Outer scope variables for camera state ---
|
| 22 |
let cameraInstance = null;
|
| 23 |
let controlsInstance = null;
|
|
|
|
| 27 |
// Generate a unique identifier for this widget instance.
|
| 28 |
const instanceId = Math.random().toString(36).substr(2, 8);
|
| 29 |
|
| 30 |
+
// Use configuration parameters from the JSON file.
|
| 31 |
+
var plyUrl = config.ply_url;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
|
| 33 |
// Optional parameters for zoom and rotation limits.
|
| 34 |
// Defaults: zoom from 0 to 20; rotation from 0 to 360.
|
| 35 |
+
var minZoom = parseFloat(config.minZoom || "0");
|
| 36 |
+
var maxZoom = parseFloat(config.maxZoom || "20");
|
| 37 |
+
var minAngle = parseFloat(config.minAngle || "0");
|
| 38 |
+
var maxAngle = parseFloat(config.maxAngle || "360");
|
| 39 |
|
| 40 |
// Determine the aspect ratio.
|
| 41 |
// Default aspect: 1:1 (i.e. 100% padding-bottom)
|
| 42 |
var aspectPercent = "100%";
|
| 43 |
+
if (config.aspect) {
|
| 44 |
+
if (config.aspect.indexOf(":") !== -1) {
|
| 45 |
+
var parts = config.aspect.split(":");
|
|
|
|
| 46 |
var w = parseFloat(parts[0]);
|
| 47 |
var h = parseFloat(parts[1]);
|
| 48 |
if (!isNaN(w) && !isNaN(h) && w > 0) {
|
| 49 |
aspectPercent = (h / w * 100) + "%";
|
| 50 |
}
|
| 51 |
} else {
|
| 52 |
+
var aspectValue = parseFloat(config.aspect);
|
| 53 |
if (!isNaN(aspectValue) && aspectValue > 0) {
|
| 54 |
aspectPercent = (100 / aspectValue) + "%";
|
| 55 |
}
|
| 56 |
}
|
| 57 |
} else {
|
| 58 |
// If no aspect parameter is provided, compute the aspect ratio from the parent element.
|
| 59 |
+
var parentContainer = scriptTag.parentNode;
|
| 60 |
var containerWidth = parentContainer.offsetWidth;
|
| 61 |
var containerHeight = parentContainer.offsetHeight;
|
| 62 |
if (containerWidth > 0 && containerHeight > 0) {
|
|
|
|
| 89 |
}
|
| 90 |
/* Viewer Container styling */
|
| 91 |
#viewer-container-${instanceId} {
|
|
|
|
| 92 |
display: block;
|
| 93 |
position: absolute;
|
| 94 |
top: 0;
|
|
|
|
| 105 |
height: 100%;
|
| 106 |
display: block;
|
| 107 |
}
|
| 108 |
+
/* Progress dialog styling */
|
| 109 |
#progress-dialog-${instanceId} {
|
| 110 |
position: absolute;
|
| 111 |
top: 50%;
|
|
|
|
| 118 |
z-index: 1000;
|
| 119 |
display: none;
|
| 120 |
}
|
| 121 |
+
/* Menu content styling */
|
| 122 |
#menu-content-${instanceId} {
|
| 123 |
display: none;
|
| 124 |
position: absolute;
|
|
|
|
| 147 |
align-items: center;
|
| 148 |
justify-content: center;
|
| 149 |
}
|
| 150 |
+
/* Button positions */
|
|
|
|
| 151 |
#fullscreen-toggle-${instanceId} {
|
| 152 |
top: 17px;
|
| 153 |
right: 15px;
|
|
|
|
| 163 |
line-height: 1;
|
| 164 |
padding: 0;
|
| 165 |
}
|
|
|
|
| 166 |
.reset-icon {
|
| 167 |
display: inline-block;
|
|
|
|
| 168 |
}
|
| 169 |
`;
|
| 170 |
document.head.appendChild(styleEl);
|
|
|
|
| 173 |
var widgetContainer = document.createElement('div');
|
| 174 |
widgetContainer.id = 'ply-widget-container-' + instanceId;
|
| 175 |
widgetContainer.innerHTML = `
|
| 176 |
+
<!-- Viewer Container -->
|
| 177 |
<div id="viewer-container-${instanceId}">
|
| 178 |
<canvas id="canvas-${instanceId}"></canvas>
|
| 179 |
<div id="progress-dialog-${instanceId}">
|
|
|
|
| 191 |
</div>
|
| 192 |
</div>
|
| 193 |
`;
|
| 194 |
+
scriptTag.parentNode.appendChild(widgetContainer);
|
| 195 |
|
| 196 |
+
// Grab element references.
|
| 197 |
var viewerContainer = document.getElementById('viewer-container-' + instanceId);
|
| 198 |
var fullscreenToggle = document.getElementById('fullscreen-toggle-' + instanceId);
|
| 199 |
var helpToggle = document.getElementById('help-toggle-' + instanceId);
|
|
|
|
| 207 |
|
| 208 |
fullscreenToggle.addEventListener('click', function() {
|
| 209 |
if (isIOS) {
|
| 210 |
+
widgetContainer.classList.toggle('fake-fullscreen');
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
fullscreenToggle.textContent = widgetContainer.classList.contains('fake-fullscreen') ? '⇲' : '⇱';
|
| 212 |
} else {
|
| 213 |
if (!document.fullscreenElement) {
|
|
|
|
| 229 |
});
|
| 230 |
|
| 231 |
document.addEventListener('fullscreenchange', function() {
|
| 232 |
+
fullscreenToggle.textContent = (document.fullscreenElement === widgetContainer) ? '⇲' : '⇱';
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
});
|
| 234 |
|
| 235 |
helpToggle.addEventListener('click', function(e) {
|
|
|
|
| 260 |
const camera = new SPLAT.Camera();
|
| 261 |
const controls = new SPLAT.OrbitControls(camera, canvas);
|
| 262 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 263 |
cameraInstance = camera;
|
| 264 |
controlsInstance = controls;
|
| 265 |
initialCameraPosition = camera.position.clone();
|
|
|
|
| 302 |
requestAnimationFrame(frame);
|
| 303 |
}
|
| 304 |
|
| 305 |
+
// Start the viewer.
|
| 306 |
initializeViewer();
|
| 307 |
})();
|