@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.
- package/LICENSE +21 -0
- package/README.md +609 -0
- package/dist/camera/index.d.ts +133 -0
- package/dist/camera/index.js +291 -0
- package/dist/camera/index.js.map +1 -0
- package/dist/camera/index.mjs +265 -0
- package/dist/camera/index.mjs.map +1 -0
- package/dist/core/index.d.ts +102 -0
- package/dist/core/index.js +455 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/index.mjs +432 -0
- package/dist/core/index.mjs.map +1 -0
- package/dist/effect/index.d.ts +214 -0
- package/dist/effect/index.js +749 -0
- package/dist/effect/index.js.map +1 -0
- package/dist/effect/index.mjs +728 -0
- package/dist/effect/index.mjs.map +1 -0
- package/dist/index.d.ts +852 -0
- package/dist/index.js +3268 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3223 -0
- package/dist/index.mjs.map +1 -0
- package/dist/interaction/index.d.ts +160 -0
- package/dist/interaction/index.js +661 -0
- package/dist/interaction/index.js.map +1 -0
- package/dist/interaction/index.mjs +637 -0
- package/dist/interaction/index.mjs.map +1 -0
- package/dist/loader/index.d.ts +175 -0
- package/dist/loader/index.js +786 -0
- package/dist/loader/index.js.map +1 -0
- package/dist/loader/index.mjs +758 -0
- package/dist/loader/index.mjs.map +1 -0
- package/dist/setup/index.d.ts +47 -0
- package/dist/setup/index.js +199 -0
- package/dist/setup/index.js.map +1 -0
- package/dist/setup/index.mjs +178 -0
- package/dist/setup/index.mjs.map +1 -0
- package/dist/ui/index.d.ts +36 -0
- package/dist/ui/index.js +292 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/index.mjs +271 -0
- package/dist/ui/index.mjs.map +1 -0
- 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 };
|