UNPKG

@realsee/dnalogel

Version:
342 lines (341 loc) 15 kB
var M = Object.defineProperty, C = Object.defineProperties; var S = Object.getOwnPropertyDescriptors; var f = Object.getOwnPropertySymbols; var A = Object.prototype.hasOwnProperty, _ = Object.prototype.propertyIsEnumerable; var m = (h, o, t) => o in h ? M(h, o, { enumerable: !0, configurable: !0, writable: !0, value: t }) : h[o] = t, d = (h, o) => { for (var t in o || (o = {})) A.call(o, t) && m(h, t, o[t]); if (f) for (var t of f(o)) _.call(o, t) && m(h, t, o[t]); return h; }, p = (h, o) => C(h, S(o)); var r = (h, o, t) => (m(h, typeof o != "symbol" ? o + "" : o, t), t); var u = (h, o, t) => new Promise((i, e) => { var s = (n) => { try { c(t.next(n)); } catch (l) { e(l); } }, a = (n) => { try { c(t.throw(n)); } catch (l) { e(l); } }, c = (n) => n.done ? i(n.value) : Promise.resolve(n.value).then(s, a); c((t = t.apply(h, o)).next()); }); import * as g from "three"; import { Controller as k } from "../base/BasePluginWithData.js"; import "hammerjs"; import "@realsee/five"; import "../vendor/@tweenjs/tween/dist/tween.esm.js.js"; import "../CSS3DRenderPlugin/utils/three/CSS3DRender.js"; import "../CSS3DRenderPlugin/utils/generateBehindFiveElement.js"; import { equal as I } from "../shared-utils/equal.js"; import { AreaMakerItem as D } from "./utils/Item.js"; import "../base/BasePlugin.js"; import "../shared-utils/Subscribe.js"; import "../shared-utils/url/absoluteUrl.js"; import "../shared-utils/positionToVector3.js"; import "../CSS3DRenderPlugin/utils/three/CSS3DRenderer.js"; import "three/examples/jsm/renderers/CSS3DRenderer"; import "../CSS3DRenderPlugin/utils/getAllCSS3DObject.js"; import "../shared-utils/util.js"; import "../CSS3DRenderPlugin/utils/createResizeObserver.js"; import "../CSS3DRenderPlugin/utils/even.js"; import "../CSS3DRenderPlugin/utils/three/CSS3DObject.js"; import "../CSS3DRenderPlugin/utils/three/OpacityMesh.js"; import "../shared-utils/three/centerPoint.js"; import "../shared-utils/three/getObjectVisible.js"; import "../CSS3DRenderPlugin/utils/three/CSS3DScene.js"; import "../CSS3DRenderPlugin/utils/three/CSS3DGroup.js"; import "../shared-utils/isTruelyObject.js"; import "../shared-utils/three/core/Object3D.js"; import "../shared-utils/three/objects/LineSegments.js"; import "../shared-utils/animationFrame/BetterTween.js"; import "../shared-utils/animationFrame/index.js"; import "../components/AreaLabel/LabelItem.js"; import "../vendor/svelte/internal/index.js"; import "../components/AreaLabel/Assets/roomLabelBg.js"; import "../shared-utils/math/planimetry.js"; import "../shared-utils/dom/resizeObserver.js"; class ht extends k { /** AreaMakerPlugin * @param `five` `<Five>` Five 实例 * @param `params` `<PluginType.Params> | <undefined>` 插件初始化参数 * @param `params.initialState` `<PluginType.State> | <undefined>` 插件初始化后,使用的状态 */ constructor(t, i) { super(t); // ==================== public properties ==================== /** 插件当前状态 */ r(this, "state"); /** 标注模型 { id: item } 的映射表 */ r(this, "itemMap"); /** 自定义 DOM */ r(this, "itemRenderer"); /** 标注模型容器 */ r(this, "modelGroup"); /** 当前使用的数据 */ r(this, "data"); /** tag 容器 */ r(this, "tagDomContainer"); /** 查询问题使用的调试对象 */ r(this, "checkMsg", { childrenMountedState: "" }); // ==================== private properties ==================== /** 是否在 Five Change Mode 动画中 */ r(this, "isInFiveChangeModeAnime", !1); /** 子组件是否挂载 */ r(this, "childrenMountedState", !1); /** config 的原始值 */ r(this, "_config"); /** disposed 的原始值 */ r(this, "_disposed", !1); /** 销毁插件,移除所有副作用,销毁后将不响应任何 API */ r(this, "dispose", () => { this.five.scene.remove(this.modelGroup); }); r(this, "onFiveInitAnimationWillStart", () => { this.isInFiveChangeModeAnime = !0, this.updateChildrenMountedState(); }); r(this, "onFiveInitAnimationEnded", () => { this.isInFiveChangeModeAnime = !1, this.updateChildrenMountedState(); }); r(this, "onFiveCameraUpdate", () => { const t = this.five.camera; [...this.itemMap.values()].sort((e, s) => { const a = e.tagPosition.distanceTo(t.position); return s.tagPosition.distanceTo(t.position) - a; }).forEach((e, s) => { var a; (a = this.getMaskItemByID(e.id)) == null || a.setTagZIndex(s * 10); }); }); r(this, "onFiveModeChange", () => { this.updateChildrenMountedState(); }); r(this, "onMakerTagClick", (t) => { this.hooks.emit("wantsTap", { target: t.target, intersectObjects: [] }); }); r(this, "onWantsFiveTapGesture", (t) => { const i = Array.from(this.itemMap.values()).filter((n) => n.mounted && n.visible).map((n) => ({ makerItem: n, intersects: n.modelGroup.getRaycastIntersects(t) })).filter(({ intersects: n }) => n.length > 0); if (i.length === 0) return; const e = i.reduce((n, l) => { const v = n.intersects[0].distance, b = l.intersects[0].distance; return v < b ? n : l; }), s = this.five.model.intersectRaycaster(t)[0]; if (this.config.modelDepthTest && s && s.distance < e.intersects[0].distance) return; if (this.hooks.emit("wantsTap", { target: e.makerItem, intersectObjects: e.intersects })) return !1; }); this.five = t, this.tagDomContainer = document.createElement("div"), this.tagDomContainer.style.position = "absolute", this.tagDomContainer.style.top = "0", this.tagDomContainer.style.left = "0", this.tagDomContainer.style.width = "100%", this.tagDomContainer.style.height = "100%", this.tagDomContainer.style.pointerEvents = "none"; const e = { enabled: !0, visible: !0 }; this.state = Object.assign(e, i == null ? void 0 : i.initialState); const s = d({ modelDepthTest: !0 }, i == null ? void 0 : i.config); this._config = s, this.modelGroup = new g.Group(), this.modelGroup.name = "ModelMakerPluginGroup", this.itemMap = /* @__PURE__ */ new Map(), this.state.enabled && this._enable({ userAction: !1 }); } /** 插件配置项 */ get config() { return d({}, this._config); } /** 是否已经被销毁 */ get disposed() { return this._disposed; } /** 加载数据,重复调用会使用新数据覆盖旧数据 */ load(t) { return u(this, null, function* () { const i = this.data; this.data = this.formatData(t), this.hooks.emit("dataChange", this.data, i), this.modelGroup.remove(...this.modelGroup.children), this.itemMap.forEach((e) => e.unmount()), this.itemMap.clear(), this.childrenMountedState = !1, this.checkMsg.childrenMountedState = "", this.data.list.forEach((e) => { const s = new D(this, e); s.itemRenderer = this.itemRenderer, this.modelGroup.add(s.modelGroup), this.itemMap.set(e.id, s), s.hooks.on("tagClick", this.onMakerTagClick); }), this.updateChildrenMountedState(); }); } /** 将插件的 DOM 容器添加到指定的 DOM 元素上 */ appendTo(t) { t.appendChild(this.tagDomContainer); } /** 启用插件 * @param `options` `<Option> | <undefined>` * @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。 */ enable(t = {}) { var e; if (this.state.enabled) return; const i = (e = t.userAction) != null ? e : !0; this.updateState({ enabled: !0 }, i), this._enable({ userAction: i }); } /** 禁用插件 * @param `options` `<Option> | <undefined>` * @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。 */ disable(t = {}) { var e; if (this.state.enabled === !1) return; const i = (e = t.userAction) != null ? e : !0; this.updateState({ enabled: !1 }, i), this._disable({ userAction: i }); } /** 展示标注 * @param `options` `<Partial<ShowHideOptions>> | <undefined>` * @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。 */ show(t) { return u(this, null, function* () { if (this.state.visible) return Promise.resolve(); if (this.disposed) return Promise.reject(new Error("不能在已销毁的插件上调用 show")); const i = d({ userAction: !0 }, t); this.updateState({ visible: !0 }, i.userAction), yield this._show(i); }); } /** 插件内容整体隐藏 * @param `options` `<Partial<ShowHideOptions>> | <undefined>` * @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。 */ hide(t) { return u(this, null, function* () { if (this.state.visible === !1) return; const i = d({ userAction: !0 }, t); this.updateState({ visible: !1 }, i.userAction), yield this._hide(i); }); } // 目前带动画的展示和隐藏功能有些需求细节没有确定,暂时不实现 // /** 展示标注 // * @param `options` `<Partial<ShowHideOptions>> | <undefined>` // * @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。 // * @param `options.anime` `<AnimeOptions> | <undefined>` 动画配置。 // * @param `options.anime.duration` `<number> | <undefined>` 动画时间,默认是 500ms。 // */ // public async show(options?: Partial<PluginType.ShowHideOptions>): Promise<void> { // if (this.state.visible) return Promise.resolve() // if (this.disposed) return Promise.reject(new Error('不能在已销毁的插件上调用 show')) // const mergedOptions: PluginType.ShowHideOptions = { // userAction: true, // anime: { duration: 500, ...options?.anime }, // ...options, // } // this.updateState({ visible: true }, mergedOptions.userAction) // await this._show(mergedOptions) // } // /** 插件内容整体隐藏 // * @param `options` `<Partial<ShowHideOptions>> | <undefined>` // * @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。 // * @param `options.anime` `<AnimeOptions> | <undefined>` 动画配置。 // * @param `options.anime.duration` `<number> | <undefined>` 动画时间,默认是 500ms。 // */ // public async hide(options?: Partial<PluginType.ShowHideOptions>) { // if (this.state.visible === false) return // const mergedOptions: PluginType.ShowHideOptions = { // userAction: true, // anime: { duration: 500, ...options?.anime }, // ...options, // } // this.updateState({ visible: false }, mergedOptions.userAction) // await this._hide(mergedOptions) // } /** 更改插件 State * @param `state` `<Partial<Plugin.State>>` 插件属性 `state` 的子集。 * @param `options` `<Option> | <undefined>` * @param `options.userAction` `<boolean> | <undefined>` 是否是用户操作。默认是 true。 */ setState(t, i = {}) { const e = this.state; if (I(t, e, { deep: !0 })) return; const s = i.userAction !== void 0 ? i.userAction : !0; if (this.updateState(t, s), t.enabled !== void 0 && e.enabled !== t.enabled && (t.enabled ? this._enable({ userAction: s }) : this._disable({ userAction: s })), t.visible !== void 0 && e.visible !== t.visible) { const a = { userAction: s, anime: { duration: 500 } }; t.visible ? this._show(a) : this._hide(a); } } /** 更改插件 Config * @param `config` `<Partial<Plugin.Config>>` 插件属性 `config` 的子集。 * @param `options` `<Option> | <undefined>` */ updateConfig(t, i = {}) { var a; const e = this.config, s = d(d({}, e), t); this._config = s, this.hooks.emit("configChange", { prevConfig: e, config: s, userAction: (a = i.userAction) != null ? a : !0 }); } /** 根据 ID 获取标注 */ getMaskItemByID(t) { return this.itemMap.get(t); } formatData(t) { function i(e) { return e.list.length === 0 ? !0 : !("shape" in e.list[0].object_data); } return i(t) ? { list: t.list.filter((e) => e.object_data.points.length >= 3).map((e) => { const s = new g.Shape(), a = e.object_data.points[0]; return s.moveTo(a[0], a[2]), e.object_data.points.slice(1).forEach((n) => s.lineTo(n[0], n[2])), s.lineTo(a[0], a[2]), p(d({}, e), { floor_index: e.object_data.floorIndex, object_data: p(d({}, e.object_data), { bottom_y: a[1] + e.object_data.fixedY, shape: s.toJSON(), height: e.object_data.height + e.object_data.fixedHeight }) }); }) } : t; } checkChildrenMountedState() { const t = this.state, i = this.five; if (!t.enabled) return { result: !1, msg: "插件不可用" }; const e = i.getCurrentState().mode; return e === "Panorama" ? { result: !1, msg: `Five 模态不符合条件, 当前模态为:${e}` } : this.isInFiveChangeModeAnime ? { result: !1, msg: "切换模态动画中不展示" } : { result: !0, msg: "" }; } updateChildrenMountedState() { const { result: t, msg: i } = this.checkChildrenMountedState(); this.checkMsg.childrenMountedState = i, t !== this.childrenMountedState && (this.childrenMountedState = t, this.itemMap.forEach((e) => { this.childrenMountedState ? e.mount() : e.unmount(); })); } updateState(t, i) { const e = this.state; this.state = d(d({}, this.state), t), this.hooks.emit("stateChange", { state: this.state, prevState: e, userAction: i }); } _enable(t) { this.hooks.emit("enable", { userAction: t.userAction }), this.five.scene.add(this.modelGroup), this.updateChildrenMountedState(), this.five.needsRender = !0, this.five.on("wantsTapGesture", this.onWantsFiveTapGesture), this.five.on("initAnimationWillStart", this.onFiveInitAnimationWillStart), this.five.on("initAnimationEnded", this.onFiveInitAnimationEnded), this.five.on("modeChange", this.onFiveModeChange), this.five.on("cameraUpdate", this.onFiveCameraUpdate); } _disable(t) { this.hooks.emit("disable", { userAction: t.userAction }), this.five.scene.remove(this.modelGroup), this.updateChildrenMountedState(), this.five.needsRender = !0, this.five.off("wantsTapGesture", this.onWantsFiveTapGesture), this.five.off("initAnimationWillStart", this.onFiveInitAnimationWillStart), this.five.off("initAnimationEnded", this.onFiveInitAnimationEnded), this.five.off("modeChange", this.onFiveModeChange), this.five.off("cameraUpdate", this.onFiveCameraUpdate); } _show(t) { return u(this, null, function* () { this.hooks.emit("show", t), this.five.needsRender = !0; }); } _hide(t) { return u(this, null, function* () { this.hooks.emit("hide", t), this.five.needsRender = !0; }); } } export { ht as Controller };