MikaFil commited on
Commit
8ca2873
·
verified ·
1 Parent(s): 263ad84

Update viewer_ar_ios.js

Browse files
Files changed (1) hide show
  1. viewer_ar_ios.js +67 -45
viewer_ar_ios.js CHANGED
@@ -1,7 +1,8 @@
1
  /* viewer_ar_ios.js — AR PlayCanvas + GLB/USDZ via config.json
2
  - Lit config.json (data-config) => { "glb_url": "...", "usdz_url": "..." }
3
- - iOS : AR Quick Look (USDZ) avec #allowsContentScaling=0 (pas de zoom)
4
  - Android/Desktop : WebXR AR (plans HORIZONTAUX uniquement) + slider yaw + blob shadow
 
5
  - Éclairage PBR par défaut (sans WebXR light estimation)
6
  - Monté dans un conteneur choisi (data-mount="#ar-mount") pour Squarespace
7
  */
@@ -106,28 +107,31 @@
106
  }
107
 
108
  // ============ UI / Overlay commun ============
109
- // Style minimal intégré : toasts + variante centrée pour le message initial.
110
- // (Si tu utilises un CSS externe, tu peux déplacer ces règles dans ce fichier.)
111
  var css = [
112
  /* Toast (bas) */
113
  ".pc-ar-msg{position:fixed;left:50%;transform:translateX(-50%);bottom:16px;z-index:10002;padding:10px 14px;background:rgba(0,0,0,.65);color:#fff;border-radius:12px;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-size:14px;line-height:1.3;text-align:center;max-width:min(90vw,640px);box-shadow:0 6px 20px rgba(0,0,0,.25);backdrop-filter:blur(4px);pointer-events:none}",
114
  /* Variante centrée + plus grande pour le message “Modèle chargé …” */
115
  ".pc-ar-msg.pc-ar-msg--centerBig{top:50%;bottom:auto;transform:translate(-50%,-50%);font-size:18px;padding:14px 18px;max-width:min(90vw,720px)}",
116
 
 
 
 
 
 
 
 
 
117
  "#xr-overlay-root{position:fixed;inset:0;z-index:10001;pointer-events:none}",
118
 
119
- /* --- NE PAS MODIFIER : panneau Rotation --- */
120
  ".ar-ui{position:absolute;right:12px;top:50%;transform:translateY(-50%);background:rgba(0,0,0,0.55);color:#fff;padding:12px 10px;border-radius:16px;width:56px;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;pointer-events:auto;display:flex;flex-direction:column;align-items:center;gap:8px;box-shadow:0 6px 18px rgba(0,0,0,.25);backdrop-filter:blur(6px);touch-action:none}",
121
  ".ar-ui .label{font-size:12px;text-align:center;opacity:.95}",
122
  ".rotY-wrap{position:relative;width:48px;height:200px;display:flex;align-items:center;justify-content:center;touch-action:none;overflow:visible;pointer-events:auto}",
123
  ".rotY-rail{position:absolute;left:50%;transform:translateX(-50%);width:4px;height:100%;background:rgba(255,255,255,.35);border-radius:2px;pointer-events:none}",
124
  ".rotY-knob{position:absolute;left:50%;width:22px;height:22px;border-radius:50%;background:#fff;box-shadow:0 2px 8px rgba(0,0,0,.35);transform:translate(-50%,-50%);top:50%;will-change:top;touch-action:none;pointer-events:none}",
125
  ".ar-ui input[type=\"range\"].rotY{position:absolute;opacity:0;pointer-events:none;width:0;height:0}",
126
- ".ar-ui .val{font-size:12px;opacity:.95}",
127
-
128
- /* iOS Quick Look button */
129
- "#ios-quicklook-btn{position:fixed;left:50%;transform:translateX(-50%);bottom:16px;z-index:10003;display:inline-block;pointer-events:auto}",
130
- "#ios-quicklook-btn img{display:block;height:44px;width:auto}"
131
  ].join("\n");
132
  var styleTag = document.createElement("style");
133
  styleTag.textContent = css;
@@ -179,24 +183,39 @@
179
  }
180
  }
181
 
182
- function ensureQuickLookButton(USDZ_URL) {
183
- var btn = document.getElementById("ios-quicklook-btn");
184
- if (btn) return btn;
185
-
186
- var anchor = document.createElement("a");
187
- anchor.id = "ios-quicklook-btn";
188
- anchor.setAttribute("rel", "ar");
189
- anchor.setAttribute("href", buildQuickLookHref(USDZ_URL));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
- var img = document.createElement("img");
192
- img.alt = "Voir en AR";
193
- img.src =
194
- "data:image/svg+xml;charset=utf-8," +
195
- encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="180" height="48"><rect rx="10" ry="10" width="180" height="48" fill="black"/><text x="90" y="30" font-size="16" text-anchor="middle" fill="white" font-family="system-ui, -apple-system, Segoe UI, Roboto">Voir en AR</text></svg>');
 
196
 
197
- anchor.appendChild(img);
198
- document.body.appendChild(anchor);
199
- return anchor;
200
  }
201
 
202
  // ============ Canvas monté dans un conteneur contrôlé (Squarespace) ============
@@ -248,7 +267,7 @@
248
  return canvas;
249
  }
250
 
251
- // ---------- Panneau “Rotation” (inchangé) ----------
252
  function ensureSliderUI() {
253
  var p = overlayRoot.querySelector(".ar-ui");
254
  if (p) return p;
@@ -266,27 +285,31 @@
266
  return p;
267
  }
268
 
269
- // ============ Boot : charge config, route iOS vs Android/Desktop ============
270
  (async function () {
271
  var cfgUrl = findConfigUrl();
272
  var cfg = await loadConfigJson(cfgUrl);
273
- var GLB_URL = (cfg && typeof cfg.glb_url === "string" && cfg.glb_url) ?
274
- cfg.glb_url :
275
- "https://huggingface.co/datasets/MikaFil/viewer_gs/resolve/main/AR/tests/danae_no_metallic.glb";
276
- var USDZ_URL = (cfg && typeof cfg.usdz_url === "string" && cfg.usdz_url) ?
277
- cfg.usdz_url :
278
- null;
279
-
 
280
  if (isIOS()) {
281
  if (USDZ_URL) {
282
- ensureQuickLookButton(USDZ_URL);
283
- messageToast("iOS détecté : utilisez le bouton « Voir en AR » (AR Quick Look).");
 
 
284
  } else {
285
  messageToast("iOS détecté, mais aucun 'usdz_url' dans config.json.");
286
  }
287
  return;
288
  }
289
 
 
290
  try {
291
  await loadPlayCanvasRobust({ esmFirst: true, loadTimeoutMs: 15000 });
292
  } catch (e) {
@@ -303,11 +326,11 @@
303
 
304
  // Canvas + UI
305
  var canvas = ensureCanvas();
306
- var sliderPanel = ensureSliderUI(); // (anciennement 'ui', plus explicite)
307
- var rotTrack = sliderPanel.querySelector("#ar-rotY-wrap"); // (anciennement rotWrap)
308
- var rotThumb = sliderPanel.querySelector("#ar-rotY-knob"); // (anciennement rotKnob)
309
- var rotRangeInput = sliderPanel.querySelector("#ar-rotY"); // (anciennement rotYInput)
310
- var rotValueLabel = sliderPanel.querySelector("#ar-rotY-val"); // (anciennement rotYVal)
311
 
312
  window.focus();
313
 
@@ -473,8 +496,7 @@
473
  baseEulerX = initE.x; baseEulerZ = initE.z;
474
 
475
  modelLoaded = true;
476
-
477
- // >>> Message centré & un peu plus grand pour l’invite initiale
478
  messageCenterBig("Modèle chargé. Touchez l’écran pour démarrer l’AR.");
479
  });
480
 
@@ -529,7 +551,7 @@
529
  document.addEventListener("pointerup", endDrag, { capture: true, passive: false });
530
  document.addEventListener("pointercancel", endDrag, { capture: true, passive: false });
531
 
532
- // --- Démarrage AR (Android/Desktop)
533
  function activateAR() {
534
  if (!app.xr.isAvailable(pc.XRTYPE_AR)) { messageToast("AR immersive indisponible sur cet appareil."); return; }
535
  if (!app.xr.domOverlay) app.xr.domOverlay = {};
@@ -593,7 +615,7 @@
593
  placedOnce = true;
594
  rotRangeInput.disabled = false;
595
 
596
- // Après placement, on repasse aux toasts bas classiques
597
  messageToast("Objet placé. Glissez pour déplacer, tournez-le avec le slider →");
598
  }
599
  });
 
1
  /* viewer_ar_ios.js — AR PlayCanvas + GLB/USDZ via config.json
2
  - Lit config.json (data-config) => { "glb_url": "...", "usdz_url": "..." }
3
+ - iOS : AR Quick Look (USDZ) avec #allowsContentScaling=0 (pas de zoom) + bouton “Lancer l’AR”
4
  - Android/Desktop : WebXR AR (plans HORIZONTAUX uniquement) + slider yaw + blob shadow
5
+ - Message de démarrage centré & plus grand sur iOS ET Android
6
  - Éclairage PBR par défaut (sans WebXR light estimation)
7
  - Monté dans un conteneur choisi (data-mount="#ar-mount") pour Squarespace
8
  */
 
107
  }
108
 
109
  // ============ UI / Overlay commun ============
110
+ // Style minimal intégré : toasts, message centré, bouton “Lancer l’AR” (iOS & Android).
 
111
  var css = [
112
  /* Toast (bas) */
113
  ".pc-ar-msg{position:fixed;left:50%;transform:translateX(-50%);bottom:16px;z-index:10002;padding:10px 14px;background:rgba(0,0,0,.65);color:#fff;border-radius:12px;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-size:14px;line-height:1.3;text-align:center;max-width:min(90vw,640px);box-shadow:0 6px 20px rgba(0,0,0,.25);backdrop-filter:blur(4px);pointer-events:none}",
114
  /* Variante centrée + plus grande pour le message “Modèle chargé …” */
115
  ".pc-ar-msg.pc-ar-msg--centerBig{top:50%;bottom:auto;transform:translate(-50%,-50%);font-size:18px;padding:14px 18px;max-width:min(90vw,720px)}",
116
 
117
+ /* Bouton “Lancer l’AR” */
118
+ "#ar-launch-btn{position:fixed;left:50%;transform:translateX(-50%);bottom:72px;z-index:10003;pointer-events:auto;appearance:none;border:none;border-radius:14px;padding:12px 18px;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-size:15px;font-weight:600;color:#fff;background:rgba(0,0,0,0.85);box-shadow:0 6px 18px rgba(0,0,0,.25);backdrop-filter:blur(6px);cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent}",
119
+ "#ar-launch-btn:active{transform:translateX(-50%) scale(0.98)}",
120
+ "#ar-launch-btn:disabled{opacity:.5;cursor:not-allowed}",
121
+
122
+ /* Ancre Quick Look cachée (iOS) */
123
+ "#ios-quicklook-anchor{position:absolute!important;width:1px!important;height:1px!important;overflow:hidden!important;clip-path:inset(50%)!important;pointer-events:none!important}",
124
+
125
  "#xr-overlay-root{position:fixed;inset:0;z-index:10001;pointer-events:none}",
126
 
127
+ /* --- NE PAS MODIFIER : panneau Rotation (WebXR) --- */
128
  ".ar-ui{position:absolute;right:12px;top:50%;transform:translateY(-50%);background:rgba(0,0,0,0.55);color:#fff;padding:12px 10px;border-radius:16px;width:56px;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;pointer-events:auto;display:flex;flex-direction:column;align-items:center;gap:8px;box-shadow:0 6px 18px rgba(0,0,0,.25);backdrop-filter:blur(6px);touch-action:none}",
129
  ".ar-ui .label{font-size:12px;text-align:center;opacity:.95}",
130
  ".rotY-wrap{position:relative;width:48px;height:200px;display:flex;align-items:center;justify-content:center;touch-action:none;overflow:visible;pointer-events:auto}",
131
  ".rotY-rail{position:absolute;left:50%;transform:translateX(-50%);width:4px;height:100%;background:rgba(255,255,255,.35);border-radius:2px;pointer-events:none}",
132
  ".rotY-knob{position:absolute;left:50%;width:22px;height:22px;border-radius:50%;background:#fff;box-shadow:0 2px 8px rgba(0,0,0,.35);transform:translate(-50%,-50%);top:50%;will-change:top;touch-action:none;pointer-events:none}",
133
  ".ar-ui input[type=\"range\"].rotY{position:absolute;opacity:0;pointer-events:none;width:0;height:0}",
134
+ ".ar-ui .val{font-size:12px;opacity:.95}"
 
 
 
 
135
  ].join("\n");
136
  var styleTag = document.createElement("style");
137
  styleTag.textContent = css;
 
183
  }
184
  }
185
 
186
+ // Bouton “Lancer l’AR” (visible) + ancre Quick Look (cachée) pour iOS
187
+ function ensureIOSLaunchUI(usdzUrl) {
188
+ // Ancre cachée qui déclenche Quick Look
189
+ var anchor = document.getElementById("ios-quicklook-anchor");
190
+ if (!anchor) {
191
+ anchor = document.createElement("a");
192
+ anchor.id = "ios-quicklook-anchor";
193
+ anchor.setAttribute("rel", "ar");
194
+ document.body.appendChild(anchor);
195
+ }
196
+ if (usdzUrl) anchor.setAttribute("href", buildQuickLookHref(usdzUrl));
197
+
198
+ // Bouton visible “Lancer l’AR”
199
+ var btn = document.getElementById("ar-launch-btn");
200
+ if (!btn) {
201
+ btn = document.createElement("button");
202
+ btn.id = "ar-launch-btn";
203
+ btn.type = "button";
204
+ btn.textContent = "Lancer l’AR";
205
+ // Évite la propagation d’events vers la scène
206
+ btn.addEventListener("pointerdown", function (e) { e.stopPropagation(); }, { passive: true });
207
+ btn.addEventListener("click", function (e) { e.stopPropagation(); }, false);
208
+ document.body.appendChild(btn);
209
+ }
210
 
211
+ // Clic => simulateur de clic sur l’ancre rel="ar"
212
+ btn.onclick = function (e) {
213
+ e.preventDefault();
214
+ e.stopPropagation();
215
+ if (anchor && anchor.href) anchor.click();
216
+ };
217
 
218
+ return { btn: btn, anchor: anchor };
 
 
219
  }
220
 
221
  // ============ Canvas monté dans un conteneur contrôlé (Squarespace) ============
 
267
  return canvas;
268
  }
269
 
270
+ // ---------- Panneau “Rotation” (inchangé pour WebXR) ----------
271
  function ensureSliderUI() {
272
  var p = overlayRoot.querySelector(".ar-ui");
273
  if (p) return p;
 
285
  return p;
286
  }
287
 
288
+ // ============ Boot : charge config, branche iOS vs Android/Desktop ============
289
  (async function () {
290
  var cfgUrl = findConfigUrl();
291
  var cfg = await loadConfigJson(cfgUrl);
292
+ var GLB_URL = (cfg && typeof cfg.glb_url === "string" && cfg.glb_url)
293
+ ? cfg.glb_url
294
+ : "https://huggingface.co/datasets/MikaFil/viewer_gs/resolve/main/AR/tests/danae_no_metallic.glb";
295
+ var USDZ_URL = (cfg && typeof cfg.usdz_url === "string" && cfg.usdz_url)
296
+ ? cfg.usdz_url
297
+ : null;
298
+
299
+ // --------- iOS : Quick Look + message centré + bouton “Lancer l’AR” ---------
300
  if (isIOS()) {
301
  if (USDZ_URL) {
302
+ // UI iOS (ancre rel=ar + bouton visible)
303
+ ensureIOSLaunchUI(USDZ_URL);
304
+ // Message de démarrage centré et plus grand (même UX que WebXR)
305
+ messageCenterBig("Modèle chargé. Appuyez sur « Lancer l’AR » pour démarrer.");
306
  } else {
307
  messageToast("iOS détecté, mais aucun 'usdz_url' dans config.json.");
308
  }
309
  return;
310
  }
311
 
312
+ // --------- Android / Desktop : WebXR ---------
313
  try {
314
  await loadPlayCanvasRobust({ esmFirst: true, loadTimeoutMs: 15000 });
315
  } catch (e) {
 
326
 
327
  // Canvas + UI
328
  var canvas = ensureCanvas();
329
+ var sliderPanel = ensureSliderUI();
330
+ var rotTrack = sliderPanel.querySelector("#ar-rotY-wrap");
331
+ var rotThumb = sliderPanel.querySelector("#ar-rotY-knob");
332
+ var rotRangeInput = sliderPanel.querySelector("#ar-rotY");
333
+ var rotValueLabel = sliderPanel.querySelector("#ar-rotY-val");
334
 
335
  window.focus();
336
 
 
496
  baseEulerX = initE.x; baseEulerZ = initE.z;
497
 
498
  modelLoaded = true;
499
+ // Message de démarrage centré & plus grand (même UX que iOS)
 
500
  messageCenterBig("Modèle chargé. Touchez l’écran pour démarrer l’AR.");
501
  });
502
 
 
551
  document.addEventListener("pointerup", endDrag, { capture: true, passive: false });
552
  document.addEventListener("pointercancel", endDrag, { capture: true, passive: false });
553
 
554
+ // --- Démarrage AR (tap écran)
555
  function activateAR() {
556
  if (!app.xr.isAvailable(pc.XRTYPE_AR)) { messageToast("AR immersive indisponible sur cet appareil."); return; }
557
  if (!app.xr.domOverlay) app.xr.domOverlay = {};
 
615
  placedOnce = true;
616
  rotRangeInput.disabled = false;
617
 
618
+ // Après placement, toasts bas classiques
619
  messageToast("Objet placé. Glissez pour déplacer, tournez-le avec le slider →");
620
  }
621
  });