cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
136 lines (135 loc) • 4.38 kB
JavaScript
import { Vector3, Matrix3, Triangle, Quaternion } from "../../../../_three@0.150.1@three/build/three.module.mjs";
import { CSS2DObject } from "../../../../_three@0.150.1@three/examples/jsm/renderers/CSS2DRenderer.mjs";
import { normalizeUnit } from "../styles/conversions.mjs";
import { parseExpressions } from "../styles/parsers.mjs";
/* @license
* Copyright 2020 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 a = new Vector3();
const b = new Vector3();
const c = new Vector3();
const mat = new Matrix3();
const triangle = new Triangle();
const quat = new Quaternion();
class Hotspot extends CSS2DObject {
constructor(config) {
super(document.createElement("div"));
this.normal = new Vector3(0, 1, 0);
this.initialized = false;
this.referenceCount = 1;
this.pivot = document.createElement("div");
this.slot = document.createElement("slot");
this.element.classList.add("annotation-wrapper");
this.slot.name = config.name;
this.element.appendChild(this.pivot);
this.pivot.appendChild(this.slot);
this.updatePosition(config.position);
this.updateNormal(config.normal);
this.surface = config.surface;
}
get facingCamera() {
return !this.element.classList.contains("hide");
}
show() {
if (!this.facingCamera || !this.initialized) {
this.updateVisibility(true);
}
}
hide() {
if (this.facingCamera || !this.initialized) {
this.updateVisibility(false);
}
}
increment() {
this.referenceCount++;
}
decrement() {
if (this.referenceCount > 0) {
--this.referenceCount;
}
return this.referenceCount === 0;
}
updatePosition(position) {
if (position == null)
return;
const positionNodes = parseExpressions(position)[0].terms;
for (let i = 0; i < 3; ++i) {
this.position.setComponent(i, normalizeUnit(positionNodes[i]).number);
}
this.updateMatrixWorld();
}
updateNormal(normal) {
if (normal == null)
return;
const normalNodes = parseExpressions(normal)[0].terms;
for (let i = 0; i < 3; ++i) {
this.normal.setComponent(i, normalNodes[i].number);
}
}
updateSurface(forceUpdate) {
if (!forceUpdate && this.initialized) {
return;
}
const { mesh, tri, bary } = this;
if (mesh == null || tri == null || bary == null) {
return;
}
mesh.getVertexPosition(tri.x, a);
mesh.getVertexPosition(tri.y, b);
mesh.getVertexPosition(tri.z, c);
a.toArray(mat.elements, 0);
b.toArray(mat.elements, 3);
c.toArray(mat.elements, 6);
this.position.copy(bary).applyMatrix3(mat);
const target = this.parent;
target.worldToLocal(mesh.localToWorld(this.position));
triangle.set(a, b, c);
triangle.getNormal(this.normal).transformDirection(mesh.matrixWorld);
const scene = target.parent;
quat.setFromAxisAngle(a.set(0, 1, 0), -scene.yaw);
this.normal.applyQuaternion(quat);
}
orient(radians) {
this.pivot.style.transform = `rotate(${radians}rad)`;
}
updateVisibility(show) {
if (show) {
this.element.classList.remove("hide");
} else {
this.element.classList.add("hide");
}
this.slot.assignedNodes().forEach((node) => {
if (node.nodeType !== Node.ELEMENT_NODE) {
return;
}
const element = node;
const visibilityAttribute = element.dataset.visibilityAttribute;
if (visibilityAttribute != null) {
const attributeName = `data-${visibilityAttribute}`;
if (show) {
element.setAttribute(attributeName, "");
} else {
element.removeAttribute(attributeName);
}
}
element.dispatchEvent(new CustomEvent("hotspot-visibility", {
detail: {
visible: show
}
}));
});
this.initialized = true;
}
}
export { Hotspot };