@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/ImageLoader-Br_nvMOg.js +1444 -0
- package/dist/ImageLoader-DL32KyTh.cjs +24 -0
- package/dist/PredictiveLoader-CZfMSjv-.js +3731 -0
- package/dist/PredictiveLoader-DDxh7dDg.cjs +2 -0
- package/dist/assets/gltfParser.worker-Bqz8BBJx.js +6 -0
- package/dist/assets/gltfParserOptimized.worker-DfipxPjm.js +6 -0
- package/dist/hooks.cjs +1 -1
- package/dist/hooks.js +7 -5
- package/dist/modelOptimizer-A0Cs6f9e.cjs +1 -0
- package/dist/modelOptimizer-BRPnM2RH.js +179 -0
- package/dist/threejs.cjs +3 -1
- package/dist/threejs.js +334 -118
- package/dist/useBatchGLTFLoader-B5EUagWI.js +493 -0
- package/dist/useBatchGLTFLoader-BjAvIpyB.cjs +5 -0
- package/dist/utils.cjs +1 -1
- package/dist/utils.js +32 -20
- package/package.json +1 -1
- package/readme.md +1186 -94
- package/dist/ImageLoader-DwvBWW6h.cjs +0 -5
- package/dist/ImageLoader-xzOH4Owt.js +0 -860
- package/dist/modelSerialize-B8gu_KnK.cjs +0 -15
- package/dist/modelSerialize-DWUt6OcZ.js +0 -276
- package/dist/useGLTFLoader-D01iU8lB.cjs +0 -2
- package/dist/useGLTFLoader-MhUFIZp1.js +0 -2510
package/dist/threejs.js
CHANGED
|
@@ -1,74 +1,119 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import {
|
|
5
|
-
import { d as
|
|
6
|
-
import { I as
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
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:
|
|
25
|
+
maxPolarAngle: g.degToRad(60)
|
|
16
26
|
};
|
|
17
|
-
class
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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:
|
|
60
|
+
initListener: !0,
|
|
61
|
+
// 使用布尔值代替字符串
|
|
62
|
+
initialFov: 50,
|
|
63
|
+
// 初始 FOV 值,用于避免全屏切换时的累积误差
|
|
37
64
|
control: {
|
|
38
65
|
init: !0,
|
|
39
66
|
options: {}
|
|
40
67
|
}
|
|
41
68
|
});
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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(
|
|
52
|
-
this.control[
|
|
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
|
-
},
|
|
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
|
-
|
|
63
|
-
|
|
96
|
+
/**
|
|
97
|
+
* WebGL 上下文丢失处理
|
|
98
|
+
* @param {Event} e - 事件对象
|
|
99
|
+
*/
|
|
100
|
+
o(this, "onContextLost", (e) => {
|
|
101
|
+
e.preventDefault(), this.animationFrameId && cancelAnimationFrame(this.animationFrameId);
|
|
64
102
|
});
|
|
65
|
-
|
|
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
|
-
},
|
|
110
|
+
}, k);
|
|
69
111
|
});
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
82
|
-
|
|
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
|
|
132
|
+
this.onContextLost,
|
|
85
133
|
!1
|
|
86
134
|
), this.renderer.domElement.removeEventListener(
|
|
87
135
|
"webglcontextrestored",
|
|
88
|
-
this.onContextRestored
|
|
136
|
+
this.onContextRestored,
|
|
89
137
|
!1
|
|
90
|
-
);
|
|
138
|
+
));
|
|
91
139
|
});
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
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
|
-
|
|
152
|
+
/**
|
|
153
|
+
* 请求渲染(如果尚未请求)
|
|
154
|
+
*/
|
|
155
|
+
o(this, "requestRenderIfNotRequested", () => {
|
|
99
156
|
this.renderRequested || (this.renderRequested = !0, requestAnimationFrame(() => {
|
|
100
157
|
this.onRender();
|
|
101
158
|
}));
|
|
102
159
|
});
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
|
148
|
-
const [e,
|
|
149
|
-
this.css3dRenderer.setSize(e,
|
|
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
|
-
|
|
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
|
-
|
|
156
|
-
|
|
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(),
|
|
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
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
};
|