Spaces:
Running
Running
Update index.js
Browse files
index.js
CHANGED
@@ -4,6 +4,9 @@
|
|
4 |
let controlsInstance = null;
|
5 |
let initialCameraPosition = null;
|
6 |
let initialCameraRotation = null;
|
|
|
|
|
|
|
7 |
|
8 |
// Helper: Get query parameters from THIS script’s src URL.
|
9 |
function getScriptQueryParam(param) {
|
@@ -31,18 +34,18 @@
|
|
31 |
// Detect if the device is iOS.
|
32 |
var isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
33 |
|
34 |
-
// Inject CSS styles into the document head.
|
35 |
var styleEl = document.createElement('style');
|
36 |
styleEl.textContent = `
|
37 |
/* Widget container styling */
|
38 |
-
#ply-widget-container {
|
39 |
position: relative;
|
40 |
width: 100%;
|
41 |
height: 0;
|
42 |
padding-bottom: 100%;
|
43 |
}
|
44 |
/* When in fake fullscreen mode (iOS fallback) */
|
45 |
-
#ply-widget-container.fake-fullscreen {
|
46 |
position: fixed !important;
|
47 |
top: 0 !important;
|
48 |
left: 0 !important;
|
@@ -52,7 +55,7 @@
|
|
52 |
z-index: 9999 !important;
|
53 |
}
|
54 |
/* GIF Preview styling */
|
55 |
-
#gif-preview-container {
|
56 |
position: absolute;
|
57 |
top: 0;
|
58 |
left: 0;
|
@@ -63,13 +66,13 @@
|
|
63 |
overflow: hidden;
|
64 |
cursor: pointer;
|
65 |
}
|
66 |
-
#gif-preview-container img {
|
67 |
width: 100%;
|
68 |
height: 100%;
|
69 |
object-fit: cover;
|
70 |
}
|
71 |
/* Viewer Container styling */
|
72 |
-
#viewer-container {
|
73 |
display: none;
|
74 |
position: absolute;
|
75 |
top: 0;
|
@@ -81,13 +84,13 @@
|
|
81 |
border-radius: 10px;
|
82 |
}
|
83 |
/* Canvas fills the viewer container */
|
84 |
-
#canvas {
|
85 |
width: 100%;
|
86 |
height: 100%;
|
87 |
display: block;
|
88 |
}
|
89 |
/* Progress dialog styling (as a centered div) */
|
90 |
-
#progress-dialog {
|
91 |
position: absolute;
|
92 |
top: 50%;
|
93 |
left: 50%;
|
@@ -100,7 +103,7 @@
|
|
100 |
display: none;
|
101 |
}
|
102 |
/* Menu (instructions) content styling */
|
103 |
-
#menu-content {
|
104 |
display: none;
|
105 |
position: absolute;
|
106 |
top: 62px;
|
@@ -129,20 +132,20 @@
|
|
129 |
justify-content: center;
|
130 |
}
|
131 |
/* Positions: Close at top-left, fullscreen at top-right, help (instructions) below fullscreen */
|
132 |
-
#close-btn {
|
133 |
top: 17px;
|
134 |
left: 15px;
|
135 |
}
|
136 |
-
#fullscreen-toggle {
|
137 |
top: 17px;
|
138 |
right: 15px;
|
139 |
}
|
140 |
-
#help-toggle {
|
141 |
top: 72px;
|
142 |
right: 15px;
|
143 |
}
|
144 |
-
/*
|
145 |
-
#reset-camera-btn {
|
146 |
top: 127px;
|
147 |
right: 15px;
|
148 |
}
|
@@ -151,23 +154,23 @@
|
|
151 |
|
152 |
// Create the widget container and set its inner HTML.
|
153 |
var widgetContainer = document.createElement('div');
|
154 |
-
widgetContainer.id = 'ply-widget-container';
|
155 |
widgetContainer.innerHTML = `
|
156 |
<!-- GIF Preview Container -->
|
157 |
-
<div id="gif-preview-container">
|
158 |
-
<img id="preview-image" alt="Preview" crossorigin="anonymous">
|
159 |
</div>
|
160 |
<!-- Viewer Container -->
|
161 |
-
<div id="viewer-container">
|
162 |
-
<canvas id="canvas"></canvas>
|
163 |
-
<div id="progress-dialog">
|
164 |
-
<progress id="progress-indicator" max="100" value="0"></progress>
|
165 |
</div>
|
166 |
-
<button id="close-btn" class="widget-button">X</button>
|
167 |
-
<button id="fullscreen-toggle" class="widget-button">⇱</button>
|
168 |
-
<button id="help-toggle" class="widget-button">?</button>
|
169 |
-
<button id="reset-camera-btn" class="widget-button">🗘</button>
|
170 |
-
<div id="menu-content">
|
171 |
- Rotate with right click<br>
|
172 |
- Zoom in/out with middle click<br>
|
173 |
- Translate with left click
|
@@ -176,18 +179,18 @@
|
|
176 |
`;
|
177 |
document.currentScript.parentNode.appendChild(widgetContainer);
|
178 |
|
179 |
-
// Grab element references.
|
180 |
-
var gifPreview = document.getElementById('gif-preview-container');
|
181 |
-
var viewerContainer = document.getElementById('viewer-container');
|
182 |
-
var previewImage = document.getElementById('preview-image');
|
183 |
-
var closeBtn = document.getElementById('close-btn');
|
184 |
-
var fullscreenToggle = document.getElementById('fullscreen-toggle');
|
185 |
-
var helpToggle = document.getElementById('help-toggle');
|
186 |
-
var resetCameraBtn = document.getElementById('reset-camera-btn');
|
187 |
-
var menuContent = document.getElementById('menu-content');
|
188 |
-
var canvas = document.getElementById('canvas');
|
189 |
-
var progressDialog = document.getElementById('progress-dialog');
|
190 |
-
var progressIndicator = document.getElementById('progress-indicator');
|
191 |
|
192 |
// Set the preview image if provided.
|
193 |
if (gifUrl) {
|
@@ -303,10 +306,8 @@
|
|
303 |
progressDialog.innerHTML = `<p style="color: red">Error loading model: ${error.message}</p>`;
|
304 |
}
|
305 |
|
306 |
-
|
307 |
const frame = () => {
|
308 |
controls.update();
|
309 |
-
|
310 |
renderer.render(scene, camera);
|
311 |
requestAnimationFrame(frame);
|
312 |
};
|
|
|
4 |
let controlsInstance = null;
|
5 |
let initialCameraPosition = null;
|
6 |
let initialCameraRotation = null;
|
7 |
+
|
8 |
+
// Generate a unique identifier for this widget instance.
|
9 |
+
const instanceId = Math.random().toString(36).substr(2, 8);
|
10 |
|
11 |
// Helper: Get query parameters from THIS script’s src URL.
|
12 |
function getScriptQueryParam(param) {
|
|
|
34 |
// Detect if the device is iOS.
|
35 |
var isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
36 |
|
37 |
+
// Inject CSS styles into the document head, scoped with the unique id.
|
38 |
var styleEl = document.createElement('style');
|
39 |
styleEl.textContent = `
|
40 |
/* Widget container styling */
|
41 |
+
#ply-widget-container-${instanceId} {
|
42 |
position: relative;
|
43 |
width: 100%;
|
44 |
height: 0;
|
45 |
padding-bottom: 100%;
|
46 |
}
|
47 |
/* When in fake fullscreen mode (iOS fallback) */
|
48 |
+
#ply-widget-container-${instanceId}.fake-fullscreen {
|
49 |
position: fixed !important;
|
50 |
top: 0 !important;
|
51 |
left: 0 !important;
|
|
|
55 |
z-index: 9999 !important;
|
56 |
}
|
57 |
/* GIF Preview styling */
|
58 |
+
#gif-preview-container-${instanceId} {
|
59 |
position: absolute;
|
60 |
top: 0;
|
61 |
left: 0;
|
|
|
66 |
overflow: hidden;
|
67 |
cursor: pointer;
|
68 |
}
|
69 |
+
#gif-preview-container-${instanceId} img {
|
70 |
width: 100%;
|
71 |
height: 100%;
|
72 |
object-fit: cover;
|
73 |
}
|
74 |
/* Viewer Container styling */
|
75 |
+
#viewer-container-${instanceId} {
|
76 |
display: none;
|
77 |
position: absolute;
|
78 |
top: 0;
|
|
|
84 |
border-radius: 10px;
|
85 |
}
|
86 |
/* Canvas fills the viewer container */
|
87 |
+
#canvas-${instanceId} {
|
88 |
width: 100%;
|
89 |
height: 100%;
|
90 |
display: block;
|
91 |
}
|
92 |
/* Progress dialog styling (as a centered div) */
|
93 |
+
#progress-dialog-${instanceId} {
|
94 |
position: absolute;
|
95 |
top: 50%;
|
96 |
left: 50%;
|
|
|
103 |
display: none;
|
104 |
}
|
105 |
/* Menu (instructions) content styling */
|
106 |
+
#menu-content-${instanceId} {
|
107 |
display: none;
|
108 |
position: absolute;
|
109 |
top: 62px;
|
|
|
132 |
justify-content: center;
|
133 |
}
|
134 |
/* Positions: Close at top-left, fullscreen at top-right, help (instructions) below fullscreen */
|
135 |
+
#close-btn-${instanceId} {
|
136 |
top: 17px;
|
137 |
left: 15px;
|
138 |
}
|
139 |
+
#fullscreen-toggle-${instanceId} {
|
140 |
top: 17px;
|
141 |
right: 15px;
|
142 |
}
|
143 |
+
#help-toggle-${instanceId} {
|
144 |
top: 72px;
|
145 |
right: 15px;
|
146 |
}
|
147 |
+
/* Reset Camera Button below the help button */
|
148 |
+
#reset-camera-btn-${instanceId} {
|
149 |
top: 127px;
|
150 |
right: 15px;
|
151 |
}
|
|
|
154 |
|
155 |
// Create the widget container and set its inner HTML.
|
156 |
var widgetContainer = document.createElement('div');
|
157 |
+
widgetContainer.id = 'ply-widget-container-' + instanceId;
|
158 |
widgetContainer.innerHTML = `
|
159 |
<!-- GIF Preview Container -->
|
160 |
+
<div id="gif-preview-container-${instanceId}">
|
161 |
+
<img id="preview-image-${instanceId}" alt="Preview" crossorigin="anonymous">
|
162 |
</div>
|
163 |
<!-- Viewer Container -->
|
164 |
+
<div id="viewer-container-${instanceId}">
|
165 |
+
<canvas id="canvas-${instanceId}"></canvas>
|
166 |
+
<div id="progress-dialog-${instanceId}">
|
167 |
+
<progress id="progress-indicator-${instanceId}" max="100" value="0"></progress>
|
168 |
</div>
|
169 |
+
<button id="close-btn-${instanceId}" class="widget-button">X</button>
|
170 |
+
<button id="fullscreen-toggle-${instanceId}" class="widget-button">⇱</button>
|
171 |
+
<button id="help-toggle-${instanceId}" class="widget-button">?</button>
|
172 |
+
<button id="reset-camera-btn-${instanceId}" class="widget-button">🗘</button>
|
173 |
+
<div id="menu-content-${instanceId}">
|
174 |
- Rotate with right click<br>
|
175 |
- Zoom in/out with middle click<br>
|
176 |
- Translate with left click
|
|
|
179 |
`;
|
180 |
document.currentScript.parentNode.appendChild(widgetContainer);
|
181 |
|
182 |
+
// Grab element references using the unique IDs.
|
183 |
+
var gifPreview = document.getElementById('gif-preview-container-' + instanceId);
|
184 |
+
var viewerContainer = document.getElementById('viewer-container-' + instanceId);
|
185 |
+
var previewImage = document.getElementById('preview-image-' + instanceId);
|
186 |
+
var closeBtn = document.getElementById('close-btn-' + instanceId);
|
187 |
+
var fullscreenToggle = document.getElementById('fullscreen-toggle-' + instanceId);
|
188 |
+
var helpToggle = document.getElementById('help-toggle-' + instanceId);
|
189 |
+
var resetCameraBtn = document.getElementById('reset-camera-btn-' + instanceId);
|
190 |
+
var menuContent = document.getElementById('menu-content-' + instanceId);
|
191 |
+
var canvas = document.getElementById('canvas-' + instanceId);
|
192 |
+
var progressDialog = document.getElementById('progress-dialog-' + instanceId);
|
193 |
+
var progressIndicator = document.getElementById('progress-indicator-' + instanceId);
|
194 |
|
195 |
// Set the preview image if provided.
|
196 |
if (gifUrl) {
|
|
|
306 |
progressDialog.innerHTML = `<p style="color: red">Error loading model: ${error.message}</p>`;
|
307 |
}
|
308 |
|
|
|
309 |
const frame = () => {
|
310 |
controls.update();
|
|
|
311 |
renderer.render(scene, camera);
|
312 |
requestAnimationFrame(frame);
|
313 |
};
|