UNPKG

@realsee/dnalogel

Version:
506 lines (499 loc) 22 kB
var V = Object.defineProperty, T = Object.defineProperties; var U = Object.getOwnPropertyDescriptors; var k = Object.getOwnPropertySymbols; var x = Object.prototype.hasOwnProperty, F = Object.prototype.propertyIsEnumerable; var v = (l, e, t) => e in l ? V(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t, d = (l, e) => { for (var t in e || (e = {})) x.call(e, t) && v(l, t, e[t]); if (k) for (var t of k(e)) F.call(e, t) && v(l, t, e[t]); return l; }, p = (l, e) => T(l, U(e)); var i = (l, e, t) => (v(l, typeof e != "symbol" ? e + "" : e, t), t); import * as n from "three"; import { logWarning as L, logError as S } from "../../shared-utils/log.js"; import { createLineGeometry as O } from "../utils/createLineGeometry.js"; import { isPanoramaLike as _, isModelLike as M } from "../../shared-utils/five/mode.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 "animejs"; import { notNil as w } from "../../shared-utils/isNil.js"; import { BetterTween as E, tweenProgress as A } from "../../shared-utils/animationFrame/BetterTween.js"; import { loadTexture as G } from "../../shared-utils/three/loadTexture.js"; import P from "../../PanoTagPlugin/controller/index.js"; import B from "../Components/Tag.js"; import { filterAdjacentDistinct as W } from "../utils/index.js"; import { objectAssignDeepExports as I } from "../../vendor/object-assign-deep/objectAssignDeep.js"; const R = ( /* glsl */ ` varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } ` ), N = ( /* glsl */ ` // 是否使用颜色 uniform int useMapColor; // 贴图 uniform sampler2D map; // 贴图颜色 uniform vec3 mapColor; // 贴图透明度 uniform float mapOpacity; // 背景颜色 uniform vec3 backgroundColor; // 边框颜色 uniform vec3 borderColor; // 边框透明度 uniform float borderOpacity; // 边框宽度 uniform float borderWidth; // 背景透明度 uniform float backgroundOpacity; // @link https://developer.mozilla.org/en-US/docs/Web/CSS/background-clip uniform int backgroundClip; // 整体透明度 uniform float opacity; // 最大 U 值 uniform float maxU; // v offset uniform float vOffset; // 闪烁动画值 uniform float flicker; // 纹理坐标 varying vec2 vUv; // 获取纹理颜色 vec4 getImage() { vec2 uv = vUv; uv.y = uv.y - vOffset; // 原始贴图颜色 vec4 image = texture2D(map, uv); // 如果使用颜色 if (useMapColor == 1) { // 混合颜色 image = mix(image, vec4(mapColor, image.a), image.a); } image.a = image.a * mapOpacity; return image; } // 获取线性渐变的透明度 float linearGradientOpacity() { // 当前的 v 值 float v = vUv.y; float gradientLength = 1.0; if (v <= gradientLength) { return v / gradientLength; // 在 [0, gradientLength] 范围内,透明度为 [0, 1] } else if (v <= maxU - gradientLength) { return 1.0; // 在 (gradientLength, maxU - gradientLength) 范围内,透明度为 1 } else { return (maxU - v) / gradientLength; // 在 [maxU - gradientLength, maxU] 范围内,透明度为 [1, 0] } } vec4 getBorder() { float u = vUv.x; if (u <= borderWidth || u >= 1.0 - borderWidth) { return vec4(borderColor, borderOpacity); } return vec4(0.0, 0.0, 0.0, 0.0); } vec4 getBackground() { // border-box if (backgroundClip == 0) { return vec4(backgroundColor, backgroundOpacity); } else { // padding-box float u = vUv.x; if (u > borderWidth && u < 1.0 - borderWidth) { return vec4(backgroundColor, backgroundOpacity); } return vec4(0.0, 0.0, 0.0, 0.0); } } void main() { vec4 image = getImage(); vec4 border = getBorder(); vec4 background = getBackground(); // 设置背景颜色 gl_FragColor = background; // 混合颜色和背景 gl_FragColor = mix(background, vec4(image.rgb, image.a * 0.4 + 0.6), image.a); // image.a * 0.4 + 0.6 先这么写,但是不是最优解 // 混合边框 gl_FragColor = mix(gl_FragColor, border, border.a); // 设置整体透明度 gl_FragColor.a = gl_FragColor.a * opacity; gl_FragColor.a = gl_FragColor.a * linearGradientOpacity(); gl_FragColor.a = gl_FragColor.a * flicker; } ` ); class H { constructor(e, t) { i(this, "name", ""); i(this, "startTagContainer"); i(this, "endTagContainer"); i(this, "path", []); i(this, "geometryStyle", {}); i(this, "materialStyle", {}); i(this, "meshStyle", {}); i(this, "mesh"); i(this, "five"); i(this, "mode"); i(this, "_curvePath", null); i(this, "_curvePoints", null); i(this, "_panoGroup", []); i(this, "skippedPositions", null); i(this, "textureUrl", ""); i(this, "scale", 1); i(this, "width", 0.5); i(this, "unitLength", 0.5); i(this, "_visibleFloorIndexes", null); i(this, "visible", null); /** Five Mode 是否满足 */ i(this, "modeVisible", !1); /** 楼层是否满足展示条件 */ i(this, "floorVisible", !0); /** 默认是否展示 */ i(this, "defaultVisible", !1); /** 走点动画 */ i(this, "inWalkAnimation", !1); i(this, "customVisible", null); i(this, "parent"); i(this, "plugin"); i(this, "textureHasLoaded", !1); i(this, "disposed", !1); i(this, "flowAnime", new E({ progress: 0 }).to({ progress: 1 }).duration(1500).repeat(1 / 0)); i(this, "flickerAnime", A(300).yoyo(!0).repeat(5)); /** 缓存 panoGroup 中每个点距离起点的长度 */ i(this, "cacheLengths", []); /** 为了让多条路线在高度上错开,每个路线都需要有个额外的 offset */ i(this, "heightOffset", 0); i(this, "dispose", () => { var e, t; this.disposed || (this.disposed = !0, this.parent.hooks.off("show", this.updateVisible), this.parent.hooks.off("hide", this.updateVisible), this.plugin.hooks.off("show", this.updateVisible), this.plugin.hooks.off("hide", this.updateVisible), this.plugin.hooks.off("enable", this.updateVisible), this.plugin.hooks.off("disable", this.updateVisible), this.five.off("modeChange", this.onFiveModeChange), this.five.off("modelShownFloorChange", this.onFiveModelShownFloorChange), this.doHide(), (e = this.startTagContainer) == null || e.plugin.dispose(), (t = this.endTagContainer) == null || t.plugin.dispose()); }); /** 开始走点动画 */ i(this, "onWalkAnimationStart", () => { this.inWalkAnimation = !0, this.updateVisible(); }); /** 结束走点动画 */ i(this, "onWalkAnimationEnd", () => { this.inWalkAnimation = !1, this.updateVisible(); }); /** 模型状态变更 */ i(this, "onFiveModeChange", (e) => { this.modeVisible = this.mode === "panorama" ? _(e) : M(e), this.updateVisible(); }); i(this, "onFiveModelShownFloorChange", (e) => { this.floorVisible = e === null || this.visibleFloorIndexes === null || this.visibleFloorIndexes.includes(e), this.updateVisible(); }); /** 更新可见性 */ i(this, "updateVisible", () => { const e = (() => !this.parent.visible || !this.plugin.state.enabled || !this.plugin.state.visible ? !1 : this.customVisible !== null ? this.customVisible : this.inWalkAnimation ? !0 : this.modeVisible && this.textureHasLoaded && this.defaultVisible && this.floorVisible)(); this.visible !== e && (this.visible = e, e ? this.doShow() : this.doHide()); }); i(this, "onFlowAnimeUpdate", (e) => { const { progress: t } = e; this.mesh.material.uniforms.vOffset.value = t, this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0; }); i(this, "onFlickerAnimeUpdate", (e) => { var r, o, a, h; const { progress: t } = e, s = 1 - t; this.mesh.material.uniforms.flicker.value = s, this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0, this.startTagContainer.tag && b(this.startTagContainer.tag) && ((a = this.startTagContainer.app) == null || a.$set(p(d({}, this.startTagContainer.tag.data), { opacity: s, name: this.name, distance: Math.round((o = (r = this.curvePath) == null ? void 0 : r.getLength()) != null ? o : 0) }))), this.endTagContainer.tag && b(this.endTagContainer.tag) && ((h = this.endTagContainer.app) == null || h.$set(p(d({}, this.endTagContainer.tag.data), { opacity: s }))); }); i(this, "logWarning", (e) => L("GuideLineModeItem: ", e)); i(this, "logError", (e) => S("GuideLineModeItem: ", e)); var o, a; this.five = e, this.mode = t.mode, this.plugin = t.plugin, this.parent = t.parent, this.startTagContainer = { tag: null, plugin: new P(this.five) }, this.endTagContainer = { tag: null, plugin: new P(this.five) }; const s = new n.BufferGeometry(), r = new n.ShaderMaterial({ vertexShader: R, fragmentShader: N, transparent: !0, uniforms: { map: { value: null }, useMapColor: { value: 0 }, mapColor: { value: new n.Color() }, mapOpacity: { value: 1 }, backgroundColor: { value: new n.Color() }, backgroundOpacity: { value: 0 }, borderColor: { value: new n.Color() }, borderOpacity: { value: 0 }, backgroundClip: { value: 0 }, borderWidth: { value: 0.05 }, opacity: { value: 1 }, flicker: { value: 1 }, maxU: { value: 0 }, vOffset: { value: 0 } } }); this.mesh = new n.Mesh(s, r), this.mesh.name = "GuideLineModeItem", this.mode === "panorama" && (this.parent.hooks.on("walkStart", this.onWalkAnimationStart), this.parent.hooks.on("walkEnded", this.onWalkAnimationEnd)), this.updateVisible(), this.onFiveModeChange(this.five.getCurrentState().mode), this.onFiveModelShownFloorChange((a = (o = this.five.model) == null ? void 0 : o.shownFloor) != null ? a : null), this.flowAnime.onUpdate(this.onFlowAnimeUpdate), this.flickerAnime.onUpdate(this.onFlickerAnimeUpdate), this.parent.hooks.on("show", this.updateVisible), this.parent.hooks.on("hide", this.updateVisible), this.plugin.hooks.on("show", this.updateVisible), this.plugin.hooks.on("hide", this.updateVisible), this.plugin.hooks.on("enable", this.updateVisible), this.plugin.hooks.on("disable", this.updateVisible), this.plugin.hooks.on("dispose", this.dispose), this.five.on("modeChange", this.onFiveModeChange), this.five.on("modelShownFloorChange", this.onFiveModelShownFloorChange); } get panoGroup() { return this._panoGroup; } /** 可展示的楼层 */ get visibleFloorIndexes() { return this._visibleFloorIndexes; } /** THREE Curve 路径 */ get curvePath() { return this._curvePath; } /** THREE Curve 路径上的点 */ get curvePoints() { return this._curvePoints; } /** 自定义展示 */ setCustomVisible(e) { if (this.disposed) return this.logError("disposed"); this.customVisible !== e && (this.customVisible = e, this.updateVisible()); } /** 设置默认展示 */ setDefaultVisible(e) { if (this.disposed) return this.logError("disposed"); this.defaultVisible !== e && (this.defaultVisible = e, this.updateVisible()); } /** 基础宽、长 */ setUnitSize(e, t) { if (this.disposed) return this.logError("disposed"); this.width = e, this.unitLength = t, this.setGeometryByPath(this.path, { width: e, unit_length: t }); } /** 设置缩放 */ setScale(e) { if (this.disposed) return this.logError("disposed"); this.scale = e, this.setGeometryByPath(this.path, { scale: e }); } /** 通过点位设置线条形状 */ setGeometryByPanoGroup(e, t) { if (this.disposed) return this.logError("disposed"); if (!this.five.work) return this.logError("setPathByPanoGroup: work is not ready"); const s = W(e); if (this._panoGroup = s, (t == null ? void 0 : t.skipPanoGroup) !== void 0) { const o = t.skipPanoGroup ? s.map((a) => this.plugin.workUtils.getObserverStandingPosition(a)).filter(w) : null; this.skippedPositions = o; } const r = this.getPathFromPanoGroup(s, this.five.work, t); this.path = r, this.setGeometryByPath(r, t); } /** 通过路径设置线条形状 */ setGeometryByPath(e, t) { var c, y, C; if (this.disposed) return this.logError("disposed"); const s = (c = t == null ? void 0 : t.scale) != null ? c : this.scale, r = (y = t == null ? void 0 : t.width) != null ? y : this.width, o = (C = t == null ? void 0 : t.unit_length) != null ? C : this.unitLength; this.scale = s, this.width = r, this.unitLength = o; const { geometry: a, maxU: h, curvePath: u, curvePoints: g } = O({ path: e, width: r * s, unitLength: o * s, skipPositions: this.skippedPositions }); this._curvePath = u, this._curvePoints = g, this.mesh.geometry = a, this.mesh.material.needsUpdate = !0, this.mesh.material.uniforms.maxU.value = h, this.five.needsRender = !0; const m = e, f = d(d({}, this.geometryStyle), t); this.path = m, this.geometryStyle = f; } /** 设置线条材质 */ setMartial(e) { var s, r, o, a, h; if (this.disposed) return this.logError("disposed"); this.setDefaultVisible((s = e == null ? void 0 : e.visible) != null ? s : !1), this.setColor((r = e == null ? void 0 : e.color) != null ? r : "#ffffff"), this.setOpacity((o = e == null ? void 0 : e.opacity) != null ? o : 0.5), this.setTextureUrl((h = (a = e == null ? void 0 : e.texture) == null ? void 0 : a.url) != null ? h : "https://vr-image-4.realsee-cdn.cn/release/web/arrow1.ebe7d0ff.png"), (e == null ? void 0 : e.background_color) !== void 0 && this.setBackgroundColor(e.background_color), (e == null ? void 0 : e.background_opacity) !== void 0 && this.setBackgroundOpacity(e.background_opacity), (e == null ? void 0 : e.border_color) !== void 0 && this.setBorderColor(e.border_color), (e == null ? void 0 : e.border_opacity) !== void 0 && this.setBorderOpacity(e.border_opacity), (e == null ? void 0 : e.border_width) !== void 0 && this.setBorderWidth(e.border_width), (e == null ? void 0 : e.background_clip) !== void 0 && this.setBackgroundClip(e.background_clip); const t = d(d({}, this.materialStyle), e); this.materialStyle = t; } /** 设置模型状态 */ setMeshStyle(e) { if (e != null && e.translate) { const r = new n.Vector3(), o = new n.Vector3().fromArray(e.translate); o.y += this.heightOffset, r.add(o), this.mesh.position.copy(r), s(this.startTagContainer, o), s(this.endTagContainer, o); } const t = d(d({}, this.meshStyle), e); this.meshStyle = t; function s(r, o) { if (!r.tag) return; const a = new n.Vector3().fromArray(r.tag.position); a.add(o); const h = a.toArray(); r.plugin.changeTagById(r.tag.id, { position: h }); } } /** 设置 Y 轴上的偏移量,为了让多条路线在高度上错开,每个路线都需要有个额外的 offset */ setHeightOffset(e) { const t = new n.Vector3(); this.meshStyle.translate && t.add(new n.Vector3().fromArray(this.meshStyle.translate)), t.setY(t.y + e), this.mesh.position.copy(t), this.heightOffset = e, this.five.needsRender = !0; } /** 设置贴图颜色 */ setColor(e) { if (this.disposed) return this.logError("disposed"); e && (this.mesh.material.uniforms.mapColor.value = new n.Color().set(e)), this.mesh.material.uniforms.useMapColor.value = e ? 1 : 0, this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0; } /** 设置边框 */ setBorderColor(e) { if (this.disposed) return this.logError("disposed"); this.mesh.material.uniforms.borderColor.value = new n.Color().set(e), this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0; } /** 设置边框透明度 */ setBorderOpacity(e) { if (this.disposed) return this.logError("disposed"); this.mesh.material.uniforms.borderOpacity.value = e, this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0; } setBackgroundClip(e) { if (this.disposed) return this.logError("disposed"); this.mesh.material.uniforms.backgroundClip.value = e === "border-box" ? 0 : 1, this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0; } /** * @description: 设置边框宽度 */ setBorderWidth(e) { if (this.disposed) return this.logError("disposed"); this.mesh.material.uniforms.borderWidth.value = e, this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0; } /** 设置背景颜色 */ setBackgroundColor(e) { if (this.disposed) return this.logError("disposed"); this.mesh.material.uniforms.backgroundColor.value = new n.Color().set(e), this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0; } /** 设置背景透明度 */ setBackgroundOpacity(e) { if (this.disposed) return this.logError("disposed"); this.mesh.material.uniforms.backgroundOpacity.value = e, this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0; } /** 设置整体透明度 */ setOpacity(e) { if (this.disposed) return this.logError("disposed"); this.mesh.material.uniforms.opacity.value = e, this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0; } /** 设置贴图透明度 */ setMapOpacity(e) { if (this.disposed) return this.logError("disposed"); this.mesh.material.uniforms.mapOpacity.value = e, this.mesh.material.uniformsNeedUpdate = !0, this.five.needsRender = !0; } /** 设置贴图 */ setTextureUrl(e) { if (this.disposed) return this.logError("disposed"); this.textureUrl = e, G(e).then((t) => { this.disposed || this.textureUrl === e && (t.wrapT = n.RepeatWrapping, this.textureHasLoaded = !0, this.mesh.material.uniforms.map.value = t, this.mesh.material.uniformsNeedUpdate = !0, this.mesh.material.needsUpdate = !0, this.five.needsRender = !0, this.updateVisible()); }); } setVisibleFloorIndexes(e) { var t, s; if (this.disposed) return this.logError("disposed"); this._visibleFloorIndexes = e, this.onFiveModelShownFloorChange((s = (t = this.five.model) == null ? void 0 : t.shownFloor) != null ? s : null); } setStartTag(e) { this.setTag("start", e); } setEndTag(e) { this.setTag("end", e); } /** 闪烁 */ flicker() { if (this.disposed) return this.logError("disposed"); this.flickerAnime.play(); } /** 求起点到 panoIndex 曲线长度 * @param index panoIndex 在 panoGroup 中的索引 * * @description 为什么不使用 panoIndex 作为参数? * - panoIndex 在一个曲线中可能出现多次,无法确定是哪一个。 */ getLengthByPanoGroupIndex(e) { return this.disposed ? this.logError("disposed") : this.cacheLengths.length !== 0 ? this.cacheLengths[e] : (this.cacheLengths = this.getPanoGroupLengths(), this.cacheLengths[e]); } getPanoGroupLengths() { var u; if (!this.curvePoints || !this.curvePath) return []; const e = this.curvePoints.length, t = this.curvePath.getLength(), s = e - 1, r = t / s, o = (u = this.curvePath.getLengths(s)) != null ? u : [], a = []; let h = 0; for (let g = 0; g < e; g++) { const m = this.curvePoints[g], f = this.plugin.workUtils.getObserverStandingPosition(h); if (!f) break; f.clone().setY(0).distanceTo(m.clone().setY(0)) < r && (a.push(o[g]), h += 1); } return a; } setTag(e, t) { const s = this.curvePath, r = e === "start" ? this.startTagContainer : this.endTagContainer; if (!(t != null && t.data)) return r.plugin.clearTags(); const a = I({}, { contentType: "Custom", stickType: "2DPoint", config: { visibleConfig: { visibleFiveMode: ["Floorplan", "Mapview"], followModelVisibility: !1 } }, style: { point: { enabled: !1 } }, data: {} }, t); r.tag = a, b(a) && (r.tag.element = (u) => { var f, c; (f = r.app) == null || f.$destroy(); const g = e === "start" ? p(d({}, a.data), { name: this.name, distance: Math.round((c = s.getLength()) != null ? c : 0), i18n: this.plugin.config.i18n }) : a.data, m = new B({ target: u, intro: !0, props: g }); return r.app = m, () => m.$destroy(); }), r.plugin.load({ tagList: [r.tag] }); const h = this.meshStyle.translate; if (h && a.position) { const u = new n.Vector3().fromArray(a.position), g = new n.Vector3().fromArray(h); u.add(g), u.y += this.heightOffset; const m = u.toArray(); r.plugin.changeTagById(r.tag.id, { position: m }); } } doShow() { this.mode === "model" && this.flowAnime.play(), this.five.scene.add(this.mesh), this.startTagContainer.plugin.show(), this.endTagContainer.plugin.show(), this.five.needsRender = !0; } doHide() { this.mode === "model" && this.flowAnime.stop(), this.five.scene.remove(this.mesh), this.startTagContainer.plugin.hide(), this.endTagContainer.plugin.hide(), this.five.needsRender = !0; } /** 通过 panoIndex 数组计算路径 */ getPathFromPanoGroup(e, t, s) { if (e.length < 2) return []; const r = e.map((o) => { var a; return (a = this.plugin.workUtils.getObserverStandingPosition(o)) == null ? void 0 : a.toArray(); }).filter(w); return [d({ type: "CatmullRomCurve3", points: r }, s)]; } } function b(l) { return l.contentType === "Custom"; } const oe = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, GuideLineModeItem: H }, Symbol.toStringTag, { value: "Module" })); export { H as GuideLineModeItem, oe as GuideLineModeItem$1 };