cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
169 lines (168 loc) • 6.09 kB
JavaScript
import { Matrix4, Vector3 } from "../../../../_three@0.150.1@three/build/three.module.mjs";
import { $needsRender, $tick, $scene, toVector3D, toVector2D } from "../model-viewer-base.mjs";
import { Hotspot } from "../three-components/Hotspot.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.
*/
const $hotspotMap = Symbol("hotspotMap");
const $mutationCallback = Symbol("mutationCallback");
const $observer = Symbol("observer");
const $addHotspot = Symbol("addHotspot");
const $removeHotspot = Symbol("removeHotspot");
const worldToModel = new Matrix4();
const AnnotationMixin = (ModelViewerElement) => {
var _a, _b, _c;
class AnnotationModelViewerElement extends ModelViewerElement {
constructor() {
super(...arguments);
this[_a] = /* @__PURE__ */ new Map();
this[_b] = (mutations) => {
mutations.forEach((mutation) => {
if (!(mutation instanceof MutationRecord) || mutation.type === "childList") {
mutation.addedNodes.forEach((node) => {
this[$addHotspot](node);
});
mutation.removedNodes.forEach((node) => {
this[$removeHotspot](node);
});
this[$needsRender]();
}
});
};
this[_c] = new MutationObserver(this[$mutationCallback]);
}
connectedCallback() {
super.connectedCallback();
for (let i = 0; i < this.children.length; ++i) {
this[$addHotspot](this.children[i]);
}
const { ShadyDOM } = self;
if (ShadyDOM == null) {
this[$observer].observe(this, { childList: true });
} else {
this[$observer] = ShadyDOM.observeChildren(this, this[$mutationCallback]);
}
}
disconnectedCallback() {
super.disconnectedCallback();
const { ShadyDOM } = self;
if (ShadyDOM == null) {
this[$observer].disconnect();
} else {
ShadyDOM.unobserveChildren(this[$observer]);
}
}
[(_a = $hotspotMap, _b = $mutationCallback, _c = $observer, $tick)](time, delta) {
super[$tick](time, delta);
const scene = this[$scene];
const { annotationRenderer } = scene;
const camera = scene.getCamera();
if (scene.shouldRender()) {
scene.updateSurfaceHotspots();
scene.updateHotspotsVisibility(camera.position);
annotationRenderer.domElement.style.display = "";
annotationRenderer.render(scene, camera);
}
}
updateHotspot(config) {
const hotspot = this[$hotspotMap].get(config.name);
if (hotspot == null) {
return;
}
hotspot.updatePosition(config.position);
hotspot.updateNormal(config.normal);
hotspot.surface = config.surface;
this[$needsRender]();
}
queryHotspot(name) {
const hotspot = this[$hotspotMap].get(name);
if (hotspot == null) {
return null;
}
const position = toVector3D(hotspot.position);
const normal = toVector3D(hotspot.normal);
const facingCamera = hotspot.facingCamera;
const scene = this[$scene];
const camera = scene.getCamera();
const vector = new Vector3();
vector.setFromMatrixPosition(hotspot.matrixWorld);
vector.project(camera);
const widthHalf = scene.width / 2;
const heightHalf = scene.height / 2;
vector.x = vector.x * widthHalf + widthHalf;
vector.y = -(vector.y * heightHalf) + heightHalf;
const canvasPosition = toVector3D(new Vector3(vector.x, vector.y, vector.z));
if (!Number.isFinite(canvasPosition.x) || !Number.isFinite(canvasPosition.y)) {
return null;
}
return { position, normal, canvasPosition, facingCamera };
}
positionAndNormalFromPoint(pixelX, pixelY) {
const scene = this[$scene];
const ndcPosition = scene.getNDC(pixelX, pixelY);
const hit = scene.positionAndNormalFromPoint(ndcPosition);
if (hit == null) {
return null;
}
worldToModel.copy(scene.target.matrixWorld).invert();
const position = toVector3D(hit.position.applyMatrix4(worldToModel));
const normal = toVector3D(hit.normal.transformDirection(worldToModel));
let uv = null;
if (hit.uv != null) {
uv = toVector2D(hit.uv);
}
return { position, normal, uv };
}
surfaceFromPoint(pixelX, pixelY) {
const scene = this[$scene];
const ndcPosition = scene.getNDC(pixelX, pixelY);
return scene.surfaceFromPoint(ndcPosition);
}
[$addHotspot](node) {
if (!(node instanceof HTMLElement && node.slot.indexOf("hotspot") === 0)) {
return;
}
let hotspot = this[$hotspotMap].get(node.slot);
if (hotspot != null) {
hotspot.increment();
} else {
hotspot = new Hotspot({
name: node.slot,
position: node.dataset.position,
normal: node.dataset.normal,
surface: node.dataset.surface
});
this[$hotspotMap].set(node.slot, hotspot);
this[$scene].addHotspot(hotspot);
}
this[$scene].queueRender();
}
[$removeHotspot](node) {
if (!(node instanceof HTMLElement)) {
return;
}
const hotspot = this[$hotspotMap].get(node.slot);
if (!hotspot) {
return;
}
if (hotspot.decrement()) {
this[$scene].removeHotspot(hotspot);
this[$hotspotMap].delete(node.slot);
}
this[$scene].queueRender();
}
}
return AnnotationModelViewerElement;
};
export { AnnotationMixin };