@ridp/threejs 1.4.1 → 1.4.2

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 (55) hide show
  1. package/dist/hooks.cjs +1 -1
  2. package/dist/hooks.js +12 -9
  3. package/dist/packages/threejs/package.json.cjs +1 -0
  4. package/dist/packages/threejs/package.json.js +4 -0
  5. package/dist/packages/threejs/src/hooks/useBatchGLTFLoader.cjs +1 -0
  6. package/dist/packages/threejs/src/hooks/useBatchGLTFLoader.js +83 -0
  7. package/dist/packages/threejs/src/hooks/useGLTFLoader.cjs +1 -0
  8. package/dist/packages/threejs/src/hooks/useGLTFLoader.js +292 -0
  9. package/dist/packages/threejs/src/hooks/useObb.cjs +1 -0
  10. package/dist/packages/threejs/src/hooks/useObb.js +41 -0
  11. package/dist/packages/threejs/src/hooks/useRaycaster.cjs +1 -0
  12. package/dist/packages/threejs/src/hooks/useRaycaster.js +35 -0
  13. package/dist/packages/threejs/src/hooks/useThreeJs.cjs +5 -0
  14. package/dist/packages/threejs/src/hooks/useThreeJs.js +153 -0
  15. package/dist/packages/threejs/src/instance/IDBCache.cjs +1 -0
  16. package/dist/packages/threejs/src/instance/IDBCache.js +142 -0
  17. package/dist/packages/threejs/src/instance/threeIns.cjs +3 -0
  18. package/dist/packages/threejs/src/instance/threeIns.js +369 -0
  19. package/dist/packages/threejs/src/utils/CacheMonitor.cjs +1 -0
  20. package/dist/packages/threejs/src/utils/CacheMonitor.js +125 -0
  21. package/dist/packages/threejs/src/utils/ImageLoader.cjs +1 -0
  22. package/dist/packages/threejs/src/utils/ImageLoader.js +33 -0
  23. package/dist/packages/threejs/src/utils/PredictiveLoader.cjs +1 -0
  24. package/dist/packages/threejs/src/utils/PredictiveLoader.js +155 -0
  25. package/dist/packages/threejs/src/utils/RetryHelper.cjs +1 -0
  26. package/dist/packages/threejs/src/utils/RetryHelper.js +108 -0
  27. package/dist/packages/threejs/src/utils/common.cjs +1 -0
  28. package/dist/packages/threejs/src/utils/common.js +15 -0
  29. package/dist/packages/threejs/src/utils/css3dHelper.cjs +15 -0
  30. package/dist/packages/threejs/src/utils/css3dHelper.js +42 -0
  31. package/dist/packages/threejs/src/utils/disposeObject.cjs +1 -0
  32. package/dist/packages/threejs/src/utils/disposeObject.js +13 -0
  33. package/dist/packages/threejs/src/utils/helper.cjs +1 -0
  34. package/dist/packages/threejs/src/utils/helper.js +47 -0
  35. package/dist/packages/threejs/src/utils/modelSerialize.cjs +1 -0
  36. package/dist/packages/threejs/src/utils/modelSerialize.js +225 -0
  37. package/dist/packages/threejs/src/utils/sceneRebuilder.cjs +1 -0
  38. package/dist/packages/threejs/src/utils/sceneRebuilder.js +138 -0
  39. package/dist/packages/threejs/src/workers/gltfParser.worker.cjs +1 -0
  40. package/dist/packages/threejs/src/workers/gltfParser.worker.js +11 -0
  41. package/dist/packages/threejs/src/workers/gltfParserOptimized.worker.cjs +1 -0
  42. package/dist/packages/threejs/src/workers/gltfParserOptimized.worker.js +11 -0
  43. package/dist/threejs.cjs +1 -3
  44. package/dist/threejs.js +58 -404
  45. package/dist/utils.cjs +1 -1
  46. package/dist/utils.js +40 -32
  47. package/package.json +1 -1
  48. package/dist/ImageLoader-Br_nvMOg.js +0 -1444
  49. package/dist/ImageLoader-DL32KyTh.cjs +0 -24
  50. package/dist/PredictiveLoader-CZfMSjv-.js +0 -3731
  51. package/dist/PredictiveLoader-DDxh7dDg.cjs +0 -2
  52. package/dist/useBatchGLTFLoader-B5EUagWI.js +0 -493
  53. package/dist/useBatchGLTFLoader-BjAvIpyB.cjs +0 -5
  54. /package/dist/{modelOptimizer-A0Cs6f9e.cjs → packages/threejs/src/utils/modelOptimizer.cjs} +0 -0
  55. /package/dist/{modelOptimizer-BRPnM2RH.js → packages/threejs/src/utils/modelOptimizer.js} +0 -0
@@ -0,0 +1,153 @@
1
+ import { MathUtils as I, WebGLRenderer as G, Scene as N, PerspectiveCamera as Y, Box3 as K, Vector3 as y } from "three";
2
+ import { ref as b, shallowRef as Q, onMounted as X, onUnmounted as Z, nextTick as k } from "vue";
3
+ import $ from "../../../../node_modules/.pnpm/three@0.178.0/node_modules/three/examples/jsm/libs/stats.module.js";
4
+ import { CSS3DRenderer as ee } from "../../../../node_modules/.pnpm/three@0.178.0/node_modules/three/examples/jsm/renderers/CSS3DRenderer.js";
5
+ import { createOrbitControl as te } from "../utils/helper.js";
6
+ import { disposeThreeObject as ne } from "../utils/disposeObject.js";
7
+ import "../utils/PredictiveLoader.js";
8
+ const oe = {
9
+ enableDamping: !0,
10
+ dampingFactor: 0.25,
11
+ screenSpacePanning: !1,
12
+ minDistance: 0.1,
13
+ maxDistance: 1e3,
14
+ maxPolarAngle: I.degToRad(60)
15
+ };
16
+ function pe(L, j) {
17
+ typeof console < "u" && console.warn && console.warn(
18
+ `[ThreeIns] useThreeJs() Hook 已弃用,建议使用 ThreeIns 类代替。
19
+ 旧用法: const { scene, camera } = useThreeJs(selector, options)
20
+ 新用法: const threeIns = new ThreeIns(selector, options)
21
+
22
+ ThreeIns 类提供更完整的 API 和更好的性能。`
23
+ );
24
+ const r = Object.assign(
25
+ {
26
+ css3d: !1,
27
+ stats: !1,
28
+ renderType: "change",
29
+ control: {
30
+ init: !0,
31
+ options: {}
32
+ }
33
+ },
34
+ j || {}
35
+ );
36
+ let c, p, n, x = [];
37
+ const z = b(!1), u = Q(), s = b(0), i = b(0), o = new G({
38
+ antialias: !0,
39
+ alpha: !0,
40
+ precision: "mediump",
41
+ logarithmicDepthBuffer: !0
42
+ }), f = new N({}), e = new Y(50, 1, 0.1, 2e3), T = Math.tan(Math.PI / 180 * e.fov / 2);
43
+ let w = !1;
44
+ o.setPixelRatio(window.devicePixelRatio);
45
+ function S() {
46
+ z.value = !1;
47
+ const t = O();
48
+ s.value = t[0], i.value = t[1], e.aspect = s.value / i.value, e.position.set(47, 39, 100), e.fov = 360 / Math.PI * Math.atan(T * (i.value / s.value)), e.lookAt(0, 0, 0), e.updateProjectionMatrix(), o.setSize(s.value, i.value), c.appendChild(o.domElement), r.stats && _(), r.css3d && J();
49
+ let a;
50
+ if (r.control && r.control.init) {
51
+ a = te(e, o.domElement);
52
+ const l = Object.assign(
53
+ oe,
54
+ r.control.options || {}
55
+ );
56
+ Object.keys(l).forEach((h) => {
57
+ a[h] = l[h];
58
+ });
59
+ }
60
+ return k(() => z.value = !0), a;
61
+ }
62
+ function A(t) {
63
+ t.preventDefault(), cancelAnimationFrame(v);
64
+ }
65
+ function R(t) {
66
+ t.preventDefault(), S(), v();
67
+ }
68
+ function q(t) {
69
+ x.push(t);
70
+ }
71
+ function v(t) {
72
+ x && x.length && x.forEach((a) => {
73
+ typeof a == "function" && a();
74
+ }), r.renderType === "loop" && g(), requestAnimationFrame(v);
75
+ }
76
+ function g() {
77
+ w = !1, p && p.update(), u.value && u.value.update(), o.render(f, e), n && n.render(f, e);
78
+ }
79
+ function D() {
80
+ w || (w = !0, requestAnimationFrame(g));
81
+ }
82
+ function C() {
83
+ k(() => {
84
+ const t = O();
85
+ s.value = t[0], i.value = t[1], e.aspect = s.value / i.value, e.fov = 360 / Math.PI * Math.atan(T * (i.value / s.value)), e.updateProjectionMatrix(), e.lookAt(f.position), o.setSize(s.value, i.value), n && n.setSize(s.value, i.value), g();
86
+ });
87
+ }
88
+ function O() {
89
+ return c = document.querySelector(L), c ? [c.clientWidth, c.clientHeight] : [0, 0];
90
+ }
91
+ function _() {
92
+ p = new $(), p.dom.style.cssText = "position:absolute;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000", c.appendChild(p.dom);
93
+ }
94
+ function H(t, a, l, h, P) {
95
+ const F = new K().setFromObject(t), M = F.getSize(new y()).length(), d = F.getCenter(new y());
96
+ P && d.add(P);
97
+ const W = M * a * 0.5, B = I.degToRad(l.fov * 0.5), U = W / Math.tan(B), E = new y().subVectors(l.position, d).multiply(new y(1, 1, 1)).normalize().multiplyScalar(U).add(d), m = {
98
+ x: E.x,
99
+ y: E.y,
100
+ z: E.z,
101
+ lookAt_x: d.x,
102
+ lookAt_y: d.y,
103
+ lookAt_z: d.z
104
+ };
105
+ return l.position.set(m.x, m.y, m.z), l.lookAt(
106
+ m.lookAt_x,
107
+ m.lookAt_y,
108
+ m.lookAt_z
109
+ ), l.updateProjectionMatrix(), h.target.copy(d), h.update(), M;
110
+ }
111
+ function J() {
112
+ n = new ee(), n.setSize(s.value, i.value), n.domElement.style.position = "absolute", n.domElement.style.top = 0, n.domElement.style.left = 0, n.domElement.style.pointerEvents = "none", c.appendChild(n.domElement);
113
+ }
114
+ function V() {
115
+ ne(f);
116
+ }
117
+ return X(() => {
118
+ u.value = S(), window.addEventListener("resize", C, !1), o.domElement.addEventListener(
119
+ "webglcontextlost",
120
+ A,
121
+ !1
122
+ ), o.domElement.addEventListener(
123
+ "webglcontextrestored",
124
+ R,
125
+ !1
126
+ ), r.renderType === "loop" ? requestAnimationFrame(v) : r.renderType === "change" && u.value && u.value.addEventListener("change", D);
127
+ }), Z(() => {
128
+ cancelAnimationFrame(v), o.domElement.removeEventListener("resize", C, !1), o.domElement.removeEventListener(
129
+ "webglcontextlost",
130
+ A,
131
+ !1
132
+ ), o.domElement.removeEventListener(
133
+ "webglcontextrestored",
134
+ R,
135
+ !1
136
+ ), V();
137
+ }), {
138
+ addAnimate: q,
139
+ frameArea: H,
140
+ onRender: g,
141
+ css3dRenderer: n,
142
+ scene: f,
143
+ camera: e,
144
+ control: u,
145
+ renderer: o,
146
+ domWidth: s,
147
+ domHeight: i,
148
+ isReady: z
149
+ };
150
+ }
151
+ export {
152
+ pe as useThreeJs
153
+ };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require("three");const d=require("dexie"),c=4;class r{constructor(e="threeJsIDBCache",t={}){this.version=c,this.dbName=e,this.options={maxSize:t.maxSize||500*1024*1024,maxEntries:t.maxEntries||50,evictRatio:t.evictRatio||.2},this.dbInit()}dbInit(){this.db=new d(this.dbName),this.db.version(this.version).stores({models:"&path, version, timestamp, accessCount, size"}).upgrade(async e=>{console.log("[ IDBCache 版本更新 ] ====> version",c);const t=e.table("models"),s=await t.toArray();for(const o of s)o.data instanceof ArrayBuffer||await t.delete(o.path)})}getDatabase(){return this.db}async saveModel(e,t,s){await this.ensureCapacity(s.byteLength),await this.db.table("models").put({path:e,version:t,data:s,size:s.byteLength,timestamp:Date.now(),accessCount:0})}async ensureCapacity(e){const t=await this.db.table("models").toArray(),s=t.reduce((a,i)=>a+(i.size||0),0),o=t.length,n=s+e>this.options.maxSize,l=o>=this.options.maxEntries;(n||l)&&(console.log(`[ IDBCache ] ====> 容量不足,开始 LRU 淘汰. 总大小: ${(s/1024/1024).toFixed(2)}MB, 条目数: ${o}`),await this.evictLRU(t))}async evictLRU(e){const t=e.sort((a,i)=>(a.accessCount||0)!==(i.accessCount||0)?(a.accessCount||0)-(i.accessCount||0):(a.timestamp||0)-(i.timestamp||0)),s=Math.max(1,Math.floor(t.length*this.options.evictRatio)),o=t.slice(0,s),n=o.map(a=>a.path);await this.db.table("models").bulkDelete(n);const l=o.reduce((a,i)=>a+(i.size||0),0);console.log(`[ IDBCache ] ====> LRU 淘汰完成. 删除 ${s} 个条目,释放 ${(l/1024/1024).toFixed(2)}MB`)}async getModel(e,t){const s=await this.db.table("models").get(e);return s?s.version!==t?(console.log("模型版本不一致, 清除当前记录"),await this.db.table("models").delete(e),null):(await this.db.table("models").update(e,{accessCount:(s.accessCount||0)+1,timestamp:Date.now()}),s.data):(console.warn(`Model "${e}" not found in table models`),null)}async cacheModel(e,t,s){console.log("[ ] ====> path, modelData, version",e,t,s);try{this.db.table("models").put({version:s,path:e,data:t}).then(()=>{console.log(`Model "${e}" cached successfully in table models`)})}catch{console.log(" 缓存模型失败 =====> ")}return t}async loadCachedModel(e,t){let s=null;try{if(s=await this.db.table("models").get(e),!s)return console.warn(`Model "${t}" not found in table models`),null;if(s.version!==t)return console.log(" =====> 模型版本不一致, 清除当前记录"),await this.db.table("models").delete(e),null}catch{return console.log(" =====> 查询表中模型失败"),this.db.delete().then(()=>{this.init()}),null}return s.data}async getStats(){const e=await this.db.table("models").toArray(),t=e.reduce((o,n)=>o+(n.size||0),0),s=e.reduce((o,n)=>o+(n.accessCount||0),0);return{count:e.length,totalSize:t,totalSizeMB:(t/1024/1024).toFixed(2),maxEntries:this.options.maxEntries,maxSizeMB:(this.options.maxSize/1024/1024).toFixed(2),usagePercentage:(t/this.options.maxSize*100).toFixed(2),totalAccessCount:s,avgAccessCount:e.length>0?(s/e.length).toFixed(2):0}}async clear(){await this.db.table("models").clear(),console.log("[ IDBCache ] ====> 缓存已清空")}async deleteModel(e){await this.db.table("models").delete(e)}}exports.IDBCache=r;
@@ -0,0 +1,142 @@
1
+ import "three";
2
+ import d from "dexie";
3
+ const c = 4;
4
+ class m {
5
+ /**
6
+ * 构造函数
7
+ * @param {string} dbName - 数据库名称
8
+ * @param {CacheOptions} options - 缓存配置选项
9
+ */
10
+ constructor(e = "threeJsIDBCache", t = {}) {
11
+ this.version = c, this.dbName = e, this.options = {
12
+ maxSize: t.maxSize || 500 * 1024 * 1024,
13
+ // 默认 500MB
14
+ maxEntries: t.maxEntries || 50,
15
+ // 默认最多 50 个模型
16
+ evictRatio: t.evictRatio || 0.2
17
+ // 淘汰 20%
18
+ }, this.dbInit();
19
+ }
20
+ dbInit() {
21
+ this.db = new d(this.dbName), this.db.version(this.version).stores({
22
+ models: "&path, version, timestamp, accessCount, size"
23
+ }).upgrade(async (e) => {
24
+ console.log("[ IDBCache 版本更新 ] ====> version", c);
25
+ const t = e.table("models"), s = await t.toArray();
26
+ for (const o of s)
27
+ o.data instanceof ArrayBuffer || await t.delete(o.path);
28
+ });
29
+ }
30
+ /**
31
+ * 获取 Dexie 数据库实例
32
+ * @returns {Dexie} Dexie 实例
33
+ */
34
+ getDatabase() {
35
+ return this.db;
36
+ }
37
+ async saveModel(e, t, s) {
38
+ await this.ensureCapacity(s.byteLength), await this.db.table("models").put({
39
+ path: e,
40
+ version: t,
41
+ data: s,
42
+ size: s.byteLength,
43
+ timestamp: Date.now(),
44
+ accessCount: 0
45
+ });
46
+ }
47
+ /**
48
+ * 确保缓存容量足够,不足时执行 LRU 淘汰
49
+ * @param {number} requiredSize - 需要的额外空间(字节)
50
+ */
51
+ async ensureCapacity(e) {
52
+ const t = await this.db.table("models").toArray(), s = t.reduce((a, i) => a + (i.size || 0), 0), o = t.length, n = s + e > this.options.maxSize, l = o >= this.options.maxEntries;
53
+ (n || l) && (console.log(`[ IDBCache ] ====> 容量不足,开始 LRU 淘汰. 总大小: ${(s / 1024 / 1024).toFixed(2)}MB, 条目数: ${o}`), await this.evictLRU(t));
54
+ }
55
+ /**
56
+ * 执行 LRU 淘汰策略
57
+ * @param {Array} models - 所有缓存记录
58
+ */
59
+ async evictLRU(e) {
60
+ const t = e.sort((a, i) => (a.accessCount || 0) !== (i.accessCount || 0) ? (a.accessCount || 0) - (i.accessCount || 0) : (a.timestamp || 0) - (i.timestamp || 0)), s = Math.max(1, Math.floor(t.length * this.options.evictRatio)), o = t.slice(0, s), n = o.map((a) => a.path);
61
+ await this.db.table("models").bulkDelete(n);
62
+ const l = o.reduce((a, i) => a + (i.size || 0), 0);
63
+ console.log(`[ IDBCache ] ====> LRU 淘汰完成. 删除 ${s} 个条目,释放 ${(l / 1024 / 1024).toFixed(2)}MB`);
64
+ }
65
+ async getModel(e, t) {
66
+ const s = await this.db.table("models").get(e);
67
+ return s ? s.version !== t ? (console.log("模型版本不一致, 清除当前记录"), await this.db.table("models").delete(e), null) : (await this.db.table("models").update(e, {
68
+ accessCount: (s.accessCount || 0) + 1,
69
+ timestamp: Date.now()
70
+ }), s.data) : (console.warn(`Model "${e}" not found in table models`), null);
71
+ }
72
+ // ---------------------------- ---------------------------------
73
+ /**
74
+ * 缓存模型到 IndexedDB
75
+ * @param {string} path - 主键值
76
+ * @param {THREE.Object3D} model - 要缓存的模型
77
+ * @param {string} [version] - 缓存模型版本
78
+ */
79
+ async cacheModel(e, t, s) {
80
+ console.log("[ ] ====> path, modelData, version", e, t, s);
81
+ try {
82
+ this.db.table("models").put({ version: s, path: e, data: t }).then(() => {
83
+ console.log(`Model "${e}" cached successfully in table models`);
84
+ });
85
+ } catch {
86
+ console.log(" 缓存模型失败 =====> ");
87
+ }
88
+ return t;
89
+ }
90
+ /**
91
+ * 从 IndexedDB 加载缓存的模型
92
+ * @param {string} path - 主键值
93
+ * @returns {THREE.Object3D | null} 加载的模型
94
+ */
95
+ async loadCachedModel(e, t) {
96
+ let s = null;
97
+ try {
98
+ if (s = await this.db.table("models").get(e), !s)
99
+ return console.warn(`Model "${t}" not found in table models`), null;
100
+ if (s.version !== t)
101
+ return console.log(" =====> 模型版本不一致, 清除当前记录"), await this.db.table("models").delete(e), null;
102
+ } catch {
103
+ return console.log(" =====> 查询表中模型失败"), this.db.delete().then(() => {
104
+ this.init();
105
+ }), null;
106
+ }
107
+ return s.data;
108
+ }
109
+ /**
110
+ * 获取缓存统计信息
111
+ * @returns {Promise<Object>} 缓存统计数据
112
+ */
113
+ async getStats() {
114
+ const e = await this.db.table("models").toArray(), t = e.reduce((o, n) => o + (n.size || 0), 0), s = e.reduce((o, n) => o + (n.accessCount || 0), 0);
115
+ return {
116
+ count: e.length,
117
+ totalSize: t,
118
+ totalSizeMB: (t / 1024 / 1024).toFixed(2),
119
+ maxEntries: this.options.maxEntries,
120
+ maxSizeMB: (this.options.maxSize / 1024 / 1024).toFixed(2),
121
+ usagePercentage: (t / this.options.maxSize * 100).toFixed(2),
122
+ totalAccessCount: s,
123
+ avgAccessCount: e.length > 0 ? (s / e.length).toFixed(2) : 0
124
+ };
125
+ }
126
+ /**
127
+ * 清空所有缓存
128
+ */
129
+ async clear() {
130
+ await this.db.table("models").clear(), console.log("[ IDBCache ] ====> 缓存已清空");
131
+ }
132
+ /**
133
+ * 删除指定模型缓存
134
+ * @param {string} path - 模型路径
135
+ */
136
+ async deleteModel(e) {
137
+ await this.db.table("models").delete(e);
138
+ }
139
+ }
140
+ export {
141
+ m as IDBCache
142
+ };
@@ -0,0 +1,3 @@
1
+ "use strict";var I=Object.defineProperty;var q=(x,e,t)=>e in x?I(x,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):x[e]=t;var i=(x,e,t)=>q(x,typeof e!="symbol"?e+"":e,t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("three"),A=require("../../../../node_modules/.pnpm/three@0.178.0/node_modules/three/examples/jsm/renderers/CSS3DRenderer.cjs"),H=require("../../../../node_modules/.pnpm/three@0.178.0/node_modules/three/examples/jsm/libs/stats.module.cjs"),P=require("../utils/helper.cjs"),X=require("../utils/disposeObject.cjs");require("../utils/PredictiveLoader.cjs");const Y=require("../../package.json.cjs"),j=50,Z=20,_=20,E={TOP:"top",RIGHT:"right",LEFT:"left",ISO:"iso"},B={enableDamping:!0,dampingFactor:.25,screenSpacePanning:!1,minDistance:.1,maxDistance:1e3,maxPolarAngle:n.MathUtils.degToRad(60)};class C{constructor(e,t){i(this,"isReady",!1);i(this,"scene",null);i(this,"camera",null);i(this,"renderer",null);i(this,"control",null);i(this,"css3dRenderer",null);i(this,"el",null);i(this,"renderRequested",!1);i(this,"selector",null);i(this,"eventsListener",{});i(this,"stats",null);i(this,"isDispose",!1);i(this,"version","0.0.0");i(this,"boxHelper",null);i(this,"initOpt",{css3d:!1,stats:!1,renderType:"change",initListener:!0,initialFov:50,control:{init:!0,options:{}}});i(this,"setup",e=>{if(this.isDispose=!1,this.selector=e,this.el=document.querySelector(e),!this.el){console.error(`ThreeIns: 找不到元素 ${e}`);return}const[t,h]=this.getTargetSize();if(this.updateCameraFOV(t,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(t,h),this.el.appendChild(this.renderer.domElement),this.initOpt.control&&this.initOpt.control.init){this.control=P.createOrbitControl(this.camera,this.renderer.domElement);const s=Object.assign(B,this.initOpt.control.options||{});Object.keys(s).forEach(p=>{this.control[p]=s[p]})}setTimeout(()=>{this.isReady=!0},Z),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()});i(this,"onContextLost",e=>{e.preventDefault(),this.animationFrameId&&cancelAnimationFrame(this.animationFrameId)});i(this,"onContextRestored",e=>{e.preventDefault(),this.dispose(),setTimeout(()=>{this.setup(this.selector)},_)});i(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)});i(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))});i(this,"animate",()=>{this.isDispose||(this.initOpt.renderType==="loop"&&this.onRender(),this.animationFrameId=requestAnimationFrame(this.animate))});i(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(e=>e()))});i(this,"requestRenderIfNotRequested",()=>{this.renderRequested||(this.renderRequested=!0,requestAnimationFrame(()=>{this.onRender()}))});i(this,"onResize",()=>{this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=setTimeout(()=>{const[e,t]=this.getTargetSize();this.updateCameraFOV(e,t),this.camera.lookAt(this.scene.position),this.renderer.setSize(e,t),this.css3dRenderer&&this.css3dRenderer.setSize(e,t),this.onRender()},j)});i(this,"frameArea",(e,t)=>(console.warn(`[ThreeIns] frameArea() 已弃用,建议使用 setView() 方法。
2
+ 旧用法: threeIns.frameArea(model, scale)
3
+ 新用法: threeIns.setView(model, ViewType.ISO, { scale })`),this.setView(e,E.ISO,{scale:t,animate:!1,showBox:!1})));i(this,"setView",(e,t,h={})=>{let s=h.scale||.8,p=h.offset||null,F=h.showBox||!1,y=h.boxColor||16776960,w=h.animate!==void 0?h.animate:!0,z=h.duration||1e3;const g=new n.Box3().setFromObject(e);let c=g.getCenter(new n.Vector3);p&&c.add(p);const T={top:new n.Vector3(0,1,0),right:new n.Vector3(2,1,1).normalize(),left:new n.Vector3(-2,1,1).normalize(),iso:new n.Vector3(0,1,1).normalize()},R=T[t]||T.iso,o=g.getSize(new n.Vector3),b=this.camera.aspect,r=n.MathUtils.degToRad(this.camera.fov*.5),S=n.MathUtils.degToRad(80),d=Math.min(Math.atan(Math.tan(r)*b),S);let m;if(t==="top"){const a=o.x*.5/(Math.tan(d)*s),l=o.z*.5/(Math.tan(r)*s);m=Math.max(a,l)}else if(t==="right"||t==="left"){const a=o.y*.5/(Math.tan(r)*s),l=o.z*.5/(Math.tan(r)*s);m=Math.max(a,l)}else{const a=o.x*.5/(Math.tan(d)*s),l=o.y*.5/(Math.tan(r)*s),f=o.z*.5/(Math.tan(r)*s);m=Math.max(a,l,f)}const u=R.clone().multiplyScalar(m).add(c);if(F&&(console.log("📍 相机位置验证:"),console.log(" - 方向向量:",R),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))),F?(this.boxHelper&&(this.scene.remove(this.boxHelper),this.boxHelper=null),this.boxHelper=new n.Box3Helper(g,y),this.scene.add(this.boxHelper)):this.boxHelper&&(this.scene.remove(this.boxHelper),this.boxHelper=null),w){const a=this.camera.position.clone(),l=this.control?this.control.target.clone():new n.Vector3(0,0,0),f=c,V=Date.now(),v=()=>{const D=Date.now()-V,L=Math.min(D/z,1),O=1-Math.pow(1-L,3);if(this.camera.position.lerpVectors(a,u,O),this.control){const M=new n.Vector3;M.lerpVectors(l,f,O),this.control.target.copy(M),this.camera.lookAt(M)}else this.camera.lookAt(c);this.camera.updateProjectionMatrix(),L<1?requestAnimationFrame(v):(this.camera.position.copy(u),this.camera.lookAt(c),this.camera.updateProjectionMatrix(),this.control&&(this.control.target.copy(c),this.control.update()),this.onRender())};v()}else this.camera.position.copy(u),this.camera.lookAt(c),this.camera.updateProjectionMatrix(),this.control&&(this.control.target.copy(c),this.control.update()),this.onRender();if(F){if(console.log("🎥 视角切换信息:"),console.log(" - 视角类型:",t),console.log(" - 相机位置:",u),console.log(" - 观察目标:",c),console.log(" - 方向向量:",R),console.log(" - 包围盒尺寸:",o),console.log(" - 包围盒中心:",g.getCenter(new n.Vector3)),console.log(" - 水平 FOV:",n.MathUtils.radToDeg(d*2).toFixed(2)+"°"),console.log(" - 垂直 FOV:",n.MathUtils.radToDeg(r*2).toFixed(2)+"°"),console.log(" - 宽高比:",b.toFixed(4)),console.log(" - 模型宽度:",o.x.toFixed(2)),console.log(" - 模型高度:",o.y.toFixed(2)),console.log(" - 模型深度:",o.z.toFixed(2)),console.log(" - 传入的 scale 参数:",s),t==="top"){const a=o.x*.5/(Math.tan(d)*s),l=o.z*.5/(Math.tan(r)*s);console.log(" - 模型 X 尺寸 (宽度):",o.x.toFixed(2)),console.log(" - 模型 Z 尺寸 (深度):",o.z.toFixed(2)),console.log(" - tan(halfFovX):",Math.tan(d).toFixed(4)),console.log(" - tan(halfFovY):",Math.tan(r).toFixed(4)),console.log(" - X方向距离计算: (",(o.x*.5).toFixed(2),") / (",Math.tan(d).toFixed(4)," *",s,") =",a.toFixed(2)),console.log(" - Z方向距离计算: (",(o.z*.5).toFixed(2),") / (",Math.tan(r).toFixed(4)," *",s,") =",l.toFixed(2)),console.log(" - X方向距离 (scale="+s+"):",a.toFixed(2)),console.log(" - Z方向距离 (scale="+s+"):",l.toFixed(2))}else if(t==="right"||t==="left"){const a=o.y*.5/(Math.tan(r)*s),l=o.z*.5/(Math.tan(r)*s);console.log(" - Y方向距离 (scale="+s+"):",a.toFixed(2)),console.log(" - Z方向距离 (scale="+s+"):",l.toFixed(2))}else{const a=o.x*.5/(Math.tan(d)*s),l=o.y*.5/(Math.tan(r)*s),f=o.z*.5/(Math.tan(r)*s);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(d).toFixed(4)),console.log(" - tan(halfFovY):",Math.tan(r).toFixed(4)),console.log(" - X方向距离计算: (",(o.x*.5).toFixed(2),") / (",Math.tan(d).toFixed(4)," *",s,") =",a.toFixed(2)),console.log(" - Y方向距离计算: (",(o.y*.5).toFixed(2),") / (",Math.tan(r).toFixed(4)," *",s,") =",l.toFixed(2)),console.log(" - Z方向距离计算: (",(o.z*.5).toFixed(2),") / (",Math.tan(r).toFixed(4)," *",s,") =",f.toFixed(2)),console.log(" - X方向距离 (scale="+s+"):",a.toFixed(2)),console.log(" - Y方向距离 (scale="+s+"):",l.toFixed(2)),console.log(" - Z方向距离 (scale="+s+"):",f.toFixed(2)),console.log(" - 最大距离 (Max):",Math.max(a,l,f).toFixed(2))}console.log(" - 最终距离:",m.toFixed(2)),console.log(" - 缩放比例:",s),console.log(" - 动画:",w?"是 ("+z+"ms)":"否")}return{position:u,target:c,distance:m,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 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=Y.version,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 H,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[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&&(X.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(C,"ViewType",E);exports.ThreeIns=C;exports.ViewType=E;