UNPKG

cione-comp-lib

Version:

`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`

341 lines (340 loc) 14.2 kB
import { property as e } from "../../../../_@lit_reactive-element@1.6.1@@lit/reactive-element/decorators/property.mjs"; import "../../../../_@lit_reactive-element@1.6.1@@lit/reactive-element/decorators/query-assigned-elements.mjs"; import { USDZExporter } from "../../../../_three@0.150.1@three/examples/jsm/exporters/USDZExporter.mjs"; import { IS_WEBXR_AR_CANDIDATE, IS_SCENEVIEWER_CANDIDATE, IS_AR_QUICKLOOK_CANDIDATE } from "../constants.mjs"; import { $renderer, $scene, $needsRender, $updateSource, $shouldAttemptPreload, $progressTracker } from "../model-viewer-base.mjs"; import { enumerationDeserializer } from "../styles/deserializers.mjs"; import { ARStatus, ARTracking } from "../three-components/ARRenderer.mjs"; import { waitForEvent } from "../utilities.mjs"; /* @license * Copyright 2019 Google LLC. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the 'License'); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an 'AS IS' BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var __decorate = globalThis && globalThis.__decorate || function(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; let isWebXRBlocked = false; let isSceneViewerBlocked = false; const noArViewerSigil = "#model-viewer-no-ar-fallback"; const deserializeARModes = enumerationDeserializer(["quick-look", "scene-viewer", "webxr", "none"]); const DEFAULT_AR_MODES = "webxr scene-viewer quick-look"; const ARMode = { QUICK_LOOK: "quick-look", SCENE_VIEWER: "scene-viewer", WEBXR: "webxr", NONE: "none" }; const $arButtonContainer = Symbol("arButtonContainer"); const $enterARWithWebXR = Symbol("enterARWithWebXR"); const $openSceneViewer = Symbol("openSceneViewer"); const $openIOSARQuickLook = Symbol("openIOSARQuickLook"); const $canActivateAR = Symbol("canActivateAR"); const $arMode = Symbol("arMode"); const $arModes = Symbol("arModes"); const $arAnchor = Symbol("arAnchor"); const $preload = Symbol("preload"); const $onARButtonContainerClick = Symbol("onARButtonContainerClick"); const $onARStatus = Symbol("onARStatus"); const $onARTracking = Symbol("onARTracking"); const $onARTap = Symbol("onARTap"); const $selectARMode = Symbol("selectARMode"); const $triggerLoad = Symbol("triggerLoad"); const ARMixin = (ModelViewerElement) => { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; class ARModelViewerElement extends ModelViewerElement { constructor() { super(...arguments); this.ar = false; this.arScale = "auto"; this.arPlacement = "floor"; this.arModes = DEFAULT_AR_MODES; this.iosSrc = null; this.xrEnvironment = false; this[_a] = false; this[_b] = this.shadowRoot.querySelector(".ar-button"); this[_c] = document.createElement("a"); this[_d] = /* @__PURE__ */ new Set(); this[_e] = ARMode.NONE; this[_f] = false; this[_g] = (event) => { event.preventDefault(); this.activateAR(); }; this[_h] = ({ status }) => { if (status === ARStatus.NOT_PRESENTING || this[$renderer].arRenderer.presentedScene === this[$scene]) { this.setAttribute("ar-status", status); this.dispatchEvent(new CustomEvent("ar-status", { detail: { status } })); if (status === ARStatus.NOT_PRESENTING) { this.removeAttribute("ar-tracking"); } else if (status === ARStatus.SESSION_STARTED) { this.setAttribute("ar-tracking", ARTracking.TRACKING); } } }; this[_j] = ({ status }) => { this.setAttribute("ar-tracking", status); this.dispatchEvent(new CustomEvent("ar-tracking", { detail: { status } })); }; this[_k] = (event) => { if (event.data == "_apple_ar_quicklook_button_tapped") { this.dispatchEvent(new CustomEvent("quick-look-button-tapped")); } }; } get canActivateAR() { return this[$arMode] !== ARMode.NONE; } connectedCallback() { super.connectedCallback(); this[$renderer].arRenderer.addEventListener("status", this[$onARStatus]); this.setAttribute("ar-status", ARStatus.NOT_PRESENTING); this[$renderer].arRenderer.addEventListener("tracking", this[$onARTracking]); this[$arAnchor].addEventListener("message", this[$onARTap]); } disconnectedCallback() { super.disconnectedCallback(); this[$renderer].arRenderer.removeEventListener("status", this[$onARStatus]); this[$renderer].arRenderer.removeEventListener("tracking", this[$onARTracking]); this[$arAnchor].removeEventListener("message", this[$onARTap]); } update(changedProperties) { super.update(changedProperties); if (changedProperties.has("arScale")) { this[$scene].canScale = this.arScale !== "fixed"; } if (changedProperties.has("arPlacement")) { this[$scene].updateShadow(); this[$needsRender](); } if (changedProperties.has("arModes")) { this[$arModes] = deserializeARModes(this.arModes); } if (changedProperties.has("ar") || changedProperties.has("arModes") || changedProperties.has("src") || changedProperties.has("iosSrc")) { this[$selectARMode](); } } async activateAR() { switch (this[$arMode]) { case ARMode.QUICK_LOOK: this[$openIOSARQuickLook](); break; case ARMode.WEBXR: await this[$enterARWithWebXR](); break; case ARMode.SCENE_VIEWER: this[$openSceneViewer](); break; default: console.warn("No AR Mode can be activated. This is probably due to missing configuration or device capabilities"); break; } } async [(_a = $canActivateAR, _b = $arButtonContainer, _c = $arAnchor, _d = $arModes, _e = $arMode, _f = $preload, _g = $onARButtonContainerClick, _h = $onARStatus, _j = $onARTracking, _k = $onARTap, $selectARMode)]() { let arMode = ARMode.NONE; if (this.ar) { if (this.src != null) { for (const value of this[$arModes]) { if (value === "webxr" && IS_WEBXR_AR_CANDIDATE && !isWebXRBlocked && await this[$renderer].arRenderer.supportsPresentation()) { arMode = ARMode.WEBXR; break; } if (value === "scene-viewer" && IS_SCENEVIEWER_CANDIDATE && !isSceneViewerBlocked) { arMode = ARMode.SCENE_VIEWER; break; } if (value === "quick-look" && IS_AR_QUICKLOOK_CANDIDATE) { arMode = ARMode.QUICK_LOOK; break; } } } if (arMode === ARMode.NONE && this.iosSrc != null && IS_AR_QUICKLOOK_CANDIDATE) { arMode = ARMode.QUICK_LOOK; } } if (arMode !== ARMode.NONE) { this[$arButtonContainer].classList.add("enabled"); this[$arButtonContainer].addEventListener("click", this[$onARButtonContainerClick]); } else if (this[$arButtonContainer].classList.contains("enabled")) { this[$arButtonContainer].removeEventListener("click", this[$onARButtonContainerClick]); this[$arButtonContainer].classList.remove("enabled"); const status = ARStatus.FAILED; this.setAttribute("ar-status", status); this.dispatchEvent(new CustomEvent("ar-status", { detail: { status } })); } this[$arMode] = arMode; } async [$enterARWithWebXR]() { console.log("Attempting to present in AR with WebXR..."); await this[$triggerLoad](); try { this[$arButtonContainer].removeEventListener("click", this[$onARButtonContainerClick]); const { arRenderer } = this[$renderer]; arRenderer.placeOnWall = this.arPlacement === "wall"; await arRenderer.present(this[$scene], this.xrEnvironment); } catch (error) { console.warn("Error while trying to present in AR with WebXR"); console.error(error); await this[$renderer].arRenderer.stopPresenting(); isWebXRBlocked = true; console.warn("Falling back to next ar-mode"); await this[$selectARMode](); this.activateAR(); } finally { this[$selectARMode](); } } async [$triggerLoad]() { if (!this.loaded) { this[$preload] = true; this[$updateSource](); await waitForEvent(this, "load"); this[$preload] = false; } } [$shouldAttemptPreload]() { return super[$shouldAttemptPreload]() || this[$preload]; } [$openSceneViewer]() { const location = self.location.toString(); const locationUrl = new URL(location); const modelUrl = new URL(this.src, location); if (modelUrl.hash) modelUrl.hash = ""; const params = new URLSearchParams(modelUrl.search); locationUrl.hash = noArViewerSigil; params.set("mode", "ar_preferred"); if (!params.has("disable_occlusion")) { params.set("disable_occlusion", "true"); } if (this.arScale === "fixed") { params.set("resizable", "false"); } if (this.arPlacement === "wall") { params.set("enable_vertical_placement", "true"); } if (params.has("sound")) { const soundUrl = new URL(params.get("sound"), location); params.set("sound", soundUrl.toString()); } if (params.has("link")) { const linkUrl = new URL(params.get("link"), location); params.set("link", linkUrl.toString()); } const intent = `intent://arvr.google.com/scene-viewer/1.0?${params.toString() + "&file=" + encodeURIComponent(modelUrl.toString())}#Intent;scheme=https;package=com.google.ar.core;action=android.intent.action.VIEW;S.browser_fallback_url=${encodeURIComponent(locationUrl.toString())};end;`; const undoHashChange = () => { if (self.location.hash === noArViewerSigil) { isSceneViewerBlocked = true; self.history.back(); console.warn("Error while trying to present in AR with Scene Viewer"); console.warn("Falling back to next ar-mode"); this[$selectARMode](); } }; self.addEventListener("hashchange", undoHashChange, { once: true }); this[$arAnchor].setAttribute("href", intent); console.log("Attempting to present in AR with Scene Viewer..."); this[$arAnchor].click(); } async [$openIOSARQuickLook]() { const generateUsdz = !this.iosSrc; this[$arButtonContainer].classList.remove("enabled"); const objectURL = generateUsdz ? await this.prepareUSDZ() : this.iosSrc; const modelUrl = new URL(objectURL, self.location.toString()); if (generateUsdz) { const location = self.location.toString(); const locationUrl = new URL(location); const srcUrl = new URL(this.src, locationUrl); if (srcUrl.hash) { modelUrl.hash = srcUrl.hash; } } if (this.arScale === "fixed") { if (modelUrl.hash) { modelUrl.hash += "&"; } modelUrl.hash += "allowsContentScaling=0"; } const anchor = this[$arAnchor]; anchor.setAttribute("rel", "ar"); const img = document.createElement("img"); anchor.appendChild(img); anchor.setAttribute("href", modelUrl.toString()); if (generateUsdz) { anchor.setAttribute("download", "model.usdz"); } anchor.style.display = "none"; if (!anchor.isConnected) this.shadowRoot.appendChild(anchor); console.log("Attempting to present in AR with Quick Look..."); anchor.click(); anchor.removeChild(img); if (generateUsdz) { URL.revokeObjectURL(objectURL); } this[$arButtonContainer].classList.add("enabled"); } async prepareUSDZ() { const updateSourceProgress = this[$progressTracker].beginActivity(); await this[$triggerLoad](); const { model, shadow } = this[$scene]; if (model == null) { return ""; } let visible = false; if (shadow != null) { visible = shadow.visible; shadow.visible = false; } updateSourceProgress(0.2); const exporter = new USDZExporter(); const arraybuffer = await exporter.parse(model); const blob = new Blob([arraybuffer], { type: "model/vnd.usdz+zip" }); const url = URL.createObjectURL(blob); updateSourceProgress(1); if (shadow != null) { shadow.visible = visible; } return url; } } __decorate([ e({ type: Boolean, attribute: "ar" }) ], ARModelViewerElement.prototype, "ar", void 0); __decorate([ e({ type: String, attribute: "ar-scale" }) ], ARModelViewerElement.prototype, "arScale", void 0); __decorate([ e({ type: String, attribute: "ar-placement" }) ], ARModelViewerElement.prototype, "arPlacement", void 0); __decorate([ e({ type: String, attribute: "ar-modes" }) ], ARModelViewerElement.prototype, "arModes", void 0); __decorate([ e({ type: String, attribute: "ios-src" }) ], ARModelViewerElement.prototype, "iosSrc", void 0); __decorate([ e({ type: Boolean, attribute: "xr-environment" }) ], ARModelViewerElement.prototype, "xrEnvironment", void 0); return ARModelViewerElement; }; export { $openIOSARQuickLook, $openSceneViewer, ARMixin };