UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

121 lines (120 loc) 4.35 kB
"use strict"; import { Matrix4, Vector3 } from "three"; const _vector = new Vector3(); const _viewMatrix = new Matrix4(); const _viewProjectionMatrix = new Matrix4(); const _a = new Vector3(); const _b = new Vector3(); export class CSS2DRenderer { constructor(parameters = {}) { this._width = 0; this._height = 0; this._widthHalf = 0; this._heightHalf = 0; this.dataByObject = /* @__PURE__ */ new WeakMap(); this.appendedObjects = /* @__PURE__ */ new Set(); this.objectsToRender = /* @__PURE__ */ new Set(); this.objectsToRemove = /* @__PURE__ */ new Set(); const domElement = parameters.element !== void 0 ? parameters.element : document.createElement("div"); domElement.style.overflow = "hidden"; this.domElement = domElement; } getSize() { return { width: this._width, height: this._height }; } render(scene, camera) { _viewMatrix.copy(camera.matrixWorldInverse); _viewProjectionMatrix.multiplyMatrices(camera.projectionMatrix, _viewMatrix); this.removeElementsDeletedFromSceneGraph(scene); this.renderObject(scene, scene, camera); this.zOrder(scene); } removeElementsDeletedFromSceneGraph(scene) { this.objectsToRender.clear(); scene.traverse((object) => { if (object.isCSS2DObject) { this.objectsToRender.add(object); } }); this.objectsToRemove.clear(); this.appendedObjects.forEach((appendedObject) => { if (!this.objectsToRender.has(appendedObject)) { this.objectsToRemove.add(appendedObject); } }); this.objectsToRemove.forEach((object) => { this.domElement.removeChild(object.element); this.appendedObjects.delete(object); }); } setSize(width, height) { this._width = width; this._height = height; this._widthHalf = this._width / 2; this._heightHalf = this._height / 2; this.domElement.style.width = width + "px"; this.domElement.style.height = height + "px"; } renderObject(object, scene, camera) { if (object.isCSS2DObject) { _vector.setFromMatrixPosition(object.matrixWorld); _vector.applyMatrix4(_viewProjectionMatrix); const visible = object.visible === true && _vector.z >= -1 && _vector.z <= 1 && object.layers.test(camera.layers) === true; object.element.style.display = visible === true ? "" : "none"; if (visible === true) { object.onBeforeRender(this, scene, camera); const element = object.element; element.style.transform = "translate(-50%,-50%) translate(" + (_vector.x * this._widthHalf + this._widthHalf) + "px," + (-_vector.y * this._heightHalf + this._heightHalf) + "px)"; if (element.parentNode !== this.domElement) { this.domElement.appendChild(element); this.appendedObjects.add(object); } object.onAfterRender(this, scene, camera); } let objectData = this.dataByObject.get(object); const distanceToCameraSquared = this.getDistanceToSquared(camera, object); if (!objectData) { objectData = { distanceToCameraSquared }; this.dataByObject.set(object, objectData); } else { objectData.distanceToCameraSquared = distanceToCameraSquared; } } for (const child of object.children) { this.renderObject(child, scene, camera); } } getDistanceToSquared(object1, object2) { _a.setFromMatrixPosition(object1.matrixWorld); _b.setFromMatrixPosition(object2.matrixWorld); return _a.distanceToSquared(_b); } filterAndFlatten(scene) { const result = []; scene.traverse(function(object) { if (object.isCSS2DObject) result.push(object); }); return result; } zOrder(scene) { const sorted = this.filterAndFlatten(scene).sort((a, b) => { var _a2, _b2; if (a.renderOrder !== b.renderOrder) { return b.renderOrder - a.renderOrder; } const distanceA = ((_a2 = this.dataByObject.get(a)) == null ? void 0 : _a2.distanceToCameraSquared) || 0; const distanceB = ((_b2 = this.dataByObject.get(b)) == null ? void 0 : _b2.distanceToCameraSquared) || 0; return distanceA - distanceB; }); const zMax = sorted.length; for (let i = 0, l = sorted.length; i < l; i++) { sorted[i].element.style.zIndex = `${zMax - i}`; } } }