@ridp/threejs 1.5.0 → 1.5.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/README.md +104 -5
- package/dist/threejs.cjs +2 -2
- package/dist/threejs.js +212 -169
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -180,12 +180,12 @@ new ThreeIns(selector: string, options: ThreeInsOptions)
|
|
|
180
180
|
|
|
181
181
|
##### setView()
|
|
182
182
|
|
|
183
|
-
设置模型视角 -
|
|
183
|
+
设置模型视角 - 通过移动相机位置来实现视角切换。支持预设视角类型和自定义方向向量。
|
|
184
184
|
|
|
185
185
|
```javascript
|
|
186
186
|
threeJsIns.setView(
|
|
187
187
|
model: Object3D,
|
|
188
|
-
viewType: ViewType,
|
|
188
|
+
viewType: ViewType | Vector3, // 视角类型:可以是预设枚举或自定义 Vector3 方向
|
|
189
189
|
options?: {
|
|
190
190
|
scale?: number, // 缩放比例,1=占满画布,0.5=50%,2.0=200%(默认: 0.8)
|
|
191
191
|
position?: string | Vector3, // 模型在画布中的位置
|
|
@@ -198,17 +198,26 @@ threeJsIns.setView(
|
|
|
198
198
|
): void
|
|
199
199
|
```
|
|
200
200
|
|
|
201
|
-
|
|
201
|
+
**视角类型:**
|
|
202
|
+
|
|
203
|
+
**方式 1: 使用 ViewType 枚举(预设视角)**
|
|
202
204
|
- `ViewType.TOP` - 俯视(从上往下)
|
|
203
205
|
- `ViewType.RIGHT` - 右视图(从右往左)
|
|
204
206
|
- `ViewType.LEFT` - 左侧视(从左往右)
|
|
205
207
|
- `ViewType.ISO` - 等轴测视角(对角线上方俯视)
|
|
206
208
|
|
|
209
|
+
**方式 2: 使用自定义 Vector3 方向向量**
|
|
210
|
+
- 任意方向向量,如 `Vector3(1, 1, 1)`、`Vector3(2, 0, 1)`
|
|
211
|
+
- 向量会被自动归一化,实现相对模型中心的任意角度查看
|
|
212
|
+
- 支持负值和零值,如 `Vector3(0, -1, 1)` (仰视)、`Vector3(0, 0, 1)` (平视)
|
|
213
|
+
|
|
207
214
|
**position 参数选项:**
|
|
208
215
|
- 字符串选项:`'center'`(居中)、`'top-left'`(左上)、`'top-right'`(右上)、`'bottom-left'`(左下)、`'bottom-right'`(右下)
|
|
209
216
|
- Vector3:自定义偏移向量
|
|
210
217
|
|
|
211
218
|
**示例:**
|
|
219
|
+
|
|
220
|
+
**使用预设 ViewType:**
|
|
212
221
|
```javascript
|
|
213
222
|
// 基础用法 - 设置等轴测视角,模型占满画布
|
|
214
223
|
threeJsIns.setView(model, ViewType.ISO, {
|
|
@@ -238,6 +247,46 @@ threeJsIns.setView(model, ViewType.TOP, {
|
|
|
238
247
|
});
|
|
239
248
|
```
|
|
240
249
|
|
|
250
|
+
**使用自定义 Vector3 方向:**
|
|
251
|
+
```javascript
|
|
252
|
+
// 从对角线方向查看模型(类似等轴测)
|
|
253
|
+
threeJsIns.setView(model, new THREE.Vector3(1, 1, 1));
|
|
254
|
+
|
|
255
|
+
// 从右前方查看模型
|
|
256
|
+
threeJsIns.setView(model, new THREE.Vector3(2, 1, 1));
|
|
257
|
+
|
|
258
|
+
// 从左侧平视模型
|
|
259
|
+
threeJsIns.setView(model, new THREE.Vector3(0, 0, 1));
|
|
260
|
+
|
|
261
|
+
// 从下方仰视模型
|
|
262
|
+
threeJsIns.setView(model, new THREE.Vector3(0, -1, 1));
|
|
263
|
+
|
|
264
|
+
// 自定义方向 + 其他选项
|
|
265
|
+
threeJsIns.setView(model, new THREE.Vector3(1, 2, 1), {
|
|
266
|
+
scale: 0.6,
|
|
267
|
+
position: 'center',
|
|
268
|
+
showBox: true,
|
|
269
|
+
animate: true,
|
|
270
|
+
duration: 1500
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
// 从左前方查看(负值 X)
|
|
274
|
+
threeJsIns.setView(model, new THREE.Vector3(-2, 1, 1));
|
|
275
|
+
|
|
276
|
+
// 从反方向对角线查看
|
|
277
|
+
threeJsIns.setView(model, new THREE.Vector3(-1, 1, 1));
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
**两种方式对比:**
|
|
281
|
+
|
|
282
|
+
| 特性 | ViewType 枚举 | Vector3 自定义方向 |
|
|
283
|
+
|------|--------------|-------------------|
|
|
284
|
+
| 易用性 | ⭐⭐⭐⭐⭐ 简单直观 | ⭐⭐⭐ 需要理解 3D 向量 |
|
|
285
|
+
| 灵活性 | ⭐⭐⭐ 固定 4 种视角 | ⭐⭐⭐⭐⭐ 无限可能 |
|
|
286
|
+
| 适用场景 | 常用标准视角 | 特殊角度查看 |
|
|
287
|
+
| 向量归一化 | 自动处理 | 自动归一化 |
|
|
288
|
+
| 组合使用 | ✅ 支持 | ✅ 支持 |
|
|
289
|
+
|
|
241
290
|
##### setViewByRotation()
|
|
242
291
|
|
|
243
292
|
通过旋转物体切换视角 - 保持相机固定,通过旋转物体来实现视角切换。
|
|
@@ -1612,6 +1661,27 @@ function captureScreenshot() {
|
|
|
1612
1661
|
|
|
1613
1662
|
**🎉 重大更新:**
|
|
1614
1663
|
|
|
1664
|
+
- ✨ **增强 setView() 方法 - 支持自定义 Vector3 方向**:
|
|
1665
|
+
- **新增自定义方向支持**: 除了预设的 ViewType 枚举,现在可以直接传入 Vector3 方向向量
|
|
1666
|
+
- **无限视角可能性**: 支持任意相机角度,如 `Vector3(1,1,1)`、`Vector3(2,0,1)` 等
|
|
1667
|
+
- **自动归一化**: 向量会被自动归一化,确保相机距离计算准确
|
|
1668
|
+
- **完整兼容性**: 向后兼容 ViewType 枚举,同时支持新的 Vector3 参数
|
|
1669
|
+
- **灵活组合**: 自定义方向可以与 scale、position、offset 等参数组合使用
|
|
1670
|
+
- 使用示例:
|
|
1671
|
+
```javascript
|
|
1672
|
+
// 从对角线方向查看
|
|
1673
|
+
threeJsIns.setView(model, new THREE.Vector3(1, 1, 1));
|
|
1674
|
+
|
|
1675
|
+
// 从右前方查看
|
|
1676
|
+
threeJsIns.setView(model, new THREE.Vector3(2, 1, 1));
|
|
1677
|
+
|
|
1678
|
+
// 从左侧平视
|
|
1679
|
+
threeJsIns.setView(model, new THREE.Vector3(0, 0, 1));
|
|
1680
|
+
|
|
1681
|
+
// 从下方仰视
|
|
1682
|
+
threeJsIns.setView(model, new THREE.Vector3(0, -1, 1));
|
|
1683
|
+
```
|
|
1684
|
+
|
|
1615
1685
|
- ✨ **新增 setViewByRotation() 方法**: 通过旋转物体切换视角
|
|
1616
1686
|
- 提供另一种视角切换方式(与 setView 互补)
|
|
1617
1687
|
- 左视图:物体绕 X 轴 45°,Y 轴旋转 45°
|
|
@@ -1632,6 +1702,7 @@ function captureScreenshot() {
|
|
|
1632
1702
|
- 新增 `validateAndRepair()` - IDBCache 实例方法
|
|
1633
1703
|
|
|
1634
1704
|
- 🔧 **增强 setView() 方法**:
|
|
1705
|
+
- **重大增强**: 支持 Vector3 自定义方向向量
|
|
1635
1706
|
- 新增 `position` 参数控制模型在画布中的位置
|
|
1636
1707
|
- 新增 `boxColor` 参数自定义包围盒颜色
|
|
1637
1708
|
- 优化视角偏移计算逻辑
|
|
@@ -1646,6 +1717,24 @@ function captureScreenshot() {
|
|
|
1646
1717
|
**API 变更:**
|
|
1647
1718
|
|
|
1648
1719
|
```javascript
|
|
1720
|
+
// ============ 新功能:自定义 Vector3 方向 ============
|
|
1721
|
+
// 从对角线方向查看模型
|
|
1722
|
+
threeJsIns.setView(model, new THREE.Vector3(1, 1, 1));
|
|
1723
|
+
|
|
1724
|
+
// 从右前方查看
|
|
1725
|
+
threeJsIns.setView(model, new THREE.Vector3(2, 1, 1), {
|
|
1726
|
+
scale: 0.8,
|
|
1727
|
+
position: 'center',
|
|
1728
|
+
animate: true
|
|
1729
|
+
});
|
|
1730
|
+
|
|
1731
|
+
// 从左侧平视
|
|
1732
|
+
threeJsIns.setView(model, new THREE.Vector3(0, 0, 1));
|
|
1733
|
+
|
|
1734
|
+
// 从下方仰视
|
|
1735
|
+
threeJsIns.setView(model, new THREE.Vector3(0, -1, 1));
|
|
1736
|
+
|
|
1737
|
+
// ============ 其他新功能 ============
|
|
1649
1738
|
// 新增 setViewByRotation
|
|
1650
1739
|
threeJsIns.setViewByRotation(model, ViewType.LEFT, {
|
|
1651
1740
|
animate: true,
|
|
@@ -1653,9 +1742,9 @@ threeJsIns.setViewByRotation(model, ViewType.LEFT, {
|
|
|
1653
1742
|
resetRotation: true
|
|
1654
1743
|
});
|
|
1655
1744
|
|
|
1656
|
-
// setView
|
|
1745
|
+
// setView position 参数
|
|
1657
1746
|
threeJsIns.setView(model, ViewType.ISO, {
|
|
1658
|
-
position: 'top-left', //
|
|
1747
|
+
position: 'top-left', // 位置控制
|
|
1659
1748
|
scale: 0.8,
|
|
1660
1749
|
offset: new THREE.Vector3(50, 0, 0)
|
|
1661
1750
|
});
|
|
@@ -1666,6 +1755,16 @@ await cleanLegacyCache(); // 清理旧版本缓存
|
|
|
1666
1755
|
await validateCache(); // 验证和修复缓存
|
|
1667
1756
|
```
|
|
1668
1757
|
|
|
1758
|
+
**Breaking Changes:**
|
|
1759
|
+
|
|
1760
|
+
无破坏性变更,所有新功能都是向后兼容的增强。
|
|
1761
|
+
|
|
1762
|
+
**升级指南:**
|
|
1763
|
+
|
|
1764
|
+
- 如果使用预设视角(ViewType),无需修改任何代码
|
|
1765
|
+
- 如果需要自定义视角,可以直接传入 Vector3 对象替代 ViewType
|
|
1766
|
+
- 建议查看新示例代码了解更多用法
|
|
1767
|
+
|
|
1669
1768
|
**迁移说明:**
|
|
1670
1769
|
|
|
1671
1770
|
- 数据库会自动从 v4 升级到 v5
|
package/dist/threejs.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var A=Object.defineProperty;var q=(p,t,e)=>t in p?A(p,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):p[t]=e;var r=(p,t,e)=>q(p,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const F=require("./useBatchGLTFLoader-DHJyQcpJ.cjs"),a=require("./PredictiveLoader-Xy5S4HBr.cjs"),g=require("./objectQuery-DNtwsgY8.cjs"),S=require("./modelOptimizer-A0Cs6f9e.cjs"),n=require("three"),B="1.5.0",X=50,Y=20,Z=20,E={TOP:"top",RIGHT:"right",LEFT:"left",ISO:"iso"},G={enableDamping:!0,dampingFactor:.25,screenSpacePanning:!1,minDistance:.1,maxDistance:1e3,maxPolarAngle:n.MathUtils.degToRad(60)};class v{constructor(t,e){r(this,"isReady",!1);r(this,"scene",null);r(this,"camera",null);r(this,"renderer",null);r(this,"control",null);r(this,"css3dRenderer",null);r(this,"el",null);r(this,"renderRequested",!1);r(this,"selector",null);r(this,"eventsListener",{});r(this,"stats",null);r(this,"isDispose",!1);r(this,"version","0.0.0");r(this,"boxHelper",null);r(this,"initOpt",{css3d:!1,stats:!1,renderType:"change",initListener:!0,initialFov:50,control:{init:!0,options:{}}});r(this,"setup",t=>{if(this.isDispose=!1,this.selector=t,this.el=document.querySelector(t),!this.el){console.error(`ThreeIns: 找不到元素 ${t}`);return}const[e,m]=this.getTargetSize();if(this.updateCameraFOV(e,m),this.camera.position.set(0,0,0),this.camera.lookAt(0,0,0),this.camera.updateProjectionMatrix(),this.renderer.setPixelRatio(window.devicePixelRatio),this.renderer.setSize(e,m),this.el.appendChild(this.renderer.domElement),this.initOpt.control&&this.initOpt.control.init){this.control=a.createOrbitControl(this.camera,this.renderer.domElement);const o=Object.assign(G,this.initOpt.control.options||{});Object.keys(o).forEach(M=>{this.control[M]=o[M]})}setTimeout(()=>{this.isReady=!0},Y),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("change",this.requestRenderIfNotRequested),this.initListener()});r(this,"onContextLost",t=>{t.preventDefault(),this.animationFrameId&&cancelAnimationFrame(this.animationFrameId)});r(this,"onContextRestored",t=>{t.preventDefault(),this.dispose(),setTimeout(()=>{this.setup(this.selector)},Z)});r(this,"initListener",()=>{this.initOpt.initListener&&window&&window.addEventListener("resize",this.onResize,!1),this.renderer.domElement.addEventListener("webglcontextlost",this.onContextLost,!1),this.renderer.domElement.addEventListener("webglcontextrestored",this.onContextRestored,!1)});r(this,"removeListener",()=>{window&&window.removeEventListener("resize",this.onResize,!1),this.renderer&&this.renderer.domElement&&(this.renderer.domElement.removeEventListener("webglcontextlost",this.onContextLost,!1),this.renderer.domElement.removeEventListener("webglcontextrestored",this.onContextRestored,!1))});r(this,"animate",()=>{this.isDispose||(this.initOpt.renderType==="loop"&&this.onRender(),this.animationFrameId=requestAnimationFrame(this.animate))});r(this,"onRender",()=>{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(t=>t()))});r(this,"requestRenderIfNotRequested",()=>{this.renderRequested||(this.renderRequested=!0,requestAnimationFrame(()=>{this.onRender()}))});r(this,"onResize",()=>{this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=setTimeout(()=>{const[t,e]=this.getTargetSize();this.updateCameraFOV(t,e),this.camera.lookAt(this.scene.position),this.renderer.setSize(t,e),this.css3dRenderer&&this.css3dRenderer.setSize(t,e),this.onRender()},X)});r(this,"frameArea",(t,e)=>(console.warn(`[ThreeIns] frameArea() 已弃用,建议使用 setView() 方法。
|
|
2
2
|
旧用法: threeIns.frameArea(model, scale)
|
|
3
|
-
新用法: threeIns.setView(model, ViewType.ISO, { scale })`),this.setView(e,L.ISO,{scale:t,animate:!1,showBox:!1})));i(this,"setView",(e,t,h={})=>{let s=h.scale||.8,R=h.offset||null,T=h.position||"center",M=h.showBox||!1,I=h.boxColor||16776960,E=h.animate!==void 0?h.animate:!0,w=h.duration||1e3;const b=new a.Box3().setFromObject(e);let d=b.getCenter(new a.Vector3);if(typeof T=="string"){const o=b.getSize(new a.Vector3),l={center:new a.Vector3(0,0,0),"top-left":new a.Vector3(-o.x*.3,o.y*.3,o.z*.3),"top-right":new a.Vector3(o.x*.3,o.y*.3,o.z*.3),"bottom-left":new a.Vector3(-o.x*.3,-o.y*.3,o.z*.3),"bottom-right":new a.Vector3(o.x*.3,-o.y*.3,o.z*.3)},m=l[T]||l.center;t==="top"?d.add(new a.Vector3(m.x,0,m.z)):t==="right"||t==="left"?d.add(new a.Vector3(m.x,m.y,m.z)):d.add(m)}else T instanceof a.Vector3&&d.add(T);R&&d.add(R);const r=b.getSize(new a.Vector3),y={top:new a.Vector3(0,1,0),right:new a.Vector3(1,1,1).normalize(),left:new a.Vector3(-1,1,1).normalize(),iso:new a.Vector3(0,1,1).normalize()},O=y[t]||y.iso,C=this.camera.aspect,c=a.MathUtils.degToRad(this.camera.fov*.5),j=a.MathUtils.degToRad(80),u=Math.min(Math.atan(Math.tan(c)*C),j);let p;if(t==="top"){const o=r.x*.5/(Math.tan(u)*s),l=r.z*.5/(Math.tan(c)*s);p=Math.max(o,l)}else if(t==="right"||t==="left"){const o=r.y*.5/(Math.tan(c)*s),l=r.z*.5/(Math.tan(c)*s);p=Math.max(o,l)}else{const o=r.x*.5/(Math.tan(u)*s),l=r.y*.5/(Math.tan(c)*s),m=r.z*.5/(Math.tan(c)*s);p=Math.max(o,l,m)}const f=O.clone().multiplyScalar(p).add(d);if(M&&(console.log("📍 相机位置验证:"),console.log(" - 方向向量:",O),console.log(" - 距离:",p.toFixed(2)),console.log(" - 包围盒中心:",d),console.log(" - 计算公式: direction * distance + boxCenter"),console.log(" - 目标位置:",f),console.log(" - 实际相机与中心的距离:",f.clone().sub(d).length().toFixed(2))),M?(this.boxHelper&&(this.scene.remove(this.boxHelper),this.boxHelper=null),this.boxHelper=new a.Box3Helper(b,I),this.scene.add(this.boxHelper)):this.boxHelper&&(this.scene.remove(this.boxHelper),this.boxHelper=null),E){const o=this.camera.position.clone(),l=this.control?this.control.target.clone():new a.Vector3(0,0,0),m=d,P=Date.now(),v=()=>{const A=Date.now()-P,D=Math.min(A/w,1),S=1-Math.pow(1-D,3);if(this.camera.position.lerpVectors(o,f,S),this.control){const z=new a.Vector3;z.lerpVectors(l,m,S),this.control.target.copy(z),this.camera.lookAt(z)}else this.camera.lookAt(d);this.camera.updateProjectionMatrix(),D<1?requestAnimationFrame(v):(this.camera.position.copy(f),this.camera.lookAt(d),this.camera.updateProjectionMatrix(),this.control&&(this.control.target.copy(d),this.control.update()),this.onRender())};v()}else this.camera.position.copy(f),this.camera.lookAt(d),this.camera.updateProjectionMatrix(),this.control&&(this.control.target.copy(d),this.control.update()),this.onRender();if(M){if(console.log("🎥 视角切换信息:"),console.log(" - 视角类型:",t),console.log(" - 相机位置:",f),console.log(" - 观察目标:",d),console.log(" - 方向向量:",O),console.log(" - 包围盒尺寸:",r),console.log(" - 包围盒中心:",b.getCenter(new a.Vector3)),console.log(" - 水平 FOV:",a.MathUtils.radToDeg(u*2).toFixed(2)+"°"),console.log(" - 垂直 FOV:",a.MathUtils.radToDeg(c*2).toFixed(2)+"°"),console.log(" - 宽高比:",C.toFixed(4)),console.log(" - 模型宽度:",r.x.toFixed(2)),console.log(" - 模型高度:",r.y.toFixed(2)),console.log(" - 模型深度:",r.z.toFixed(2)),console.log(" - 传入的 scale 参数:",s),t==="top"){const o=r.x*.5/(Math.tan(u)*s),l=r.z*.5/(Math.tan(c)*s);console.log(" - 模型 X 尺寸 (宽度):",r.x.toFixed(2)),console.log(" - 模型 Z 尺寸 (深度):",r.z.toFixed(2)),console.log(" - tan(halfFovX):",Math.tan(u).toFixed(4)),console.log(" - tan(halfFovY):",Math.tan(c).toFixed(4)),console.log(" - X方向距离计算: (",(r.x*.5).toFixed(2),") / (",Math.tan(u).toFixed(4)," *",s,") =",o.toFixed(2)),console.log(" - Z方向距离计算: (",(r.z*.5).toFixed(2),") / (",Math.tan(c).toFixed(4)," *",s,") =",l.toFixed(2)),console.log(" - X方向距离 (scale="+s+"):",o.toFixed(2)),console.log(" - Z方向距离 (scale="+s+"):",l.toFixed(2))}else if(t==="right"||t==="left"){const o=r.y*.5/(Math.tan(c)*s),l=r.z*.5/(Math.tan(c)*s);console.log(" - Y方向距离 (scale="+s+"):",o.toFixed(2)),console.log(" - Z方向距离 (scale="+s+"):",l.toFixed(2))}else{const o=r.x*.5/(Math.tan(u)*s),l=r.y*.5/(Math.tan(c)*s),m=r.z*.5/(Math.tan(c)*s);console.log(" - 模型 X 尺寸 (宽度):",r.x.toFixed(2)),console.log(" - 模型 Y 尺寸 (高度):",r.y.toFixed(2)),console.log(" - 模型 Z 尺寸 (深度):",r.z.toFixed(2)),console.log(" - tan(halfFovX):",Math.tan(u).toFixed(4)),console.log(" - tan(halfFovY):",Math.tan(c).toFixed(4)),console.log(" - X方向距离计算: (",(r.x*.5).toFixed(2),") / (",Math.tan(u).toFixed(4)," *",s,") =",o.toFixed(2)),console.log(" - Y方向距离计算: (",(r.y*.5).toFixed(2),") / (",Math.tan(c).toFixed(4)," *",s,") =",l.toFixed(2)),console.log(" - Z方向距离计算: (",(r.z*.5).toFixed(2),") / (",Math.tan(c).toFixed(4)," *",s,") =",m.toFixed(2)),console.log(" - X方向距离 (scale="+s+"):",o.toFixed(2)),console.log(" - Y方向距离 (scale="+s+"):",l.toFixed(2)),console.log(" - Z方向距离 (scale="+s+"):",m.toFixed(2)),console.log(" - 最大距离 (Max):",Math.max(o,l,m).toFixed(2))}console.log(" - 最终距离:",p.toFixed(2)),console.log(" - 缩放比例:",s),console.log(" - 动画:",E?"是 ("+w+"ms)":"否")}return{position:f,target:d,distance:p,viewType:t}});i(this,"on",(e,t)=>!e||!t||typeof t!="function"?(console.warn("ThreeIns.on: 无效的参数"),()=>{}):(this.eventsListener[e]||(this.eventsListener[e]=[]),this.eventsListener[e].push(t),()=>this.off(e,t)));this.isReady=!1,this.scene=new a.Scene({}),this.camera=new a.PerspectiveCamera(50,1,.1,2e3),this.renderer=new a.WebGLRenderer({antialias:!0,alpha:!0,precision:"mediump",logarithmicDepthBuffer:!0}),this.version=X,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)}updateCameraFOV(e,t){const h=this.initOpt.initialFov||50,s=Math.tan(Math.PI/180*h/2);this.camera.aspect=e/t,this.camera.fov=360/Math.PI*Math.atan(s*(t/e)),this.camera.updateProjectionMatrix()}initStats(){this.stats=new n.Stats,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)}initCss3dRenderer(){this.css3dRenderer=new n.CSS3DRenderer;const[e,t]=this.getTargetSize();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)}getTargetSize(){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]}off(e,t){if(!e){this.eventsListener={};return}this.eventsListener[e]&&(t?this.eventsListener[e]=this.eventsListener[e].filter(h=>h!==t):this.eventsListener[e]=[])}dispose(){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&&(n.disposeThreeObject(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: 资源已清理完成"))}}i(H,"ViewType",L);exports.intersectColor=F.intersectColor;exports.obbObjects=F.obbObjects;exports.useBatchGLTFLoader=F.useBatchGLTFLoader;exports.useObb=F.useObb;exports.useRaycaster=F.useRaycaster;exports.useThreeJs=F.useThreeJs;exports.CacheMonitor=n.CacheMonitor;exports.ErrorType=n.ErrorType;exports.IDBCache=n.IDBCache;exports.ModelLoadError=n.ModelLoadError;exports.PredictiveLoader=n.PredictiveLoader;exports.ProgressiveSceneBuilder=n.ProgressiveSceneBuilder;exports.RetryHelper=n.RetryHelper;exports.cacheMonitor=n.cacheMonitor;exports.createArrowHelper=n.createArrowHelper;exports.createAxesHelper=n.createAxesHelper;exports.createBox3Helper=n.createBox3Helper;exports.createCameraHelper=n.createCameraHelper;exports.createGridHelper=n.createGridHelper;exports.createMapControls=n.createMapControls;exports.createOrbitControl=n.createOrbitControl;exports.createRaycaster=n.createRaycaster;exports.createStats=n.createStats;exports.dataToObject3D=n.dataToObject3D;exports.dataToObject3DSync=n.dataToObject3DSync;exports.disposeThreeObject=n.disposeThreeObject;exports.object3DToData=n.object3DToData;exports.object3DToDataSync=n.object3DToDataSync;exports.predictiveLoader=n.predictiveLoader;exports.rebuildScene=n.rebuildScene;exports.useGLTFLoader=n.useGLTFLoader;exports.ImageLoader=g.ImageLoader;exports.createInfoPlane=g.createInfoPlane;exports.createTagPlane=g.createTagPlane;exports.getCommonParent=g.getCommonParent;exports.getObjectByUserData=g.getObjectByUserData;exports.getRootObj=g.getRootObj;exports.initEnvImage=g.initEnvImage;exports.ModelOptimizer=V.ModelOptimizer;exports.modelOptimizer=V.modelOptimizer;exports.ThreeIns=H;exports.ViewType=L;
|
|
3
|
+
新用法: threeIns.setView(model, ViewType.ISO, { scale })`),this.setView(t,E.ISO,{scale:e,animate:!1,showBox:!1})));r(this,"setView",(t,e,m={})=>{let o=m.scale||.8,M=m.offset||null,z=m.position||"center",O=m.showBox||!1,H=m.boxColor||16776960,T=m.animate!==void 0?m.animate:!0,y=m.duration||1e3;const R=new n.Box3().setFromObject(t);let h=R.getCenter(new n.Vector3);if(typeof z=="string"){const i=R.getSize(new n.Vector3),l={center:new n.Vector3(0,0,0),"top-left":new n.Vector3(-i.x*.3,i.y*.3,i.z*.3),"top-right":new n.Vector3(i.x*.3,i.y*.3,i.z*.3),"bottom-left":new n.Vector3(-i.x*.3,-i.y*.3,i.z*.3),"bottom-right":new n.Vector3(i.x*.3,-i.y*.3,i.z*.3)},d=l[z]||l.center;typeof e=="string"?e==="top"?h.add(new n.Vector3(d.x,0,d.z)):e==="right"||e==="left"?h.add(new n.Vector3(d.x,d.y,d.z)):h.add(d):h.add(d)}else z instanceof n.Vector3&&h.add(z);M&&h.add(M);const s=R.getSize(new n.Vector3);let b;if(e instanceof n.Vector3)b=e.clone().normalize();else{const i={top:new n.Vector3(0,1,0),right:new n.Vector3(1,1,1).normalize(),left:new n.Vector3(-1,1,1).normalize(),iso:new n.Vector3(0,1,1).normalize()};b=i[e]||i.iso}const C=this.camera.aspect,c=n.MathUtils.degToRad(this.camera.fov*.5),I=n.MathUtils.degToRad(80),x=Math.min(Math.atan(Math.tan(c)*C),I);let f;if(e instanceof n.Vector3){const i=s.x*.5/(Math.tan(x)*o),l=s.y*.5/(Math.tan(c)*o),d=s.z*.5/(Math.tan(c)*o);f=Math.max(i,l,d)}else if(e==="top"){const i=s.x*.5/(Math.tan(x)*o),l=s.z*.5/(Math.tan(c)*o);f=Math.max(i,l)}else if(e==="right"||e==="left"){const i=s.y*.5/(Math.tan(c)*o),l=s.z*.5/(Math.tan(c)*o);f=Math.max(i,l)}else{const i=s.x*.5/(Math.tan(x)*o),l=s.y*.5/(Math.tan(c)*o),d=s.z*.5/(Math.tan(c)*o);f=Math.max(i,l,d)}const u=b.clone().multiplyScalar(f).add(h);if(O&&(console.log("📍 相机位置验证:"),console.log(" - 方向向量:",b),console.log(" - 距离:",f.toFixed(2)),console.log(" - 包围盒中心:",h),console.log(" - 计算公式: direction * distance + boxCenter"),console.log(" - 目标位置:",u),console.log(" - 实际相机与中心的距离:",u.clone().sub(h).length().toFixed(2))),O?(this.boxHelper&&(this.scene.remove(this.boxHelper),this.boxHelper=null),this.boxHelper=new n.Box3Helper(R,H),this.scene.add(this.boxHelper)):this.boxHelper&&(this.scene.remove(this.boxHelper),this.boxHelper=null),T){const i=this.camera.position.clone(),l=this.control?this.control.target.clone():new n.Vector3(0,0,0),d=h,j=Date.now(),w=()=>{const P=Date.now()-j,D=Math.min(P/y,1),V=1-Math.pow(1-D,3);if(this.camera.position.lerpVectors(i,u,V),this.control){const L=new n.Vector3;L.lerpVectors(l,d,V),this.control.target.copy(L),this.camera.lookAt(L)}else this.camera.lookAt(h);this.camera.updateProjectionMatrix(),D<1?requestAnimationFrame(w):(this.camera.position.copy(u),this.camera.lookAt(h),this.camera.updateProjectionMatrix(),this.control&&(this.control.target.copy(h),this.control.update()),this.onRender())};w()}else this.camera.position.copy(u),this.camera.lookAt(h),this.camera.updateProjectionMatrix(),this.control&&(this.control.target.copy(h),this.control.update()),this.onRender();if(O){if(console.log("🎥 视角切换信息:"),console.log(" - 视角类型:",e instanceof n.Vector3?`自定义 Vector3(${e.x.toFixed(2)}, ${e.y.toFixed(2)}, ${e.z.toFixed(2)})`:e),console.log(" - 相机位置:",u),console.log(" - 观察目标:",h),console.log(" - 方向向量:",b),console.log(" - 包围盒尺寸:",s),console.log(" - 包围盒中心:",R.getCenter(new n.Vector3)),console.log(" - 水平 FOV:",n.MathUtils.radToDeg(x*2).toFixed(2)+"°"),console.log(" - 垂直 FOV:",n.MathUtils.radToDeg(c*2).toFixed(2)+"°"),console.log(" - 宽高比:",C.toFixed(4)),console.log(" - 模型宽度:",s.x.toFixed(2)),console.log(" - 模型高度:",s.y.toFixed(2)),console.log(" - 模型深度:",s.z.toFixed(2)),console.log(" - 传入的 scale 参数:",o),e instanceof n.Vector3){const i=s.x*.5/(Math.tan(x)*o),l=s.y*.5/(Math.tan(c)*o),d=s.z*.5/(Math.tan(c)*o);console.log(" - 模型 X 尺寸 (宽度):",s.x.toFixed(2)),console.log(" - 模型 Y 尺寸 (高度):",s.y.toFixed(2)),console.log(" - 模型 Z 尺寸 (深度):",s.z.toFixed(2)),console.log(" - tan(halfFovX):",Math.tan(x).toFixed(4)),console.log(" - tan(halfFovY):",Math.tan(c).toFixed(4)),console.log(" - X方向距离计算: (",(s.x*.5).toFixed(2),") / (",Math.tan(x).toFixed(4)," *",o,") =",i.toFixed(2)),console.log(" - Y方向距离计算: (",(s.y*.5).toFixed(2),") / (",Math.tan(c).toFixed(4)," *",o,") =",l.toFixed(2)),console.log(" - Z方向距离计算: (",(s.z*.5).toFixed(2),") / (",Math.tan(c).toFixed(4)," *",o,") =",d.toFixed(2)),console.log(" - X方向距离 (scale="+o+"):",i.toFixed(2)),console.log(" - Y方向距离 (scale="+o+"):",l.toFixed(2)),console.log(" - Z方向距离 (scale="+o+"):",d.toFixed(2)),console.log(" - 最大距离 (Max):",Math.max(i,l,d).toFixed(2))}else if(e==="top"){const i=s.x*.5/(Math.tan(x)*o),l=s.z*.5/(Math.tan(c)*o);console.log(" - 模型 X 尺寸 (宽度):",s.x.toFixed(2)),console.log(" - 模型 Z 尺寸 (深度):",s.z.toFixed(2)),console.log(" - tan(halfFovX):",Math.tan(x).toFixed(4)),console.log(" - tan(halfFovY):",Math.tan(c).toFixed(4)),console.log(" - X方向距离计算: (",(s.x*.5).toFixed(2),") / (",Math.tan(x).toFixed(4)," *",o,") =",i.toFixed(2)),console.log(" - Z方向距离计算: (",(s.z*.5).toFixed(2),") / (",Math.tan(c).toFixed(4)," *",o,") =",l.toFixed(2)),console.log(" - X方向距离 (scale="+o+"):",i.toFixed(2)),console.log(" - Z方向距离 (scale="+o+"):",l.toFixed(2))}else if(e==="right"||e==="left"){const i=s.y*.5/(Math.tan(c)*o),l=s.z*.5/(Math.tan(c)*o);console.log(" - Y方向距离 (scale="+o+"):",i.toFixed(2)),console.log(" - Z方向距离 (scale="+o+"):",l.toFixed(2))}else{const i=s.x*.5/(Math.tan(x)*o),l=s.y*.5/(Math.tan(c)*o),d=s.z*.5/(Math.tan(c)*o);console.log(" - 模型 X 尺寸 (宽度):",s.x.toFixed(2)),console.log(" - 模型 Y 尺寸 (高度):",s.y.toFixed(2)),console.log(" - 模型 Z 尺寸 (深度):",s.z.toFixed(2)),console.log(" - tan(halfFovX):",Math.tan(x).toFixed(4)),console.log(" - tan(halfFovY):",Math.tan(c).toFixed(4)),console.log(" - X方向距离计算: (",(s.x*.5).toFixed(2),") / (",Math.tan(x).toFixed(4)," *",o,") =",i.toFixed(2)),console.log(" - Y方向距离计算: (",(s.y*.5).toFixed(2),") / (",Math.tan(c).toFixed(4)," *",o,") =",l.toFixed(2)),console.log(" - Z方向距离计算: (",(s.z*.5).toFixed(2),") / (",Math.tan(c).toFixed(4)," *",o,") =",d.toFixed(2)),console.log(" - X方向距离 (scale="+o+"):",i.toFixed(2)),console.log(" - Y方向距离 (scale="+o+"):",l.toFixed(2)),console.log(" - Z方向距离 (scale="+o+"):",d.toFixed(2)),console.log(" - 最大距离 (Max):",Math.max(i,l,d).toFixed(2))}console.log(" - 最终距离:",f.toFixed(2)),console.log(" - 缩放比例:",o),console.log(" - 动画:",T?"是 ("+y+"ms)":"否")}return{position:u,target:h,distance:f,viewType:e}});r(this,"on",(t,e)=>!t||!e||typeof e!="function"?(console.warn("ThreeIns.on: 无效的参数"),()=>{}):(this.eventsListener[t]||(this.eventsListener[t]=[]),this.eventsListener[t].push(e),()=>this.off(t,e)));this.isReady=!1,this.scene=new n.Scene({}),this.camera=new n.PerspectiveCamera(50,1,.1,2e3),this.renderer=new n.WebGLRenderer({antialias:!0,alpha:!0,precision:"mediump",logarithmicDepthBuffer:!0}),this.version=B,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,e&&(this.initOpt=Object.assign(this.initOpt,e)),t&&this.setup(t)}updateCameraFOV(t,e){const m=this.initOpt.initialFov||50,o=Math.tan(Math.PI/180*m/2);this.camera.aspect=t/e,this.camera.fov=360/Math.PI*Math.atan(o*(e/t)),this.camera.updateProjectionMatrix()}initStats(){this.stats=new a.Stats,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)}initCss3dRenderer(){this.css3dRenderer=new a.CSS3DRenderer;const[t,e]=this.getTargetSize();this.css3dRenderer.setSize(t,e),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)}getTargetSize(){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]}off(t,e){if(!t){this.eventsListener={};return}this.eventsListener[t]&&(e?this.eventsListener[t]=this.eventsListener[t].filter(m=>m!==e):this.eventsListener[t]=[])}dispose(){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&&(a.disposeThreeObject(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: 资源已清理完成"))}}r(v,"ViewType",E);exports.intersectColor=F.intersectColor;exports.obbObjects=F.obbObjects;exports.useBatchGLTFLoader=F.useBatchGLTFLoader;exports.useObb=F.useObb;exports.useRaycaster=F.useRaycaster;exports.useThreeJs=F.useThreeJs;exports.CacheMonitor=a.CacheMonitor;exports.ErrorType=a.ErrorType;exports.IDBCache=a.IDBCache;exports.ModelLoadError=a.ModelLoadError;exports.PredictiveLoader=a.PredictiveLoader;exports.ProgressiveSceneBuilder=a.ProgressiveSceneBuilder;exports.RetryHelper=a.RetryHelper;exports.cacheMonitor=a.cacheMonitor;exports.createArrowHelper=a.createArrowHelper;exports.createAxesHelper=a.createAxesHelper;exports.createBox3Helper=a.createBox3Helper;exports.createCameraHelper=a.createCameraHelper;exports.createGridHelper=a.createGridHelper;exports.createMapControls=a.createMapControls;exports.createOrbitControl=a.createOrbitControl;exports.createRaycaster=a.createRaycaster;exports.createStats=a.createStats;exports.dataToObject3D=a.dataToObject3D;exports.dataToObject3DSync=a.dataToObject3DSync;exports.disposeThreeObject=a.disposeThreeObject;exports.object3DToData=a.object3DToData;exports.object3DToDataSync=a.object3DToDataSync;exports.predictiveLoader=a.predictiveLoader;exports.rebuildScene=a.rebuildScene;exports.useGLTFLoader=a.useGLTFLoader;exports.ImageLoader=g.ImageLoader;exports.createInfoPlane=g.createInfoPlane;exports.createTagPlane=g.createTagPlane;exports.getCommonParent=g.getCommonParent;exports.getObjectByUserData=g.getObjectByUserData;exports.getRootObj=g.getRootObj;exports.initEnvImage=g.initEnvImage;exports.ModelOptimizer=S.ModelOptimizer;exports.modelOptimizer=S.modelOptimizer;exports.ThreeIns=v;exports.ViewType=E;
|
package/dist/threejs.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { i as
|
|
5
|
-
import { d as
|
|
6
|
-
import { C as
|
|
7
|
-
import { I as
|
|
8
|
-
import { ModelOptimizer as
|
|
9
|
-
import { MathUtils as
|
|
10
|
-
const
|
|
1
|
+
var H = Object.defineProperty;
|
|
2
|
+
var A = (g, t, e) => t in g ? H(g, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : g[t] = e;
|
|
3
|
+
var n = (g, t, e) => A(g, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
+
import { i as se, o as oe, c as ie, b as ne, a as re, u as ae } from "./useBatchGLTFLoader-C1C8R5Ss.js";
|
|
5
|
+
import { d as P, S as j, s as X, j as Y } from "./PredictiveLoader-C9zJlZEQ.js";
|
|
6
|
+
import { C as ce, E as de, I as he, M as me, P as xe, q as fe, R as ge, n as ue, h as pe, g as Fe, b as Re, c as Me, a as ze, e as be, f as Ee, i as Le, l as Oe, m as we, o as Ce, k as ye, p as Te, r as Se, u as De } from "./PredictiveLoader-C9zJlZEQ.js";
|
|
7
|
+
import { I as Ie, c as He, a as Ae, g as Pe, b as je, d as Xe, i as Ye } from "./objectQuery-BfHUGPET.js";
|
|
8
|
+
import { ModelOptimizer as Ze, modelOptimizer as qe } from "./modelOptimizer-D6fRg-DF.js";
|
|
9
|
+
import { MathUtils as R, Scene as V, PerspectiveCamera as Z, WebGLRenderer as q, Box3 as B, Vector3 as l, Box3Helper as _ } from "three";
|
|
10
|
+
const G = "1.5.0", N = 50, W = 20, $ = 20, T = {
|
|
11
11
|
TOP: "top",
|
|
12
12
|
// 俯视(从上往下)
|
|
13
13
|
RIGHT: "right",
|
|
@@ -16,15 +16,15 @@ const N = "1.5.0", W = 50, k = 20, U = 20, v = {
|
|
|
16
16
|
// 左侧视
|
|
17
17
|
ISO: "iso"
|
|
18
18
|
// 正斜视(等轴测视角)
|
|
19
|
-
},
|
|
19
|
+
}, k = {
|
|
20
20
|
enableDamping: !0,
|
|
21
21
|
dampingFactor: 0.25,
|
|
22
22
|
screenSpacePanning: !1,
|
|
23
23
|
minDistance: 0.1,
|
|
24
24
|
maxDistance: 1e3,
|
|
25
|
-
maxPolarAngle:
|
|
25
|
+
maxPolarAngle: R.degToRad(60)
|
|
26
26
|
};
|
|
27
|
-
class
|
|
27
|
+
class U {
|
|
28
28
|
/**
|
|
29
29
|
* 构造函数
|
|
30
30
|
* @param {string} selector - DOM 容器选择器
|
|
@@ -38,22 +38,22 @@ class J {
|
|
|
38
38
|
* @param {boolean} [option.control.init=true] - 是否初始化控制器
|
|
39
39
|
* @param {Object} [option.control.options={}] - 控制器选项
|
|
40
40
|
*/
|
|
41
|
-
constructor(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
41
|
+
constructor(t, e) {
|
|
42
|
+
n(this, "isReady", !1);
|
|
43
|
+
n(this, "scene", null);
|
|
44
|
+
n(this, "camera", null);
|
|
45
|
+
n(this, "renderer", null);
|
|
46
|
+
n(this, "control", null);
|
|
47
|
+
n(this, "css3dRenderer", null);
|
|
48
|
+
n(this, "el", null);
|
|
49
|
+
n(this, "renderRequested", !1);
|
|
50
|
+
n(this, "selector", null);
|
|
51
|
+
n(this, "eventsListener", {});
|
|
52
|
+
n(this, "stats", null);
|
|
53
|
+
n(this, "isDispose", !1);
|
|
54
|
+
n(this, "version", "0.0.0");
|
|
55
|
+
n(this, "boxHelper", null);
|
|
56
|
+
n(this, "initOpt", {
|
|
57
57
|
css3d: !1,
|
|
58
58
|
stats: !1,
|
|
59
59
|
renderType: "change",
|
|
@@ -70,25 +70,25 @@ class J {
|
|
|
70
70
|
* 初始化场景
|
|
71
71
|
* @param {string} selector - DOM 容器选择器
|
|
72
72
|
*/
|
|
73
|
-
|
|
74
|
-
if (this.isDispose = !1, this.selector =
|
|
75
|
-
console.error(`ThreeIns: 找不到元素 ${
|
|
73
|
+
n(this, "setup", (t) => {
|
|
74
|
+
if (this.isDispose = !1, this.selector = t, this.el = document.querySelector(t), !this.el) {
|
|
75
|
+
console.error(`ThreeIns: 找不到元素 ${t}`);
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
78
|
-
const [
|
|
79
|
-
if (this.updateCameraFOV(
|
|
80
|
-
this.control =
|
|
78
|
+
const [e, h] = this.getTargetSize();
|
|
79
|
+
if (this.updateCameraFOV(e, h), this.camera.position.set(0, 0, 0), this.camera.lookAt(0, 0, 0), this.camera.updateProjectionMatrix(), this.renderer.setPixelRatio(window.devicePixelRatio), this.renderer.setSize(e, h), this.el.appendChild(this.renderer.domElement), this.initOpt.control && this.initOpt.control.init) {
|
|
80
|
+
this.control = P(this.camera, this.renderer.domElement);
|
|
81
81
|
const s = Object.assign(
|
|
82
|
-
|
|
82
|
+
k,
|
|
83
83
|
this.initOpt.control.options || {}
|
|
84
84
|
);
|
|
85
|
-
Object.keys(s).forEach((
|
|
86
|
-
this.control[
|
|
85
|
+
Object.keys(s).forEach((u) => {
|
|
86
|
+
this.control[u] = s[u];
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
89
|
setTimeout(() => {
|
|
90
90
|
this.isReady = !0;
|
|
91
|
-
},
|
|
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(
|
|
92
92
|
"change",
|
|
93
93
|
this.requestRenderIfNotRequested
|
|
94
94
|
), this.initListener();
|
|
@@ -97,22 +97,22 @@ class J {
|
|
|
97
97
|
* WebGL 上下文丢失处理
|
|
98
98
|
* @param {Event} e - 事件对象
|
|
99
99
|
*/
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
n(this, "onContextLost", (t) => {
|
|
101
|
+
t.preventDefault(), this.animationFrameId && cancelAnimationFrame(this.animationFrameId);
|
|
102
102
|
});
|
|
103
103
|
/**
|
|
104
104
|
* WebGL 上下文恢复处理
|
|
105
105
|
* @param {Event} e - 事件对象
|
|
106
106
|
*/
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
n(this, "onContextRestored", (t) => {
|
|
108
|
+
t.preventDefault(), this.dispose(), setTimeout(() => {
|
|
109
109
|
this.setup(this.selector);
|
|
110
|
-
},
|
|
110
|
+
}, $);
|
|
111
111
|
});
|
|
112
112
|
/**
|
|
113
113
|
* 初始化事件监听器
|
|
114
114
|
*/
|
|
115
|
-
|
|
115
|
+
n(this, "initListener", () => {
|
|
116
116
|
this.initOpt.initListener && window && window.addEventListener("resize", this.onResize, !1), this.renderer.domElement.addEventListener(
|
|
117
117
|
"webglcontextlost",
|
|
118
118
|
this.onContextLost,
|
|
@@ -126,7 +126,7 @@ class J {
|
|
|
126
126
|
/**
|
|
127
127
|
* 移除事件监听器
|
|
128
128
|
*/
|
|
129
|
-
|
|
129
|
+
n(this, "removeListener", () => {
|
|
130
130
|
window && window.removeEventListener("resize", this.onResize, !1), this.renderer && this.renderer.domElement && (this.renderer.domElement.removeEventListener(
|
|
131
131
|
"webglcontextlost",
|
|
132
132
|
this.onContextLost,
|
|
@@ -140,19 +140,19 @@ class J {
|
|
|
140
140
|
/**
|
|
141
141
|
* 渲染循环(loop 模式)
|
|
142
142
|
*/
|
|
143
|
-
|
|
143
|
+
n(this, "animate", () => {
|
|
144
144
|
this.isDispose || (this.initOpt.renderType === "loop" && this.onRender(), this.animationFrameId = requestAnimationFrame(this.animate));
|
|
145
145
|
});
|
|
146
146
|
/**
|
|
147
147
|
* 执行渲染
|
|
148
148
|
*/
|
|
149
|
-
|
|
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((
|
|
149
|
+
n(this, "onRender", () => {
|
|
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((t) => t()));
|
|
151
151
|
});
|
|
152
152
|
/**
|
|
153
153
|
* 请求渲染(如果尚未请求)
|
|
154
154
|
*/
|
|
155
|
-
|
|
155
|
+
n(this, "requestRenderIfNotRequested", () => {
|
|
156
156
|
this.renderRequested || (this.renderRequested = !0, requestAnimationFrame(() => {
|
|
157
157
|
this.onRender();
|
|
158
158
|
}));
|
|
@@ -160,11 +160,11 @@ class J {
|
|
|
160
160
|
/**
|
|
161
161
|
* 处理窗口大小变化(带防抖)
|
|
162
162
|
*/
|
|
163
|
-
|
|
163
|
+
n(this, "onResize", () => {
|
|
164
164
|
this.resizeTimer && clearTimeout(this.resizeTimer), this.resizeTimer = setTimeout(() => {
|
|
165
|
-
const [
|
|
166
|
-
this.updateCameraFOV(
|
|
167
|
-
},
|
|
165
|
+
const [t, e] = this.getTargetSize();
|
|
166
|
+
this.updateCameraFOV(t, e), this.camera.lookAt(this.scene.position), this.renderer.setSize(t, e), this.css3dRenderer && this.css3dRenderer.setSize(t, e), this.onRender();
|
|
167
|
+
}, N);
|
|
168
168
|
});
|
|
169
169
|
/**
|
|
170
170
|
* @deprecated 此方法已弃用,请使用 setView() 方法代替
|
|
@@ -181,21 +181,25 @@ class J {
|
|
|
181
181
|
* @param {number} [scale=0.8] - 缩放比例,1=占满画布,0.5=50%,2.0=200%
|
|
182
182
|
* @returns {Object} 返回 setView 的结果
|
|
183
183
|
*/
|
|
184
|
-
|
|
184
|
+
n(this, "frameArea", (t, e) => (console.warn(
|
|
185
185
|
`[ThreeIns] frameArea() 已弃用,建议使用 setView() 方法。
|
|
186
186
|
旧用法: threeIns.frameArea(model, scale)
|
|
187
187
|
新用法: threeIns.setView(model, ViewType.ISO, { scale })`
|
|
188
|
-
), this.setView(
|
|
188
|
+
), this.setView(t, T.ISO, { scale: e, animate: !1, showBox: !1 })));
|
|
189
189
|
/**
|
|
190
190
|
* 切换到指定视角
|
|
191
191
|
* 根据视角类型自动调整相机位置和朝向,支持缩放比例控制
|
|
192
192
|
*
|
|
193
193
|
* @param {Object3D} model - 3D 物体对象
|
|
194
|
-
* @param {string} viewType -
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
194
|
+
* @param {string|Vector3} viewType - 视角类型,可以使用 ViewType 枚举或自定义 Vector3 方向向量
|
|
195
|
+
* - ViewType 枚举:
|
|
196
|
+
* - 'top': 俯视(从上往下看 Y 轴正方向)
|
|
197
|
+
* - 'right': 侧视(从右往左看 X 轴正方向)
|
|
198
|
+
* - 'left': 左侧视(从左往右看 X 轴负方向)
|
|
199
|
+
* - 'iso': 正斜视(等轴测视角,45°角)
|
|
200
|
+
* - Vector3 自定义方向:
|
|
201
|
+
* - 任意方向向量,如 Vector3(1, 1, 1)、Vector3(2, 0, 1)
|
|
202
|
+
* - 向量会被自动归一化,相对模型中心的任意角度
|
|
199
203
|
* @param {Object} [options] - 可选配置
|
|
200
204
|
* @param {number} [options.scale=1] - 缩放比例,控制模型在画布中的占比
|
|
201
205
|
* @param {string|Vector3} [options.position='center'] - 模型在画布中的位置
|
|
@@ -215,6 +219,8 @@ class J {
|
|
|
215
219
|
* // 导入 ViewType 枚举
|
|
216
220
|
* import { ThreeIns, ViewType } from 'threejs';
|
|
217
221
|
*
|
|
222
|
+
* // ============ 使用预设 ViewType ============
|
|
223
|
+
*
|
|
218
224
|
* // 切换到俯视,模型占满画布,居中显示
|
|
219
225
|
* threeIns.setView(model, ViewType.TOP);
|
|
220
226
|
*
|
|
@@ -244,77 +250,114 @@ class J {
|
|
|
244
250
|
* scale: 0.8
|
|
245
251
|
* });
|
|
246
252
|
*
|
|
253
|
+
* // ============ 使用自定义 Vector3 方向 ============
|
|
254
|
+
*
|
|
255
|
+
* // 从对角线方向查看模型(类似等轴测)
|
|
256
|
+
* threeIns.setView(model, new THREE.Vector3(1, 1, 1));
|
|
257
|
+
*
|
|
258
|
+
* // 从右前方查看模型
|
|
259
|
+
* threeIns.setView(model, new THREE.Vector3(2, 1, 1));
|
|
260
|
+
*
|
|
261
|
+
* // 从左侧平视模型
|
|
262
|
+
* threeIns.setView(model, new THREE.Vector3(0, 0, 1));
|
|
263
|
+
*
|
|
264
|
+
* // 从下方仰视模型
|
|
265
|
+
* threeIns.setView(model, new THREE.Vector3(0, -1, 1));
|
|
266
|
+
*
|
|
267
|
+
* // 自定义方向 + 其他选项
|
|
268
|
+
* threeIns.setView(model, new THREE.Vector3(1, 2, 1), {
|
|
269
|
+
* scale: 0.6,
|
|
270
|
+
* position: 'center',
|
|
271
|
+
* showBox: true,
|
|
272
|
+
* animate: true,
|
|
273
|
+
* duration: 1500
|
|
274
|
+
* });
|
|
275
|
+
*
|
|
247
276
|
* // 或者使用类静态属性(向后兼容)
|
|
248
277
|
* threeIns.setView(model, ThreeIns.ViewType.TOP);
|
|
249
278
|
*/
|
|
250
|
-
|
|
251
|
-
let s = h.scale || 0.8,
|
|
252
|
-
const
|
|
253
|
-
let
|
|
254
|
-
if (typeof
|
|
255
|
-
const
|
|
256
|
-
center: new
|
|
257
|
-
"top-left": new
|
|
258
|
-
"top-right": new
|
|
259
|
-
"bottom-left": new
|
|
260
|
-
"bottom-right": new
|
|
261
|
-
},
|
|
262
|
-
|
|
263
|
-
} else
|
|
264
|
-
|
|
265
|
-
const
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
279
|
+
n(this, "setView", (t, e, h = {}) => {
|
|
280
|
+
let s = h.scale || 0.8, u = h.offset || null, M = h.position || "center", z = h.showBox || !1, S = h.boxColor || 16776960, E = h.animate !== void 0 ? h.animate : !0, L = h.duration || 1e3;
|
|
281
|
+
const p = new B().setFromObject(t);
|
|
282
|
+
let d = p.getCenter(new l());
|
|
283
|
+
if (typeof M == "string") {
|
|
284
|
+
const i = p.getSize(new l()), r = {
|
|
285
|
+
center: new l(0, 0, 0),
|
|
286
|
+
"top-left": new l(-i.x * 0.3, i.y * 0.3, i.z * 0.3),
|
|
287
|
+
"top-right": new l(i.x * 0.3, i.y * 0.3, i.z * 0.3),
|
|
288
|
+
"bottom-left": new l(-i.x * 0.3, -i.y * 0.3, i.z * 0.3),
|
|
289
|
+
"bottom-right": new l(i.x * 0.3, -i.y * 0.3, i.z * 0.3)
|
|
290
|
+
}, c = r[M] || r.center;
|
|
291
|
+
typeof e == "string" ? e === "top" ? d.add(new l(c.x, 0, c.z)) : e === "right" || e === "left" ? d.add(new l(c.x, c.y, c.z)) : d.add(c) : d.add(c);
|
|
292
|
+
} else M instanceof l && d.add(M);
|
|
293
|
+
u && d.add(u);
|
|
294
|
+
const o = p.getSize(new l());
|
|
295
|
+
let F;
|
|
296
|
+
if (e instanceof l)
|
|
297
|
+
F = e.clone().normalize();
|
|
298
|
+
else {
|
|
299
|
+
const i = {
|
|
300
|
+
top: new l(0, 1, 0),
|
|
301
|
+
// 从上往下:Y 轴正方向
|
|
302
|
+
right: new l(1, 1, 1).normalize(),
|
|
303
|
+
// 从右往左:X 轴正方向
|
|
304
|
+
left: new l(-1, 1, 1).normalize(),
|
|
305
|
+
// 从左往右:X 轴负方向
|
|
306
|
+
iso: new l(0, 1, 1).normalize()
|
|
307
|
+
// 等轴测:从对角线上方俯视
|
|
308
|
+
};
|
|
309
|
+
F = i[e] || i.iso;
|
|
310
|
+
}
|
|
311
|
+
const O = this.camera.aspect, a = R.degToRad(this.camera.fov * 0.5), D = R.degToRad(80), m = Math.min(Math.atan(Math.tan(a) * O), D);
|
|
312
|
+
let x;
|
|
313
|
+
if (e instanceof l) {
|
|
314
|
+
const i = o.x * 0.5 / (Math.tan(m) * s), r = o.y * 0.5 / (Math.tan(a) * s), c = o.z * 0.5 / (Math.tan(a) * s);
|
|
315
|
+
x = Math.max(i, r, c);
|
|
316
|
+
} else if (e === "top") {
|
|
317
|
+
const i = o.x * 0.5 / (Math.tan(m) * s), r = o.z * 0.5 / (Math.tan(a) * s);
|
|
318
|
+
x = Math.max(i, r);
|
|
319
|
+
} else if (e === "right" || e === "left") {
|
|
320
|
+
const i = o.y * 0.5 / (Math.tan(a) * s), r = o.z * 0.5 / (Math.tan(a) * s);
|
|
321
|
+
x = Math.max(i, r);
|
|
282
322
|
} else {
|
|
283
|
-
const
|
|
284
|
-
|
|
323
|
+
const i = o.x * 0.5 / (Math.tan(m) * s), r = o.y * 0.5 / (Math.tan(a) * s), c = o.z * 0.5 / (Math.tan(a) * s);
|
|
324
|
+
x = Math.max(i, r, c);
|
|
285
325
|
}
|
|
286
|
-
const
|
|
287
|
-
if (z && (console.log("📍 相机位置验证:"), console.log(" - 方向向量:",
|
|
288
|
-
const
|
|
289
|
-
const
|
|
290
|
-
if (this.camera.position.lerpVectors(
|
|
291
|
-
const
|
|
292
|
-
|
|
326
|
+
const f = F.clone().multiplyScalar(x).add(d);
|
|
327
|
+
if (z && (console.log("📍 相机位置验证:"), console.log(" - 方向向量:", F), console.log(" - 距离:", x.toFixed(2)), console.log(" - 包围盒中心:", d), console.log(" - 计算公式: direction * distance + boxCenter"), console.log(" - 目标位置:", f), console.log(" - 实际相机与中心的距离:", f.clone().sub(d).length().toFixed(2))), z ? (this.boxHelper && (this.scene.remove(this.boxHelper), this.boxHelper = null), this.boxHelper = new _(p, S), this.scene.add(this.boxHelper)) : this.boxHelper && (this.scene.remove(this.boxHelper), this.boxHelper = null), E) {
|
|
328
|
+
const i = this.camera.position.clone(), r = this.control ? this.control.target.clone() : new l(0, 0, 0), c = d, v = Date.now(), w = () => {
|
|
329
|
+
const I = Date.now() - v, C = Math.min(I / L, 1), y = 1 - Math.pow(1 - C, 3);
|
|
330
|
+
if (this.camera.position.lerpVectors(i, f, y), this.control) {
|
|
331
|
+
const b = new l();
|
|
332
|
+
b.lerpVectors(r, c, y), this.control.target.copy(b), this.camera.lookAt(b);
|
|
293
333
|
} else
|
|
294
|
-
this.camera.lookAt(
|
|
295
|
-
this.camera.updateProjectionMatrix(), C < 1 ? requestAnimationFrame(
|
|
334
|
+
this.camera.lookAt(d);
|
|
335
|
+
this.camera.updateProjectionMatrix(), C < 1 ? requestAnimationFrame(w) : (this.camera.position.copy(f), this.camera.lookAt(d), this.camera.updateProjectionMatrix(), this.control && (this.control.target.copy(d), this.control.update()), this.onRender());
|
|
296
336
|
};
|
|
297
|
-
|
|
337
|
+
w();
|
|
298
338
|
} else
|
|
299
|
-
this.camera.position.copy(
|
|
339
|
+
this.camera.position.copy(f), this.camera.lookAt(d), this.camera.updateProjectionMatrix(), this.control && (this.control.target.copy(d), this.control.update()), this.onRender();
|
|
300
340
|
if (z) {
|
|
301
|
-
if (console.log("🎥 视角切换信息:"), console.log(" - 视角类型:",
|
|
302
|
-
const
|
|
303
|
-
console.log(" - 模型 X 尺寸 (宽度):",
|
|
304
|
-
} else if (
|
|
305
|
-
const
|
|
306
|
-
console.log(" -
|
|
341
|
+
if (console.log("🎥 视角切换信息:"), console.log(" - 视角类型:", e instanceof l ? `自定义 Vector3(${e.x.toFixed(2)}, ${e.y.toFixed(2)}, ${e.z.toFixed(2)})` : e), console.log(" - 相机位置:", f), console.log(" - 观察目标:", d), console.log(" - 方向向量:", F), console.log(" - 包围盒尺寸:", o), console.log(" - 包围盒中心:", p.getCenter(new l())), console.log(" - 水平 FOV:", R.radToDeg(m * 2).toFixed(2) + "°"), console.log(" - 垂直 FOV:", R.radToDeg(a * 2).toFixed(2) + "°"), console.log(" - 宽高比:", O.toFixed(4)), console.log(" - 模型宽度:", o.x.toFixed(2)), console.log(" - 模型高度:", o.y.toFixed(2)), console.log(" - 模型深度:", o.z.toFixed(2)), console.log(" - 传入的 scale 参数:", s), e instanceof l) {
|
|
342
|
+
const i = o.x * 0.5 / (Math.tan(m) * s), r = o.y * 0.5 / (Math.tan(a) * s), c = o.z * 0.5 / (Math.tan(a) * s);
|
|
343
|
+
console.log(" - 模型 X 尺寸 (宽度):", o.x.toFixed(2)), console.log(" - 模型 Y 尺寸 (高度):", o.y.toFixed(2)), console.log(" - 模型 Z 尺寸 (深度):", o.z.toFixed(2)), console.log(" - tan(halfFovX):", Math.tan(m).toFixed(4)), console.log(" - tan(halfFovY):", Math.tan(a).toFixed(4)), console.log(" - X方向距离计算: (", (o.x * 0.5).toFixed(2), ") / (", Math.tan(m).toFixed(4), " *", s, ") =", i.toFixed(2)), console.log(" - Y方向距离计算: (", (o.y * 0.5).toFixed(2), ") / (", Math.tan(a).toFixed(4), " *", s, ") =", r.toFixed(2)), console.log(" - Z方向距离计算: (", (o.z * 0.5).toFixed(2), ") / (", Math.tan(a).toFixed(4), " *", s, ") =", c.toFixed(2)), console.log(" - X方向距离 (scale=" + s + "):", i.toFixed(2)), console.log(" - Y方向距离 (scale=" + s + "):", r.toFixed(2)), console.log(" - Z方向距离 (scale=" + s + "):", c.toFixed(2)), console.log(" - 最大距离 (Max):", Math.max(i, r, c).toFixed(2));
|
|
344
|
+
} else if (e === "top") {
|
|
345
|
+
const i = o.x * 0.5 / (Math.tan(m) * s), r = o.z * 0.5 / (Math.tan(a) * s);
|
|
346
|
+
console.log(" - 模型 X 尺寸 (宽度):", o.x.toFixed(2)), console.log(" - 模型 Z 尺寸 (深度):", o.z.toFixed(2)), console.log(" - tan(halfFovX):", Math.tan(m).toFixed(4)), console.log(" - tan(halfFovY):", Math.tan(a).toFixed(4)), console.log(" - X方向距离计算: (", (o.x * 0.5).toFixed(2), ") / (", Math.tan(m).toFixed(4), " *", s, ") =", i.toFixed(2)), console.log(" - Z方向距离计算: (", (o.z * 0.5).toFixed(2), ") / (", Math.tan(a).toFixed(4), " *", s, ") =", r.toFixed(2)), console.log(" - X方向距离 (scale=" + s + "):", i.toFixed(2)), console.log(" - Z方向距离 (scale=" + s + "):", r.toFixed(2));
|
|
347
|
+
} else if (e === "right" || e === "left") {
|
|
348
|
+
const i = o.y * 0.5 / (Math.tan(a) * s), r = o.z * 0.5 / (Math.tan(a) * s);
|
|
349
|
+
console.log(" - Y方向距离 (scale=" + s + "):", i.toFixed(2)), console.log(" - Z方向距离 (scale=" + s + "):", r.toFixed(2));
|
|
307
350
|
} else {
|
|
308
|
-
const
|
|
309
|
-
console.log(" - 模型 X 尺寸 (宽度):",
|
|
351
|
+
const i = o.x * 0.5 / (Math.tan(m) * s), r = o.y * 0.5 / (Math.tan(a) * s), c = o.z * 0.5 / (Math.tan(a) * s);
|
|
352
|
+
console.log(" - 模型 X 尺寸 (宽度):", o.x.toFixed(2)), console.log(" - 模型 Y 尺寸 (高度):", o.y.toFixed(2)), console.log(" - 模型 Z 尺寸 (深度):", o.z.toFixed(2)), console.log(" - tan(halfFovX):", Math.tan(m).toFixed(4)), console.log(" - tan(halfFovY):", Math.tan(a).toFixed(4)), console.log(" - X方向距离计算: (", (o.x * 0.5).toFixed(2), ") / (", Math.tan(m).toFixed(4), " *", s, ") =", i.toFixed(2)), console.log(" - Y方向距离计算: (", (o.y * 0.5).toFixed(2), ") / (", Math.tan(a).toFixed(4), " *", s, ") =", r.toFixed(2)), console.log(" - Z方向距离计算: (", (o.z * 0.5).toFixed(2), ") / (", Math.tan(a).toFixed(4), " *", s, ") =", c.toFixed(2)), console.log(" - X方向距离 (scale=" + s + "):", i.toFixed(2)), console.log(" - Y方向距离 (scale=" + s + "):", r.toFixed(2)), console.log(" - Z方向距离 (scale=" + s + "):", c.toFixed(2)), console.log(" - 最大距离 (Max):", Math.max(i, r, c).toFixed(2));
|
|
310
353
|
}
|
|
311
|
-
console.log(" - 最终距离:",
|
|
354
|
+
console.log(" - 最终距离:", x.toFixed(2)), console.log(" - 缩放比例:", s), console.log(" - 动画:", E ? "是 (" + L + "ms)" : "否");
|
|
312
355
|
}
|
|
313
356
|
return {
|
|
314
|
-
position:
|
|
315
|
-
target:
|
|
316
|
-
distance:
|
|
317
|
-
viewType:
|
|
357
|
+
position: f,
|
|
358
|
+
target: d,
|
|
359
|
+
distance: x,
|
|
360
|
+
viewType: e
|
|
318
361
|
};
|
|
319
362
|
});
|
|
320
363
|
/**
|
|
@@ -323,14 +366,14 @@ class J {
|
|
|
323
366
|
* @param {Function} callback - 回调函数
|
|
324
367
|
* @returns {Function} 返回取消监听的函数
|
|
325
368
|
*/
|
|
326
|
-
|
|
327
|
-
}) : (this.eventsListener[
|
|
328
|
-
this.isReady = !1, this.scene = new
|
|
369
|
+
n(this, "on", (t, e) => !t || !e || typeof e != "function" ? (console.warn("ThreeIns.on: 无效的参数"), () => {
|
|
370
|
+
}) : (this.eventsListener[t] || (this.eventsListener[t] = []), this.eventsListener[t].push(e), () => this.off(t, e)));
|
|
371
|
+
this.isReady = !1, this.scene = new V({}), this.camera = new Z(50, 1, 0.1, 2e3), this.renderer = new q({
|
|
329
372
|
antialias: !0,
|
|
330
373
|
alpha: !0,
|
|
331
374
|
precision: "mediump",
|
|
332
375
|
logarithmicDepthBuffer: !0
|
|
333
|
-
}), this.version =
|
|
376
|
+
}), 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, e && (this.initOpt = Object.assign(this.initOpt, e)), t && this.setup(t);
|
|
334
377
|
}
|
|
335
378
|
/**
|
|
336
379
|
* 更新相机 FOV 以适应容器尺寸
|
|
@@ -338,23 +381,23 @@ class J {
|
|
|
338
381
|
* @param {number} domW - 容器宽度
|
|
339
382
|
* @param {number} domH - 容器高度
|
|
340
383
|
*/
|
|
341
|
-
updateCameraFOV(
|
|
384
|
+
updateCameraFOV(t, e) {
|
|
342
385
|
const h = this.initOpt.initialFov || 50, s = Math.tan(Math.PI / 180 * h / 2);
|
|
343
|
-
this.camera.aspect =
|
|
386
|
+
this.camera.aspect = t / e, this.camera.fov = 360 / Math.PI * Math.atan(s * (e / t)), this.camera.updateProjectionMatrix();
|
|
344
387
|
}
|
|
345
388
|
/**
|
|
346
389
|
* 初始化性能统计
|
|
347
390
|
*/
|
|
348
391
|
initStats() {
|
|
349
|
-
this.stats = new
|
|
392
|
+
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);
|
|
350
393
|
}
|
|
351
394
|
/**
|
|
352
395
|
* 初始化 CSS3D 渲染器
|
|
353
396
|
*/
|
|
354
397
|
initCss3dRenderer() {
|
|
355
|
-
this.css3dRenderer = new
|
|
356
|
-
const [
|
|
357
|
-
this.css3dRenderer.setSize(
|
|
398
|
+
this.css3dRenderer = new X();
|
|
399
|
+
const [t, e] = this.getTargetSize();
|
|
400
|
+
this.css3dRenderer.setSize(t, e), 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);
|
|
358
401
|
}
|
|
359
402
|
/**
|
|
360
403
|
* 获取目标容器尺寸
|
|
@@ -369,64 +412,64 @@ class J {
|
|
|
369
412
|
* @param {string} event - 事件名称
|
|
370
413
|
* @param {Function} [callback] - 可选的回调函数,如果不提供则移除该事件的所有监听器
|
|
371
414
|
*/
|
|
372
|
-
off(
|
|
373
|
-
if (!
|
|
415
|
+
off(t, e) {
|
|
416
|
+
if (!t) {
|
|
374
417
|
this.eventsListener = {};
|
|
375
418
|
return;
|
|
376
419
|
}
|
|
377
|
-
this.eventsListener[
|
|
420
|
+
this.eventsListener[t] && (e ? this.eventsListener[t] = this.eventsListener[t].filter((h) => h !== e) : this.eventsListener[t] = []);
|
|
378
421
|
}
|
|
379
422
|
/**
|
|
380
423
|
* 清理所有资源
|
|
381
424
|
*/
|
|
382
425
|
dispose() {
|
|
383
|
-
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 && (
|
|
426
|
+
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 && (Y(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: 资源已清理完成"));
|
|
384
427
|
}
|
|
385
428
|
}
|
|
386
429
|
// 存储包围盒辅助器
|
|
387
430
|
// 视角类型枚举(作为类静态属性引用,保持向后兼容)
|
|
388
|
-
|
|
431
|
+
n(U, "ViewType", T);
|
|
389
432
|
export {
|
|
390
|
-
|
|
433
|
+
ce as CacheMonitor,
|
|
391
434
|
de as ErrorType,
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
435
|
+
he as IDBCache,
|
|
436
|
+
Ie as ImageLoader,
|
|
437
|
+
me as ModelLoadError,
|
|
438
|
+
Ze as ModelOptimizer,
|
|
439
|
+
xe as PredictiveLoader,
|
|
440
|
+
fe as ProgressiveSceneBuilder,
|
|
441
|
+
ge as RetryHelper,
|
|
442
|
+
U as ThreeIns,
|
|
443
|
+
T as ViewType,
|
|
444
|
+
ue as cacheMonitor,
|
|
445
|
+
pe as createArrowHelper,
|
|
446
|
+
Fe as createAxesHelper,
|
|
447
|
+
Re as createBox3Helper,
|
|
448
|
+
Me as createCameraHelper,
|
|
449
|
+
ze as createGridHelper,
|
|
450
|
+
He as createInfoPlane,
|
|
451
|
+
be as createMapControls,
|
|
452
|
+
P as createOrbitControl,
|
|
410
453
|
Ee as createRaycaster,
|
|
411
454
|
Le as createStats,
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
455
|
+
Ae as createTagPlane,
|
|
456
|
+
Oe as dataToObject3D,
|
|
457
|
+
we as dataToObject3DSync,
|
|
458
|
+
Y as disposeThreeObject,
|
|
459
|
+
Pe as getCommonParent,
|
|
460
|
+
je as getObjectByUserData,
|
|
461
|
+
Xe as getRootObj,
|
|
462
|
+
Ye as initEnvImage,
|
|
463
|
+
se as intersectColor,
|
|
464
|
+
qe as modelOptimizer,
|
|
465
|
+
oe as obbObjects,
|
|
423
466
|
Ce as object3DToData,
|
|
424
467
|
ye as object3DToDataSync,
|
|
425
|
-
|
|
468
|
+
Te as predictiveLoader,
|
|
426
469
|
Se as rebuildScene,
|
|
427
|
-
|
|
470
|
+
ie as useBatchGLTFLoader,
|
|
428
471
|
De as useGLTFLoader,
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
472
|
+
ne as useObb,
|
|
473
|
+
re as useRaycaster,
|
|
474
|
+
ae as useThreeJs
|
|
432
475
|
};
|