@ridp/threejs 1.3.3 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/threejs.js CHANGED
@@ -1,74 +1,119 @@
1
- var R = Object.defineProperty;
2
- var g = (a, e, s) => e in a ? R(a, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : a[e] = s;
3
- var t = (a, e, s) => g(a, typeof e != "symbol" ? e + "" : e, s);
4
- import { I as M, i as q, o as F, c as I, b as k, a as H, u as W } from "./useGLTFLoader-MhUFIZp1.js";
5
- import { d as x, C as v, j as b } from "./ImageLoader-xzOH4Owt.js";
6
- import { I as V, h as _, g as G, b as N, c as J, a as U, e as Y, f as K, i as Q, k as X } from "./ImageLoader-xzOH4Owt.js";
7
- import { c as $, a as ee, d as te, e as se, g as ie, o as ne, b as re } from "./modelSerialize-DWUt6OcZ.js";
8
- import { MathUtils as m, Scene as L, PerspectiveCamera as O, WebGLRenderer as y, Box3 as S, Vector3 as c } from "three";
9
- const z = "1.3.2", T = {
1
+ var H = Object.defineProperty;
2
+ var A = (p, e, t) => e in p ? H(p, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : p[e] = t;
3
+ var o = (p, e, t) => A(p, typeof e != "symbol" ? e + "" : e, t);
4
+ import { i as se, o as oe, c as ie, b as ne, a as re, u as ae } from "./useBatchGLTFLoader-B5EUagWI.js";
5
+ import { d as P, S as j, s as V, j as q } from "./PredictiveLoader-CZfMSjv-.js";
6
+ import { C as ce, E as he, I as de, M as me, P as ue, q as fe, R as pe, n as xe, h as ge, g as Fe, b as Re, c as Me, a as Ee, e as Te, f as be, i as ze, l as we, m as Le, o as ve, k as Oe, p as Ce, r as ye, u as Se } from "./PredictiveLoader-CZfMSjv-.js";
7
+ import { I as Ie, c as He, a as Ae, g as Pe, i as je } from "./ImageLoader-Br_nvMOg.js";
8
+ import { ModelOptimizer as qe, modelOptimizer as Xe } from "./modelOptimizer-BRPnM2RH.js";
9
+ import { MathUtils as g, Scene as X, PerspectiveCamera as Y, WebGLRenderer as B, Box3 as Z, Vector3 as d, Box3Helper as _ } from "three";
10
+ const G = "1.4.1", N = 50, W = 20, k = 20, C = {
11
+ TOP: "top",
12
+ // 俯视(从上往下)
13
+ RIGHT: "right",
14
+ // 侧视(从右往左)
15
+ LEFT: "left",
16
+ // 左侧视
17
+ ISO: "iso"
18
+ // 正斜视(等轴测视角)
19
+ }, U = {
10
20
  enableDamping: !0,
11
21
  dampingFactor: 0.25,
12
22
  screenSpacePanning: !1,
13
23
  minDistance: 0.1,
14
24
  maxDistance: 1e3,
15
- maxPolarAngle: m.degToRad(60)
25
+ maxPolarAngle: g.degToRad(60)
16
26
  };
17
- class l {
18
- constructor(e, s) {
19
- t(this, "isReady", !1);
20
- t(this, "scene", null);
21
- t(this, "camera", null);
22
- t(this, "renderer", null);
23
- t(this, "control", null);
24
- t(this, "css3dRenderer", null);
25
- t(this, "el", null);
26
- t(this, "renderRequested", !1);
27
- t(this, "selector", null);
28
- t(this, "eventsListener", {});
29
- t(this, "stats", null);
30
- t(this, "isDispose", !1);
31
- t(this, "version", "0.0.0");
32
- t(this, "initOpt", {
27
+ class $ {
28
+ /**
29
+ * 构造函数
30
+ * @param {string} selector - DOM 容器选择器
31
+ * @param {Object} option - 配置选项
32
+ * @param {boolean} [option.css3d=false] - 是否启用 CSS3D 渲染器
33
+ * @param {boolean} [option.stats=false] - 是否显示性能统计
34
+ * @param {string} [option.renderType='change'] - 渲染类型: 'loop' 或 'change'
35
+ * @param {boolean} [option.initListener=true] - 是否初始化事件监听器
36
+ * @param {number} [option.initialFov=50] - 初始相机 FOV 值
37
+ * @param {Object} [option.control] - 控制器配置
38
+ * @param {boolean} [option.control.init=true] - 是否初始化控制器
39
+ * @param {Object} [option.control.options={}] - 控制器选项
40
+ */
41
+ constructor(e, t) {
42
+ o(this, "isReady", !1);
43
+ o(this, "scene", null);
44
+ o(this, "camera", null);
45
+ o(this, "renderer", null);
46
+ o(this, "control", null);
47
+ o(this, "css3dRenderer", null);
48
+ o(this, "el", null);
49
+ o(this, "renderRequested", !1);
50
+ o(this, "selector", null);
51
+ o(this, "eventsListener", {});
52
+ o(this, "stats", null);
53
+ o(this, "isDispose", !1);
54
+ o(this, "version", "0.0.0");
55
+ o(this, "boxHelper", null);
56
+ o(this, "initOpt", {
33
57
  css3d: !1,
34
58
  stats: !1,
35
59
  renderType: "change",
36
- initListener: "True",
60
+ initListener: !0,
61
+ // 使用布尔值代替字符串
62
+ initialFov: 50,
63
+ // 初始 FOV 值,用于避免全屏切换时的累积误差
37
64
  control: {
38
65
  init: !0,
39
66
  options: {}
40
67
  }
41
68
  });
42
- t(this, "setup", (e) => {
43
- this.isDispose = !1, this.selector = e, this.el = document.querySelector(e);
44
- const s = Math.tan(Math.PI / 180 * this.camera.fov / 2), [i, r] = this.getTargetSize();
45
- if (this.camera.aspect = i / r, this.camera.position.set(47, 39, 100), this.camera.fov = 360 / Math.PI * Math.atan(s * (r / i)), this.camera.lookAt(0, 0, 0), this.camera.updateProjectionMatrix(), this.renderer.setPixelRatio(window.devicePixelRatio), this.renderer.setSize(i, r), this.el.appendChild(this.renderer.domElement), this.initOpt.control && this.initOpt.control.init) {
46
- this.control = x(this.camera, this.renderer.domElement);
47
- const d = Object.assign(
48
- T,
69
+ /**
70
+ * 初始化场景
71
+ * @param {string} selector - DOM 容器选择器
72
+ */
73
+ o(this, "setup", (e) => {
74
+ if (this.isDispose = !1, this.selector = e, this.el = document.querySelector(e), !this.el) {
75
+ console.error(`ThreeIns: 找不到元素 ${e}`);
76
+ return;
77
+ }
78
+ const [t, l] = this.getTargetSize();
79
+ if (this.updateCameraFOV(t, l), this.camera.position.set(0, 0, 0), this.camera.lookAt(0, 0, 0), this.camera.updateProjectionMatrix(), this.renderer.setPixelRatio(window.devicePixelRatio), this.renderer.setSize(t, l), this.el.appendChild(this.renderer.domElement), this.initOpt.control && this.initOpt.control.init) {
80
+ this.control = P(this.camera, this.renderer.domElement);
81
+ const s = Object.assign(
82
+ U,
49
83
  this.initOpt.control.options || {}
50
84
  );
51
- Object.keys(d).forEach((n) => {
52
- this.control[n] = d[n];
85
+ Object.keys(s).forEach((x) => {
86
+ this.control[x] = s[x];
53
87
  });
54
88
  }
55
89
  setTimeout(() => {
56
90
  this.isReady = !0;
57
- }, 20), this.initOpt.stats && this.initStats(), this.initOpt.css3d && this.initCss3dRenderer(), this.initOpt.renderType === "loop" ? requestAnimationFrame(this.animate) : this.initOpt.renderType === "change" && this.control && this.control.addEventListener(
91
+ }, W), this.initOpt.stats && this.initStats(), this.initOpt.css3d && this.initCss3dRenderer(), this.initOpt.renderType === "loop" ? this.animate() : this.initOpt.renderType === "change" && this.control && this.control.addEventListener(
58
92
  "change",
59
93
  this.requestRenderIfNotRequested
60
94
  ), this.initListener();
61
95
  });
62
- t(this, "onContextLost", (e) => {
63
- e.preventDefault(), cancelAnimationFrame(this.animate);
96
+ /**
97
+ * WebGL 上下文丢失处理
98
+ * @param {Event} e - 事件对象
99
+ */
100
+ o(this, "onContextLost", (e) => {
101
+ e.preventDefault(), this.animationFrameId && cancelAnimationFrame(this.animationFrameId);
64
102
  });
65
- t(this, "onContextRestored", (e) => {
103
+ /**
104
+ * WebGL 上下文恢复处理
105
+ * @param {Event} e - 事件对象
106
+ */
107
+ o(this, "onContextRestored", (e) => {
66
108
  e.preventDefault(), this.dispose(), setTimeout(() => {
67
109
  this.setup(this.selector);
68
- }, 20);
110
+ }, k);
69
111
  });
70
- t(this, "initListener", () => {
71
- this.initOpt.initListener == "True" && window && window.addEventListener("resize", () => this.onResize(), !1), this.renderer.domElement.addEventListener(
112
+ /**
113
+ * 初始化事件监听器
114
+ */
115
+ o(this, "initListener", () => {
116
+ this.initOpt.initListener && window && window.addEventListener("resize", this.onResize, !1), this.renderer.domElement.addEventListener(
72
117
  "webglcontextlost",
73
118
  this.onContextLost,
74
119
  !1
@@ -78,113 +123,284 @@ class l {
78
123
  !1
79
124
  );
80
125
  });
81
- t(this, "removeListener", () => {
82
- window && window.removeEventListener("resize", this.onResize, !1), this.renderer.domElement.removeEventListener(
126
+ /**
127
+ * 移除事件监听器
128
+ */
129
+ o(this, "removeListener", () => {
130
+ window && window.removeEventListener("resize", this.onResize, !1), this.renderer && this.renderer.domElement && (this.renderer.domElement.removeEventListener(
83
131
  "webglcontextlost",
84
- this.onContextLost.bind(l),
132
+ this.onContextLost,
85
133
  !1
86
134
  ), this.renderer.domElement.removeEventListener(
87
135
  "webglcontextrestored",
88
- this.onContextRestored.bind(l),
136
+ this.onContextRestored,
89
137
  !1
90
- );
138
+ ));
91
139
  });
92
- t(this, "animate", () => {
93
- this.initOpt.renderType === "loop" && this.onRender(), requestAnimationFrame(this.animate);
140
+ /**
141
+ * 渲染循环(loop 模式)
142
+ */
143
+ o(this, "animate", () => {
144
+ this.isDispose || (this.initOpt.renderType === "loop" && this.onRender(), this.animationFrameId = requestAnimationFrame(this.animate));
94
145
  });
95
- t(this, "onRender", () => {
146
+ /**
147
+ * 执行渲染
148
+ */
149
+ o(this, "onRender", () => {
96
150
  this.isDispose || (this.renderRequested = !1, this.stats && this.stats.update(), this.control && this.control.update(), this.renderer.render(this.scene, this.camera), this.css3dRenderer && this.css3dRenderer.render(this.scene, this.camera), this.eventsListener.onRender && this.eventsListener.onRender.length && this.eventsListener.onRender.forEach((e) => e()));
97
151
  });
98
- t(this, "requestRenderIfNotRequested", () => {
152
+ /**
153
+ * 请求渲染(如果尚未请求)
154
+ */
155
+ o(this, "requestRenderIfNotRequested", () => {
99
156
  this.renderRequested || (this.renderRequested = !0, requestAnimationFrame(() => {
100
157
  this.onRender();
101
158
  }));
102
159
  });
103
- t(this, "onResize", () => {
104
- setTimeout(() => {
105
- const e = Math.tan(Math.PI / 180 * this.camera.fov / 2), [s, i] = this.getTargetSize();
106
- this.camera.aspect = s / i, this.camera.fov = 360 / Math.PI * Math.atan(e * (i / s)), this.camera.updateProjectionMatrix(), this.camera.lookAt(this.scene.position), this.renderer.setSize(s, i), this.css3dRenderer && this.css3dRenderer.setSize(s, i), this.onRender();
107
- }, 0);
160
+ /**
161
+ * 处理窗口大小变化(带防抖)
162
+ */
163
+ o(this, "onResize", () => {
164
+ this.resizeTimer && clearTimeout(this.resizeTimer), this.resizeTimer = setTimeout(() => {
165
+ const [e, t] = this.getTargetSize();
166
+ this.updateCameraFOV(e, t), this.camera.lookAt(this.scene.position), this.renderer.setSize(e, t), this.css3dRenderer && this.css3dRenderer.setSize(e, t), this.onRender();
167
+ }, N);
108
168
  });
109
- /**物体视窗自动适应
169
+ /**
170
+ * @deprecated 此方法已弃用,请使用 setView() 方法代替
171
+ *
172
+ * frameArea 仅为兼容旧版本保留,功能已被 setView() 完全覆盖
110
173
  *
111
- * @param {Object3D} model
112
- * @param {Number} scale
113
- * @param {Vector3} offset
174
+ * 旧用法:
175
+ * threeIns.frameArea(model, 1.0)
176
+ *
177
+ * 推荐用法:
178
+ * threeIns.setView(model, ViewType.ISO, { scale: 1.0 })
179
+ *
180
+ * @param {Object3D} model - 要调整视角的 3D 模型对象
181
+ * @param {number} [scale=0.8] - 缩放比例,1=占满画布,0.5=50%,2.0=200%
182
+ * @returns {Object} 返回 setView 的结果
114
183
  */
115
- t(this, "frameArea", (e, s, i) => {
116
- const r = new S().setFromObject(e), d = r.getSize(new c()).length(), n = r.getCenter(new c());
117
- i && n.add(i);
118
- const p = d * s * 0.5, u = m.degToRad(this.camera.fov * 0.5), f = p / Math.tan(u), h = new c().subVectors(this.camera.position, n).multiply(new c(1, 1, 1)).normalize().multiplyScalar(f).add(n), o = {
119
- x: h.x,
120
- y: h.y,
121
- z: h.z,
122
- lookAt_x: n.x,
123
- lookAt_y: n.y,
124
- lookAt_z: n.z
184
+ o(this, "frameArea", (e, t) => (console.warn(
185
+ `[ThreeIns] frameArea() 已弃用,建议使用 setView() 方法。
186
+ 旧用法: threeIns.frameArea(model, scale)
187
+ 新用法: threeIns.setView(model, ViewType.ISO, { scale })`
188
+ ), this.setView(e, C.ISO, { scale: t, animate: !1, showBox: !1 })));
189
+ /**
190
+ * 切换到指定视角
191
+ * 根据视角类型自动调整相机位置和朝向,支持缩放比例控制
192
+ *
193
+ * @param {Object3D} model - 3D 物体对象
194
+ * @param {string} viewType - 视角类型,使用 ViewType 枚举
195
+ * - 'top': 俯视(从上往下看 Y 轴正方向)
196
+ * - 'right': 侧视(从右往左看 X 轴正方向)
197
+ * - 'left': 左侧视(从左往右看 X 轴负方向)
198
+ * - 'iso': 正斜视(等轴测视角,45°角)
199
+ * @param {Object} [options] - 可选配置
200
+ * @param {number} [options.scale=1] - 缩放比例,控制模型在画布中的占比
201
+ * @param {Vector3} [options.offset] - 偏移量,调整观察中心点
202
+ * @param {boolean} [options.showBox=false] - 是否显示包围盒辅助线
203
+ * @param {number} [options.boxColor=0xffff00] - 包围盒颜色
204
+ * @param {boolean} [options.animate=true] - 是否使用动画过渡
205
+ * @param {number} [options.duration=1000] - 动画持续时间(毫秒)
206
+ * @returns {Object} 返回相机位置和模型信息
207
+ * @returns {Vector3} return.position - 相机位置
208
+ * @returns {Vector3} return.target - 相机观察目标点
209
+ * @returns {number} return.distance - 相机到模型的距离
210
+ *
211
+ * @example
212
+ * // 导入 ViewType 枚举
213
+ * import { ThreeIns, ViewType } from 'threejs';
214
+ *
215
+ * // 切换到俯视,模型占满画布
216
+ * threeIns.setView(model, ViewType.TOP);
217
+ *
218
+ * // 切换到等轴测,模型占画布的 80%
219
+ * threeIns.setView(model, ViewType.ISO, { scale: 0.8 });
220
+ *
221
+ * // 切换到斜视,显示包围盒,无动画
222
+ * threeIns.setView(model, ViewType.ISO, {
223
+ * showBox: true,
224
+ * animate: false
225
+ * });
226
+ *
227
+ * // 切换到侧视,自定义观察点
228
+ * threeIns.setView(model, ViewType.RIGHT, {
229
+ * offset: new THREE.Vector3(0, 10, 0),
230
+ * scale: 0.8
231
+ * });
232
+ *
233
+ * // 或者使用类静态属性(向后兼容)
234
+ * threeIns.setView(model, ThreeIns.ViewType.TOP);
235
+ */
236
+ o(this, "setView", (e, t, l = {}) => {
237
+ let s = l.scale || 0.8, x = l.offset || null, R = l.showBox || !1, y = l.boxColor || 16776960, T = l.animate !== void 0 ? l.animate : !0, b = l.duration || 1e3;
238
+ const F = new Z().setFromObject(e);
239
+ let c = F.getCenter(new d());
240
+ x && c.add(x);
241
+ const z = {
242
+ top: new d(0, 1, 0),
243
+ // 从上往下:Y 轴正方向
244
+ right: new d(2, 1, 1).normalize(),
245
+ // 从右往左:X 轴正方向
246
+ left: new d(-2, 1, 1).normalize(),
247
+ // 从左往右:X 轴负方向
248
+ iso: new d(0, 1, 1).normalize()
249
+ // 等轴测:从对角线上方俯视
250
+ }, M = z[t] || z.iso, i = F.getSize(new d()), w = this.camera.aspect, n = g.degToRad(this.camera.fov * 0.5), S = g.degToRad(80), h = Math.min(Math.atan(Math.tan(n) * w), S);
251
+ let m;
252
+ if (t === "top") {
253
+ const r = i.x * 0.5 / (Math.tan(h) * s), a = i.z * 0.5 / (Math.tan(n) * s);
254
+ m = Math.max(r, a);
255
+ } else if (t === "right" || t === "left") {
256
+ const r = i.y * 0.5 / (Math.tan(n) * s), a = i.z * 0.5 / (Math.tan(n) * s);
257
+ m = Math.max(r, a);
258
+ } else {
259
+ const r = i.x * 0.5 / (Math.tan(h) * s), a = i.y * 0.5 / (Math.tan(n) * s), f = i.z * 0.5 / (Math.tan(n) * s);
260
+ m = Math.max(r, a, f);
261
+ }
262
+ const u = M.clone().multiplyScalar(m).add(c);
263
+ if (R && (console.log("📍 相机位置验证:"), console.log(" - 方向向量:", M), console.log(" - 距离:", m.toFixed(2)), console.log(" - 包围盒中心:", c), console.log(" - 计算公式: direction * distance + boxCenter"), console.log(" - 目标位置:", u), console.log(" - 实际相机与中心的距离:", u.clone().sub(c).length().toFixed(2))), R ? (this.boxHelper && (this.scene.remove(this.boxHelper), this.boxHelper = null), this.boxHelper = new _(F, y), this.scene.add(this.boxHelper)) : this.boxHelper && (this.scene.remove(this.boxHelper), this.boxHelper = null), T) {
264
+ const r = this.camera.position.clone(), a = this.control ? this.control.target.clone() : new d(0, 0, 0), f = c, D = Date.now(), L = () => {
265
+ const I = Date.now() - D, v = Math.min(I / b, 1), O = 1 - Math.pow(1 - v, 3);
266
+ if (this.camera.position.lerpVectors(r, u, O), this.control) {
267
+ const E = new d();
268
+ E.lerpVectors(a, f, O), this.control.target.copy(E), this.camera.lookAt(E);
269
+ } else
270
+ this.camera.lookAt(c);
271
+ this.camera.updateProjectionMatrix(), v < 1 ? requestAnimationFrame(L) : (this.camera.position.copy(u), this.camera.lookAt(c), this.camera.updateProjectionMatrix(), this.control && (this.control.target.copy(c), this.control.update()), this.onRender());
272
+ };
273
+ L();
274
+ } else
275
+ this.camera.position.copy(u), this.camera.lookAt(c), this.camera.updateProjectionMatrix(), this.control && (this.control.target.copy(c), this.control.update()), this.onRender();
276
+ if (R) {
277
+ if (console.log("🎥 视角切换信息:"), console.log(" - 视角类型:", t), console.log(" - 相机位置:", u), console.log(" - 观察目标:", c), console.log(" - 方向向量:", M), console.log(" - 包围盒尺寸:", i), console.log(" - 包围盒中心:", F.getCenter(new d())), console.log(" - 水平 FOV:", g.radToDeg(h * 2).toFixed(2) + "°"), console.log(" - 垂直 FOV:", g.radToDeg(n * 2).toFixed(2) + "°"), console.log(" - 宽高比:", w.toFixed(4)), console.log(" - 模型宽度:", i.x.toFixed(2)), console.log(" - 模型高度:", i.y.toFixed(2)), console.log(" - 模型深度:", i.z.toFixed(2)), console.log(" - 传入的 scale 参数:", s), t === "top") {
278
+ const r = i.x * 0.5 / (Math.tan(h) * s), a = i.z * 0.5 / (Math.tan(n) * s);
279
+ console.log(" - 模型 X 尺寸 (宽度):", i.x.toFixed(2)), console.log(" - 模型 Z 尺寸 (深度):", i.z.toFixed(2)), console.log(" - tan(halfFovX):", Math.tan(h).toFixed(4)), console.log(" - tan(halfFovY):", Math.tan(n).toFixed(4)), console.log(" - X方向距离计算: (", (i.x * 0.5).toFixed(2), ") / (", Math.tan(h).toFixed(4), " *", s, ") =", r.toFixed(2)), console.log(" - Z方向距离计算: (", (i.z * 0.5).toFixed(2), ") / (", Math.tan(n).toFixed(4), " *", s, ") =", a.toFixed(2)), console.log(" - X方向距离 (scale=" + s + "):", r.toFixed(2)), console.log(" - Z方向距离 (scale=" + s + "):", a.toFixed(2));
280
+ } else if (t === "right" || t === "left") {
281
+ const r = i.y * 0.5 / (Math.tan(n) * s), a = i.z * 0.5 / (Math.tan(n) * s);
282
+ console.log(" - Y方向距离 (scale=" + s + "):", r.toFixed(2)), console.log(" - Z方向距离 (scale=" + s + "):", a.toFixed(2));
283
+ } else {
284
+ const r = i.x * 0.5 / (Math.tan(h) * s), a = i.y * 0.5 / (Math.tan(n) * s), f = i.z * 0.5 / (Math.tan(n) * s);
285
+ console.log(" - 模型 X 尺寸 (宽度):", i.x.toFixed(2)), console.log(" - 模型 Y 尺寸 (高度):", i.y.toFixed(2)), console.log(" - 模型 Z 尺寸 (深度):", i.z.toFixed(2)), console.log(" - tan(halfFovX):", Math.tan(h).toFixed(4)), console.log(" - tan(halfFovY):", Math.tan(n).toFixed(4)), console.log(" - X方向距离计算: (", (i.x * 0.5).toFixed(2), ") / (", Math.tan(h).toFixed(4), " *", s, ") =", r.toFixed(2)), console.log(" - Y方向距离计算: (", (i.y * 0.5).toFixed(2), ") / (", Math.tan(n).toFixed(4), " *", s, ") =", a.toFixed(2)), console.log(" - Z方向距离计算: (", (i.z * 0.5).toFixed(2), ") / (", Math.tan(n).toFixed(4), " *", s, ") =", f.toFixed(2)), console.log(" - X方向距离 (scale=" + s + "):", r.toFixed(2)), console.log(" - Y方向距离 (scale=" + s + "):", a.toFixed(2)), console.log(" - Z方向距离 (scale=" + s + "):", f.toFixed(2)), console.log(" - 最大距离 (Max):", Math.max(r, a, f).toFixed(2));
286
+ }
287
+ console.log(" - 最终距离:", m.toFixed(2)), console.log(" - 缩放比例:", s), console.log(" - 动画:", T ? "是 (" + b + "ms)" : "否");
288
+ }
289
+ return {
290
+ position: u,
291
+ target: c,
292
+ distance: m,
293
+ viewType: t
125
294
  };
126
- return this.camera.position.set(o.x, o.y, o.z), this.camera.lookAt(
127
- o.lookAt_x,
128
- o.lookAt_y,
129
- o.lookAt_z
130
- ), this.camera.updateProjectionMatrix(), this.control.target.copy(n), this.control.update(), d;
131
295
  });
132
- t(this, "on", (e, s) => {
133
- !e || !s || (this.eventsListener[e] || (this.eventsListener[e] = []), this.eventsListener[e].push(s));
134
- });
135
- this.isReady = !1, this.scene = new L({}), this.camera = new O(50, 1, 0.1, 2e3), this.renderer = new y({
296
+ /**
297
+ * 注册事件监听器
298
+ * @param {string} event - 事件名称
299
+ * @param {Function} callback - 回调函数
300
+ * @returns {Function} 返回取消监听的函数
301
+ */
302
+ o(this, "on", (e, t) => !e || !t || typeof t != "function" ? (console.warn("ThreeIns.on: 无效的参数"), () => {
303
+ }) : (this.eventsListener[e] || (this.eventsListener[e] = []), this.eventsListener[e].push(t), () => this.off(e, t)));
304
+ this.isReady = !1, this.scene = new X({}), this.camera = new Y(50, 1, 0.1, 2e3), this.renderer = new B({
136
305
  antialias: !0,
137
306
  alpha: !0,
138
307
  precision: "mediump",
139
308
  logarithmicDepthBuffer: !0
140
- }), this.version = z, s && (this.initOpt = Object.assign(this.initOpt, s)), e && this.setup(e);
309
+ }), this.version = G, this.onContextLost = this.onContextLost.bind(this), this.onContextRestored = this.onContextRestored.bind(this), this.onResize = this.onResize.bind(this), this.animate = this.animate.bind(this), this.resizeTimer = null, this.animationFrameId = null, t && (this.initOpt = Object.assign(this.initOpt, t)), e && this.setup(e);
310
+ }
311
+ /**
312
+ * 更新相机 FOV 以适应容器尺寸
313
+ * @private
314
+ * @param {number} domW - 容器宽度
315
+ * @param {number} domH - 容器高度
316
+ */
317
+ updateCameraFOV(e, t) {
318
+ const l = this.initOpt.initialFov || 50, s = Math.tan(Math.PI / 180 * l / 2);
319
+ this.camera.aspect = e / t, this.camera.fov = 360 / Math.PI * Math.atan(s * (t / e)), this.camera.updateProjectionMatrix();
141
320
  }
321
+ /**
322
+ * 初始化性能统计
323
+ */
142
324
  initStats() {
143
- const e = new Stats();
144
- e.dom.style.cssText = "position:absolute;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000", this.el.appendChild(e.dom);
325
+ this.stats = new j(), this.stats.dom.style.cssText = "position:absolute;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000", this.el.appendChild(this.stats.dom);
145
326
  }
327
+ /**
328
+ * 初始化 CSS3D 渲染器
329
+ */
146
330
  initCss3dRenderer() {
147
- this.css3dRenderer = new v();
148
- const [e, s] = this.getTargetSize();
149
- this.css3dRenderer.setSize(e, s), this.css3dRenderer.domElement.style.position = "absolute", this.css3dRenderer.domElement.style.pointerEvents = "none", this.css3dRenderer.domElement.style.top = 0, this.css3dRenderer.domElement.style.left = 0, this.el.appendChild(this.css3dRenderer.domElement);
331
+ this.css3dRenderer = new V();
332
+ const [e, t] = this.getTargetSize();
333
+ this.css3dRenderer.setSize(e, t), this.css3dRenderer.domElement.style.position = "absolute", this.css3dRenderer.domElement.style.pointerEvents = "none", this.css3dRenderer.domElement.style.top = 0, this.css3dRenderer.domElement.style.left = 0, this.el.appendChild(this.css3dRenderer.domElement);
150
334
  }
335
+ /**
336
+ * 获取目标容器尺寸
337
+ * 使用智能缓存策略:全屏时使用窗口尺寸,非全屏时使用元素尺寸
338
+ * @returns {[number, number]} [width, height]
339
+ */
151
340
  getTargetSize() {
152
- const e = document.querySelector(this.selector);
153
- return e ? [e.clientWidth, e.clientHeight] : [0, 0];
341
+ return document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement ? [window.innerWidth, window.innerHeight] : this.el ? !document.body.contains(this.el) && (console.warn(`ThreeIns: 缓存的元素已失效,重新查询 ${this.selector}`), this.el = document.querySelector(this.selector), !this.el) ? [0, 0] : [this.el.clientWidth, this.el.clientHeight] : [0, 0];
154
342
  }
155
- off(e) {
156
- e || (this.eventsListener = {}), this.eventsListener[e] && (this.eventsListener[e] = []);
343
+ /**
344
+ * 移除事件监听器
345
+ * @param {string} event - 事件名称
346
+ * @param {Function} [callback] - 可选的回调函数,如果不提供则移除该事件的所有监听器
347
+ */
348
+ off(e, t) {
349
+ if (!e) {
350
+ this.eventsListener = {};
351
+ return;
352
+ }
353
+ this.eventsListener[e] && (t ? this.eventsListener[e] = this.eventsListener[e].filter((l) => l !== t) : this.eventsListener[e] = []);
157
354
  }
355
+ /**
356
+ * 清理所有资源
357
+ */
158
358
  dispose() {
159
- this.isDispose = !0, this.removeListener(), b(this.scene), this.renderer.dispose(), this.renderer.domElement.remove(), this.el = null, this.renderer = null, this.camera = null, this.scene = null, this.control = null, this.css3dRenderer = null;
359
+ this.isDispose || (this.isDispose = !0, this.animationFrameId && (cancelAnimationFrame(this.animationFrameId), this.animationFrameId = null), this.resizeTimer && (clearTimeout(this.resizeTimer), this.resizeTimer = null), this.removeListener(), this.eventsListener = {}, this.stats && this.stats.dom && (this.stats.dom.remove(), this.stats = null), this.css3dRenderer && (this.css3dRenderer.domElement.remove(), this.css3dRenderer = null), this.boxHelper && (this.scene.remove(this.boxHelper), this.boxHelper = null), this.scene && (q(this.scene), this.scene = null), this.renderer && (this.renderer.dispose(), this.renderer.domElement && this.renderer.domElement.remove(), this.renderer = null), this.control && (this.control.dispose(), this.control = null), this.camera = null, this.el = null, this.selector = null, console.log("ThreeIns: 资源已清理完成"));
160
360
  }
161
361
  }
362
+ // 存储包围盒辅助器
363
+ // 视角类型枚举(作为类静态属性引用,保持向后兼容)
364
+ o($, "ViewType", C);
162
365
  export {
163
- M as IDBCache,
164
- V as ImageLoader,
165
- l as ThreeIns,
166
- _ as createArrowHelper,
167
- G as createAxesHelper,
168
- N as createBox3Helper,
169
- J as createCameraHelper,
170
- U as createGridHelper,
171
- $ as createInfoPlane,
172
- Y as createMapControls,
173
- x as createOrbitControl,
174
- K as createRaycaster,
175
- Q as createStats,
176
- ee as createTagPlane,
177
- te as dataToObject3D,
178
- se as dataToObject3DSync,
179
- b as disposeThreeObject,
180
- ie as getCommonParent,
181
- X as initEnvImage,
182
- q as intersectColor,
183
- F as obbObjects,
184
- ne as object3DToData,
185
- re as object3DToDataSync,
186
- I as useGLTFLoader,
187
- k as useObb,
188
- H as useRaycaster,
189
- W as useThreeJs
366
+ ce as CacheMonitor,
367
+ he as ErrorType,
368
+ de as IDBCache,
369
+ Ie as ImageLoader,
370
+ me as ModelLoadError,
371
+ qe as ModelOptimizer,
372
+ ue as PredictiveLoader,
373
+ fe as ProgressiveSceneBuilder,
374
+ pe as RetryHelper,
375
+ $ as ThreeIns,
376
+ C as ViewType,
377
+ xe as cacheMonitor,
378
+ ge as createArrowHelper,
379
+ Fe as createAxesHelper,
380
+ Re as createBox3Helper,
381
+ Me as createCameraHelper,
382
+ Ee as createGridHelper,
383
+ He as createInfoPlane,
384
+ Te as createMapControls,
385
+ P as createOrbitControl,
386
+ be as createRaycaster,
387
+ ze as createStats,
388
+ Ae as createTagPlane,
389
+ we as dataToObject3D,
390
+ Le as dataToObject3DSync,
391
+ q as disposeThreeObject,
392
+ Pe as getCommonParent,
393
+ je as initEnvImage,
394
+ se as intersectColor,
395
+ Xe as modelOptimizer,
396
+ oe as obbObjects,
397
+ ve as object3DToData,
398
+ Oe as object3DToDataSync,
399
+ Ce as predictiveLoader,
400
+ ye as rebuildScene,
401
+ ie as useBatchGLTFLoader,
402
+ Se as useGLTFLoader,
403
+ ne as useObb,
404
+ re as useRaycaster,
405
+ ae as useThreeJs
190
406
  };