@chocozhang/three-model-render 1.0.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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +609 -0
  3. package/dist/camera/index.d.ts +133 -0
  4. package/dist/camera/index.js +291 -0
  5. package/dist/camera/index.js.map +1 -0
  6. package/dist/camera/index.mjs +265 -0
  7. package/dist/camera/index.mjs.map +1 -0
  8. package/dist/core/index.d.ts +102 -0
  9. package/dist/core/index.js +455 -0
  10. package/dist/core/index.js.map +1 -0
  11. package/dist/core/index.mjs +432 -0
  12. package/dist/core/index.mjs.map +1 -0
  13. package/dist/effect/index.d.ts +214 -0
  14. package/dist/effect/index.js +749 -0
  15. package/dist/effect/index.js.map +1 -0
  16. package/dist/effect/index.mjs +728 -0
  17. package/dist/effect/index.mjs.map +1 -0
  18. package/dist/index.d.ts +852 -0
  19. package/dist/index.js +3268 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/index.mjs +3223 -0
  22. package/dist/index.mjs.map +1 -0
  23. package/dist/interaction/index.d.ts +160 -0
  24. package/dist/interaction/index.js +661 -0
  25. package/dist/interaction/index.js.map +1 -0
  26. package/dist/interaction/index.mjs +637 -0
  27. package/dist/interaction/index.mjs.map +1 -0
  28. package/dist/loader/index.d.ts +175 -0
  29. package/dist/loader/index.js +786 -0
  30. package/dist/loader/index.js.map +1 -0
  31. package/dist/loader/index.mjs +758 -0
  32. package/dist/loader/index.mjs.map +1 -0
  33. package/dist/setup/index.d.ts +47 -0
  34. package/dist/setup/index.js +199 -0
  35. package/dist/setup/index.js.map +1 -0
  36. package/dist/setup/index.mjs +178 -0
  37. package/dist/setup/index.mjs.map +1 -0
  38. package/dist/ui/index.d.ts +36 -0
  39. package/dist/ui/index.js +292 -0
  40. package/dist/ui/index.js.map +1 -0
  41. package/dist/ui/index.mjs +271 -0
  42. package/dist/ui/index.mjs.map +1 -0
  43. package/package.json +98 -0
@@ -0,0 +1,265 @@
1
+ import * as THREE from 'three';
2
+
3
+ // src/utils/followModels.ts - 优化版
4
+ // ✨ 使用 WeakMap 跟踪动画,支持取消
5
+ const _animationMap = new WeakMap();
6
+ /**
7
+ * 推荐角度枚举,便于快速选取常见视角
8
+ */
9
+ const FOLLOW_ANGLES = {
10
+ /** 等距斜视(默认视角)- 适合建筑、机械设备展示 */
11
+ ISOMETRIC: { azimuth: Math.PI / 4, elevation: Math.PI / 4 },
12
+ /** 正前视角 - 适合正面展示、UI 对齐 */
13
+ FRONT: { azimuth: 0, elevation: 0 },
14
+ /** 右侧视角 - 适合机械剖面、侧视检查 */
15
+ RIGHT: { azimuth: Math.PI / 2, elevation: 0 },
16
+ /** 左侧视角 */
17
+ LEFT: { azimuth: -Math.PI / 2, elevation: 0 },
18
+ /** 后视角 */
19
+ BACK: { azimuth: Math.PI, elevation: 0 },
20
+ /** 顶视图 - 适合地图、平面布局展示 */
21
+ TOP: { azimuth: 0, elevation: Math.PI / 2 },
22
+ /** 低角度俯视 - 适合车辆、人物等近地物体 */
23
+ LOW_ANGLE: { azimuth: Math.PI / 4, elevation: Math.PI / 6 },
24
+ /** 高角度俯视 - 适合鸟瞰、全景浏览 */
25
+ HIGH_ANGLE: { azimuth: Math.PI / 4, elevation: Math.PI / 3 }
26
+ };
27
+ /**
28
+ * 缓动函数集合
29
+ */
30
+ const EASING_FUNCTIONS = {
31
+ linear: (t) => t,
32
+ easeInOut: (t) => t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2,
33
+ easeOut: (t) => 1 - Math.pow(1 - t, 3),
34
+ easeIn: (t) => t * t * t
35
+ };
36
+ /**
37
+ * 自动将相机移到目标的斜上角位置,并保证目标在可视范围内(平滑过渡)- 优化版
38
+ *
39
+ * ✨ 优化内容:
40
+ * - 支持多种缓动函数
41
+ * - 添加进度回调
42
+ * - 支持取消动画
43
+ * - WeakMap 跟踪防止泄漏
44
+ * - 完善错误处理
45
+ */
46
+ function followModels(camera, targets, options = {}) {
47
+ var _a, _b, _c, _d, _e, _f;
48
+ // ✨ 取消之前的动画
49
+ cancelFollow(camera);
50
+ // ✨ 边界检查
51
+ const arr = [];
52
+ if (!targets)
53
+ return Promise.resolve();
54
+ if (Array.isArray(targets))
55
+ arr.push(...targets.filter(Boolean));
56
+ else
57
+ arr.push(targets);
58
+ if (arr.length === 0) {
59
+ console.warn('followModels: 目标对象为空');
60
+ return Promise.resolve();
61
+ }
62
+ try {
63
+ const box = new THREE.Box3();
64
+ arr.forEach((o) => box.expandByObject(o));
65
+ // ✨ 检查包围盒有效性
66
+ if (!isFinite(box.min.x) || !isFinite(box.max.x)) {
67
+ console.warn('followModels: 包围盒计算失败');
68
+ return Promise.resolve();
69
+ }
70
+ const sphere = new THREE.Sphere();
71
+ box.getBoundingSphere(sphere);
72
+ const center = sphere.center.clone();
73
+ const radiusBase = Math.max(0.001, sphere.radius);
74
+ const duration = (_a = options.duration) !== null && _a !== void 0 ? _a : 700;
75
+ const padding = (_b = options.padding) !== null && _b !== void 0 ? _b : 1.0;
76
+ const minDistance = options.minDistance;
77
+ const maxDistance = options.maxDistance;
78
+ const controls = (_c = options.controls) !== null && _c !== void 0 ? _c : null;
79
+ const azimuth = (_d = options.azimuth) !== null && _d !== void 0 ? _d : Math.PI / 4;
80
+ const elevation = (_e = options.elevation) !== null && _e !== void 0 ? _e : Math.PI / 4;
81
+ const easing = (_f = options.easing) !== null && _f !== void 0 ? _f : 'easeOut';
82
+ const onProgress = options.onProgress;
83
+ // ✨ 获取缓动函数
84
+ const easingFn = EASING_FUNCTIONS[easing] || EASING_FUNCTIONS.easeOut;
85
+ let distance = 10;
86
+ if (camera.isPerspectiveCamera) {
87
+ const cam = camera;
88
+ const halfV = THREE.MathUtils.degToRad(cam.fov * 0.5);
89
+ const halfH = Math.atan(Math.tan(halfV) * cam.aspect);
90
+ const halfMin = Math.min(halfV, halfH);
91
+ distance = (radiusBase * padding) / Math.sin(halfMin);
92
+ if (minDistance != null)
93
+ distance = Math.max(distance, minDistance);
94
+ if (maxDistance != null)
95
+ distance = Math.min(distance, maxDistance);
96
+ }
97
+ else if (camera.isOrthographicCamera) {
98
+ distance = camera.position.distanceTo(center);
99
+ }
100
+ else {
101
+ distance = camera.position.distanceTo(center);
102
+ }
103
+ // 根据 azimuth / elevation 计算方向
104
+ const hx = Math.sin(azimuth);
105
+ const hz = Math.cos(azimuth);
106
+ const dir = new THREE.Vector3(hx * Math.cos(elevation), Math.sin(elevation), hz * Math.cos(elevation)).normalize();
107
+ const desiredPos = center.clone().add(dir.multiplyScalar(distance));
108
+ const startPos = camera.position.clone();
109
+ const startTarget = controls && controls.target
110
+ ? controls.target.clone()
111
+ : camera.position.clone().add(camera.getWorldDirection(new THREE.Vector3()).multiplyScalar(1));
112
+ const endTarget = center.clone();
113
+ const startTime = performance.now();
114
+ return new Promise((resolve) => {
115
+ const step = (now) => {
116
+ var _a;
117
+ const elapsed = now - startTime;
118
+ const t = Math.min(1, duration > 0 ? elapsed / duration : 1);
119
+ const k = easingFn(t);
120
+ camera.position.lerpVectors(startPos, desiredPos, k);
121
+ if (controls && controls.target) {
122
+ const newTarget = new THREE.Vector3().lerpVectors(startTarget, endTarget, k);
123
+ controls.target.copy(newTarget);
124
+ if (typeof controls.update === 'function')
125
+ controls.update();
126
+ }
127
+ else {
128
+ camera.lookAt(endTarget);
129
+ }
130
+ (_a = camera.updateProjectionMatrix) === null || _a === void 0 ? void 0 : _a.call(camera);
131
+ // ✨ 调用进度回调
132
+ if (onProgress) {
133
+ try {
134
+ onProgress(t);
135
+ }
136
+ catch (error) {
137
+ console.error('followModels: 进度回调错误', error);
138
+ }
139
+ }
140
+ if (t < 1) {
141
+ const rafId = requestAnimationFrame(step);
142
+ _animationMap.set(camera, rafId);
143
+ }
144
+ else {
145
+ _animationMap.delete(camera);
146
+ camera.position.copy(desiredPos);
147
+ if (controls && controls.target) {
148
+ controls.target.copy(endTarget);
149
+ if (typeof controls.update === 'function')
150
+ controls.update();
151
+ }
152
+ else {
153
+ camera.lookAt(endTarget);
154
+ }
155
+ resolve();
156
+ }
157
+ };
158
+ const rafId = requestAnimationFrame(step);
159
+ _animationMap.set(camera, rafId);
160
+ });
161
+ }
162
+ catch (error) {
163
+ console.error('followModels: 执行失败', error);
164
+ return Promise.reject(error);
165
+ }
166
+ }
167
+ /**
168
+ * ✨ 取消相机的跟随动画
169
+ */
170
+ function cancelFollow(camera) {
171
+ const rafId = _animationMap.get(camera);
172
+ if (rafId !== undefined) {
173
+ cancelAnimationFrame(rafId);
174
+ _animationMap.delete(camera);
175
+ }
176
+ }
177
+
178
+ // src/utils/setView.ts - 优化版
179
+ /**
180
+ * 平滑切换相机到模型的最佳视角 - 优化版
181
+ *
182
+ * ✨ 优化内容:
183
+ * - 复用 followModels 逻辑,避免代码重复
184
+ * - 支持更多视角
185
+ * - 配置选项增强
186
+ * - 返回 Promise 支持链式调用
187
+ * - 支持取消动画
188
+ *
189
+ * @param camera THREE.PerspectiveCamera 相机实例
190
+ * @param controls OrbitControls 控制器实例
191
+ * @param targetObj THREE.Object3D 模型对象
192
+ * @param position 视角位置
193
+ * @param options 配置选项
194
+ * @returns Promise<void>
195
+ */
196
+ function setView(camera, controls, targetObj, position = 'front', options = {}) {
197
+ const { distanceFactor = 0.8, duration = 1000, easing = 'easeInOut', onProgress } = options;
198
+ // ✨ 边界检查
199
+ if (!targetObj) {
200
+ console.warn('setView: 目标对象为空');
201
+ return Promise.reject(new Error('Target object is required'));
202
+ }
203
+ try {
204
+ // 计算包围盒
205
+ const box = new THREE.Box3().setFromObject(targetObj);
206
+ if (!isFinite(box.min.x)) {
207
+ console.warn('setView: 包围盒计算失败');
208
+ return Promise.reject(new Error('Invalid bounding box'));
209
+ }
210
+ const center = box.getCenter(new THREE.Vector3());
211
+ const size = box.getSize(new THREE.Vector3());
212
+ const maxSize = Math.max(size.x, size.y, size.z);
213
+ // ✨ 使用映射表简化视角计算
214
+ const viewAngles = {
215
+ 'front': { azimuth: 0, elevation: 0 },
216
+ 'back': { azimuth: Math.PI, elevation: 0 },
217
+ 'left': { azimuth: -Math.PI / 2, elevation: 0 },
218
+ 'right': { azimuth: Math.PI / 2, elevation: 0 },
219
+ 'top': { azimuth: 0, elevation: Math.PI / 2 },
220
+ 'bottom': { azimuth: 0, elevation: -Math.PI / 2 },
221
+ 'iso': { azimuth: Math.PI / 4, elevation: Math.PI / 4 }
222
+ };
223
+ const angle = viewAngles[position] || viewAngles.front;
224
+ // ✨ 复用 followModels,避免代码重复
225
+ return followModels(camera, targetObj, {
226
+ duration,
227
+ padding: distanceFactor,
228
+ controls,
229
+ azimuth: angle.azimuth,
230
+ elevation: angle.elevation,
231
+ easing,
232
+ onProgress
233
+ });
234
+ }
235
+ catch (error) {
236
+ console.error('setView: 执行失败', error);
237
+ return Promise.reject(error);
238
+ }
239
+ }
240
+ /**
241
+ * ✨ 取消视角切换动画
242
+ */
243
+ function cancelSetView(camera) {
244
+ cancelFollow(camera);
245
+ }
246
+ /**
247
+ * ✨ 预设视角快捷方法
248
+ */
249
+ const ViewPresets = {
250
+ /**
251
+ * 前视图
252
+ */
253
+ front: (camera, controls, target, options) => setView(camera, controls, target, 'front', options),
254
+ /**
255
+ * 等距视图
256
+ */
257
+ isometric: (camera, controls, target, options) => setView(camera, controls, target, 'iso', options),
258
+ /**
259
+ * 顶视图
260
+ */
261
+ top: (camera, controls, target, options) => setView(camera, controls, target, 'top', options)
262
+ };
263
+
264
+ export { FOLLOW_ANGLES, ViewPresets, cancelFollow, cancelSetView, followModels, setView };
265
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../../src/camera/followModels.ts","../../src/camera/setView.ts"],"sourcesContent":[null,null],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ import * as THREE from 'three';
2
+ import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass';
3
+ import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer';
4
+
5
+ interface LabelOptions {
6
+ fontSize?: string;
7
+ color?: string;
8
+ background?: string;
9
+ padding?: string;
10
+ borderRadius?: string;
11
+ updateInterval?: number;
12
+ enableCache?: boolean;
13
+ }
14
+ interface LabelManager {
15
+ pause: () => void;
16
+ resume: () => void;
17
+ dispose: () => void;
18
+ isRunning: () => boolean;
19
+ }
20
+ /**
21
+ * 给子模型添加头顶标签(支持 Mesh 和 Group)- 优化版
22
+ *
23
+ * ✨ 性能优化:
24
+ * - 缓存包围盒,避免每帧重复计算
25
+ * - 支持暂停/恢复更新
26
+ * - 可配置更新间隔,降低 CPU 占用
27
+ * - 只在可见时更新,隐藏时自动暂停
28
+ *
29
+ * @param camera THREE.Camera - 场景摄像机
30
+ * @param renderer THREE.WebGLRenderer - 渲染器,用于屏幕尺寸
31
+ * @param parentModel THREE.Object3D - FBX 根节点或 Group
32
+ * @param modelLabelsMap Record<string,string> - 模型 name → 标签文字 映射表
33
+ * @param options LabelOptions - 可选标签样式配置
34
+ * @returns LabelManager - 包含 pause/resume/dispose 的管理接口
35
+ */
36
+ declare function addChildModelLabels(camera: THREE.Camera, renderer: THREE.WebGLRenderer, parentModel: THREE.Object3D, modelLabelsMap: Record<string, string>, options?: LabelOptions): LabelManager;
37
+
38
+ type HoverBreathOptions = {
39
+ camera: THREE.Camera;
40
+ scene: THREE.Scene;
41
+ renderer: THREE.WebGLRenderer;
42
+ outlinePass: OutlinePass;
43
+ highlightNames?: string[] | null;
44
+ minStrength?: number;
45
+ maxStrength?: number;
46
+ speed?: number;
47
+ throttleDelay?: number;
48
+ };
49
+ /**
50
+ * 创建单例高亮器 —— 推荐在 mounted 时创建一次
51
+ * 返回 { updateHighlightNames, dispose, getHoveredName } 接口
52
+ *
53
+ * ✨ 性能优化:
54
+ * - 无 hover 对象时自动暂停动画
55
+ * - mousemove 节流处理,避免过度计算
56
+ * - 使用 passive 事件监听器提升滚动性能
57
+ */
58
+ declare function enableHoverBreath(opts: HoverBreathOptions): {
59
+ updateHighlightNames: (names: string[] | null) => void;
60
+ dispose: () => void;
61
+ refreshSelection: () => void;
62
+ getHoveredName: () => string | null;
63
+ };
64
+
65
+ /**
66
+ * 后期处理配置选项
67
+ */
68
+ interface PostProcessingOptions {
69
+ edgeStrength?: number;
70
+ edgeGlow?: number;
71
+ edgeThickness?: number;
72
+ visibleEdgeColor?: string;
73
+ hiddenEdgeColor?: string;
74
+ resolutionScale?: number;
75
+ }
76
+ /**
77
+ * 后期处理管理接口
78
+ */
79
+ interface PostProcessingManager {
80
+ composer: EffectComposer;
81
+ outlinePass: OutlinePass;
82
+ resize: (width?: number, height?: number) => void;
83
+ dispose: () => void;
84
+ }
85
+ /**
86
+ * 初始化描边相关信息(包含 OutlinePass)- 优化版
87
+ *
88
+ * ✨ 功能增强:
89
+ * - 支持窗口 resize 自动更新
90
+ * - 可配置分辨率缩放提升性能
91
+ * - 完善的资源释放管理
92
+ *
93
+ * @param renderer THREE.WebGLRenderer
94
+ * @param scene THREE.Scene
95
+ * @param camera THREE.Camera
96
+ * @param options PostProcessingOptions - 可选配置
97
+ * @returns PostProcessingManager - 包含 composer/outlinePass/resize/dispose 的管理接口
98
+ */
99
+ declare function initPostProcessing(renderer: THREE.WebGLRenderer, scene: THREE.Scene, camera: THREE.Camera, options?: PostProcessingOptions): PostProcessingManager;
100
+
101
+ export { addChildModelLabels, enableHoverBreath, initPostProcessing };
102
+ export type { HoverBreathOptions, PostProcessingManager, PostProcessingOptions };