Spaces:
Running
Running
Update js_scripts/index.js
Browse files- js_scripts/index.js +78 -27
js_scripts/index.js
CHANGED
@@ -58,6 +58,8 @@ const currentScriptTag = document.currentScript;
|
|
58 |
let cameraEntity = null;
|
59 |
let app = null;
|
60 |
let modelEntity = null;
|
|
|
|
|
61 |
|
62 |
// Generate a unique identifier for this widget instance.
|
63 |
const instanceId = Math.random().toString(36).substr(2, 8);
|
@@ -225,7 +227,29 @@ const currentScriptTag = document.currentScript;
|
|
225 |
});
|
226 |
}
|
227 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
228 |
closeBtn.addEventListener('click', function() {
|
|
|
229 |
if (document.fullscreenElement === widgetContainer) {
|
230 |
if (document.exitFullscreen) {
|
231 |
document.exitFullscreen();
|
@@ -234,8 +258,12 @@ const currentScriptTag = document.currentScript;
|
|
234 |
if (widgetContainer.classList.contains('fake-fullscreen')) {
|
235 |
widgetContainer.classList.remove('fake-fullscreen');
|
236 |
fullscreenToggle.textContent = '⇱';
|
237 |
-
resetCamera();
|
238 |
}
|
|
|
|
|
|
|
|
|
|
|
239 |
viewerContainer.style.display = 'none';
|
240 |
gifPreview.style.display = 'block';
|
241 |
});
|
@@ -380,38 +408,55 @@ const currentScriptTag = document.currentScript;
|
|
380 |
});
|
381 |
|
382 |
// --- Prevent app from hijacking all wheel events ---
|
383 |
-
|
384 |
-
//
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
}
|
|
|
389 |
|
390 |
-
//
|
391 |
-
event
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
const sensitivity = cameraEntity.script.orbitCameraInputMouse ?
|
397 |
-
cameraEntity.script.orbitCameraInputMouse.distanceSensitivity || 0.4 : 0.4;
|
398 |
-
|
399 |
-
if (camera.projection === pc.PROJECTION_PERSPECTIVE) {
|
400 |
-
orbitCamera.distance -= event.deltaY * 0.01 * sensitivity * (orbitCamera.distance * 0.1);
|
401 |
-
} else {
|
402 |
-
orbitCamera.orthoHeight -= event.deltaY * 0.01 * sensitivity * (orbitCamera.orthoHeight * 0.1);
|
403 |
}
|
404 |
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
412 |
|
413 |
// --- Initialize the 3D PLY Viewer using PlayCanvas ---
|
414 |
async function initializeViewer() {
|
|
|
|
|
|
|
415 |
progressDialog.style.display = 'block';
|
416 |
|
417 |
// Initialize PlayCanvas
|
@@ -575,7 +620,7 @@ const currentScriptTag = document.currentScript;
|
|
575 |
|
576 |
// Initialize the orbit controller
|
577 |
setTimeout(() => {
|
578 |
-
if (cameraEntity.script.orbitCamera) {
|
579 |
// Calculate distance from camera to model
|
580 |
const modelPos = modelEntity.getPosition();
|
581 |
const camPos = cameraEntity.getPosition();
|
@@ -595,8 +640,14 @@ const currentScriptTag = document.currentScript;
|
|
595 |
// Initial resize to match container
|
596 |
resize();
|
597 |
|
|
|
|
|
|
|
598 |
// Hide progress dialog when everything is set up
|
599 |
progressDialog.style.display = 'none';
|
|
|
|
|
|
|
600 |
});
|
601 |
|
602 |
} catch (error) {
|
|
|
58 |
let cameraEntity = null;
|
59 |
let app = null;
|
60 |
let modelEntity = null;
|
61 |
+
let viewerInitialized = false;
|
62 |
+
let wheelHandlers = [];
|
63 |
|
64 |
// Generate a unique identifier for this widget instance.
|
65 |
const instanceId = Math.random().toString(36).substr(2, 8);
|
|
|
227 |
});
|
228 |
}
|
229 |
|
230 |
+
// Function to clean up the viewer
|
231 |
+
function cleanupViewer() {
|
232 |
+
// Remove wheel event listeners
|
233 |
+
for (const handler of wheelHandlers) {
|
234 |
+
const [element, func] = handler;
|
235 |
+
element.removeEventListener('wheel', func, { passive: false });
|
236 |
+
}
|
237 |
+
wheelHandlers = [];
|
238 |
+
|
239 |
+
// Destroy PlayCanvas app if it exists
|
240 |
+
if (app) {
|
241 |
+
app.destroy();
|
242 |
+
app = null;
|
243 |
+
}
|
244 |
+
|
245 |
+
// Reset entities
|
246 |
+
cameraEntity = null;
|
247 |
+
modelEntity = null;
|
248 |
+
viewerInitialized = false;
|
249 |
+
}
|
250 |
+
|
251 |
closeBtn.addEventListener('click', function() {
|
252 |
+
// Handle fullscreen exit
|
253 |
if (document.fullscreenElement === widgetContainer) {
|
254 |
if (document.exitFullscreen) {
|
255 |
document.exitFullscreen();
|
|
|
258 |
if (widgetContainer.classList.contains('fake-fullscreen')) {
|
259 |
widgetContainer.classList.remove('fake-fullscreen');
|
260 |
fullscreenToggle.textContent = '⇱';
|
|
|
261 |
}
|
262 |
+
|
263 |
+
// Clean up the viewer
|
264 |
+
cleanupViewer();
|
265 |
+
|
266 |
+
// Hide viewer and show GIF
|
267 |
viewerContainer.style.display = 'none';
|
268 |
gifPreview.style.display = 'block';
|
269 |
});
|
|
|
408 |
});
|
409 |
|
410 |
// --- Prevent app from hijacking all wheel events ---
|
411 |
+
function setupWheelHandlers() {
|
412 |
+
// First remove any existing handlers
|
413 |
+
for (const handler of wheelHandlers) {
|
414 |
+
const [element, func] = handler;
|
415 |
+
element.removeEventListener('wheel', func, { passive: false });
|
416 |
}
|
417 |
+
wheelHandlers = [];
|
418 |
|
419 |
+
// Create new wheel handler
|
420 |
+
const handleWheel = function(event) {
|
421 |
+
// Check if mouse is over the viewer
|
422 |
+
if (!isMouseOverViewer) {
|
423 |
+
// Allow normal page scrolling
|
424 |
+
return true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
425 |
}
|
426 |
|
427 |
+
// Otherwise apply zooming, but prevent default only for viewer area
|
428 |
+
event.stopPropagation();
|
429 |
+
|
430 |
+
if (cameraEntity && cameraEntity.script && cameraEntity.script.orbitCamera) {
|
431 |
+
const camera = cameraEntity.camera;
|
432 |
+
const orbitCamera = cameraEntity.script.orbitCamera;
|
433 |
+
const sensitivity = cameraEntity.script.orbitCameraInputMouse ?
|
434 |
+
cameraEntity.script.orbitCameraInputMouse.distanceSensitivity || 0.4 : 0.4;
|
435 |
+
|
436 |
+
if (camera.projection === pc.PROJECTION_PERSPECTIVE) {
|
437 |
+
orbitCamera.distance -= event.deltaY * 0.01 * sensitivity * (orbitCamera.distance * 0.1);
|
438 |
+
} else {
|
439 |
+
orbitCamera.orthoHeight -= event.deltaY * 0.01 * sensitivity * (orbitCamera.orthoHeight * 0.1);
|
440 |
+
}
|
441 |
+
|
442 |
+
event.preventDefault();
|
443 |
+
}
|
444 |
+
};
|
445 |
+
|
446 |
+
// Add wheel handlers and store references for cleanup
|
447 |
+
viewerContainer.addEventListener('wheel', handleWheel, { passive: false });
|
448 |
+
canvas.addEventListener('wheel', handleWheel, { passive: false });
|
449 |
+
|
450 |
+
// Store handlers for later cleanup
|
451 |
+
wheelHandlers.push([viewerContainer, handleWheel]);
|
452 |
+
wheelHandlers.push([canvas, handleWheel]);
|
453 |
+
}
|
454 |
|
455 |
// --- Initialize the 3D PLY Viewer using PlayCanvas ---
|
456 |
async function initializeViewer() {
|
457 |
+
// Skip initialization if already initialized
|
458 |
+
if (viewerInitialized) return;
|
459 |
+
|
460 |
progressDialog.style.display = 'block';
|
461 |
|
462 |
// Initialize PlayCanvas
|
|
|
620 |
|
621 |
// Initialize the orbit controller
|
622 |
setTimeout(() => {
|
623 |
+
if (cameraEntity && cameraEntity.script && cameraEntity.script.orbitCamera) {
|
624 |
// Calculate distance from camera to model
|
625 |
const modelPos = modelEntity.getPosition();
|
626 |
const camPos = cameraEntity.getPosition();
|
|
|
640 |
// Initial resize to match container
|
641 |
resize();
|
642 |
|
643 |
+
// Set up wheel handlers
|
644 |
+
setupWheelHandlers();
|
645 |
+
|
646 |
// Hide progress dialog when everything is set up
|
647 |
progressDialog.style.display = 'none';
|
648 |
+
|
649 |
+
// Mark viewer as initialized
|
650 |
+
viewerInitialized = true;
|
651 |
});
|
652 |
|
653 |
} catch (error) {
|