bc-model-viewer 1.7.18 → 1.7.20

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.
@@ -60,6 +60,15 @@
60
60
 
61
61
  import { Viewer } from '../../index.ts'
62
62
 
63
+ // 尝试导入样式配置,如果失败则使用空对象
64
+ let styles = null;
65
+ try {
66
+ const styleModule = await import('../../src/options/style.ts');
67
+ styles = styleModule.default;
68
+ } catch (error) {
69
+ console.warn('无法导入样式配置,将从 viewer 中获取:', error);
70
+ }
71
+
63
72
  const container = document.getElementById('container')
64
73
 
65
74
  // 实例化 Viewer 对象
@@ -78,11 +87,73 @@
78
87
  // 获取样式管理器实例
79
88
  const { styleManager } = viewer;
80
89
 
90
+ /**
91
+ * 更新页面上的参数输入框
92
+ * @param {Object} styleConfig 样式配置对象
93
+ */
94
+ function updateInputsFromStyle(styleConfig) {
95
+ if (!styleConfig) return;
96
+
97
+ const { background, edge } = styleConfig;
98
+
99
+ // 更新背景颜色输入框
100
+ if (background) {
101
+ // 更新纯色背景
102
+ const solidColorInput = document.getElementById('solidColor');
103
+ if (solidColorInput && background.color) {
104
+ solidColorInput.value = background.color;
105
+ }
106
+
107
+ // 更新渐变背景
108
+ const topColorInput = document.getElementById('topColor');
109
+ const middleColorInput = document.getElementById('middleColor');
110
+ const bottomColorInput = document.getElementById('bottomColor');
111
+
112
+ if (topColorInput && background.color) {
113
+ topColorInput.value = background.color;
114
+ }
115
+ if (middleColorInput && background.middleColor) {
116
+ middleColorInput.value = background.middleColor;
117
+ } else if (middleColorInput && background.color) {
118
+ // 如果没有中间色,使用基础色
119
+ middleColorInput.value = background.color;
120
+ }
121
+ if (bottomColorInput && background.gradientColor) {
122
+ bottomColorInput.value = background.gradientColor;
123
+ } else if (bottomColorInput && background.color) {
124
+ // 如果没有渐变色,使用基础色
125
+ bottomColorInput.value = background.color;
126
+ }
127
+ }
128
+
129
+ // 更新边缘颜色输入框
130
+ if (edge && edge.color) {
131
+ const edgeColorInput = document.getElementById('edgeColor');
132
+ if (edgeColorInput) {
133
+ edgeColorInput.value = edge.color;
134
+ }
135
+ }
136
+ }
137
+
81
138
  // 切换到预设样式
82
139
  function changeToPresetStyle(styleIndex) {
83
140
  console.log(`切换到预设样式 ${styleIndex}`);
141
+
142
+ // 优先使用导入的原始样式配置(更准确),如果不存在则使用回调中的 style
143
+ let styleConfig = null;
144
+ if (styles && styles[styleIndex]) {
145
+ styleConfig = styles[styleIndex];
146
+ }
147
+
148
+ // 切换样式
84
149
  styleManager.changeStyle(styleIndex, (style) => {
85
150
  console.log('样式应用成功:', style);
151
+
152
+ // 如果原始样式配置不存在,使用合并后的样式配置
153
+ const configToUse = styleConfig || style;
154
+
155
+ // 更新页面上的输入框
156
+ updateInputsFromStyle(configToUse);
86
157
  });
87
158
  }
88
159
 
@@ -125,23 +196,23 @@
125
196
  window.setSolidBackground = setSolidBackground;
126
197
  window.setGradientBackground = setGradientBackground;
127
198
  window.setEdgeColor = setEdgeColor;
128
-
199
+
129
200
  // 边线控制方法
130
201
  function toggleEdgeVisibility() {
131
202
  console.log('切换边线显隐状态');
132
203
  styleManager.toggleEdgeVisibility();
133
204
  }
134
-
205
+
135
206
  function showEdge() {
136
207
  console.log('显示边线');
137
208
  styleManager.showEdge();
138
209
  }
139
-
210
+
140
211
  function hideEdge() {
141
212
  console.log('隐藏边线');
142
213
  styleManager.hideEdge();
143
214
  }
144
-
215
+
145
216
  // 暴露边线控制方法到全局
146
217
  window.toggleEdgeVisibility = toggleEdgeVisibility;
147
218
  window.showEdge = showEdge;
@@ -13,21 +13,19 @@
13
13
  <a href="index.html" class="back-button">返回示例列表</a>
14
14
  <div class="demo">
15
15
  <h2>💥 模型爆炸图演示</h2>
16
- <p>通过调整爆炸强度来分离和展示模型的不同部件,便于查看内部结构。</p>
16
+ <p>通过调整爆炸强度来分离和展示模型的不同部件,便于查看内部结构。工具自带拖动条控制强度。</p>
17
+
18
+ <!-- 工具控制按钮 -->
17
19
  <div class="control-group">
18
- <button onclick="viewer.explosion.applyExplosion(10)">爆炸</button>
19
- <button onclick="viewer.explosion.resetExplosion()" id="resetBtn" class="secondary">复位</button>
20
- </div>
21
- <div class="control-group">
22
- <label for="intensity">爆炸强度: <span id="intensityValue">0</span></label>
23
- <input type="range" id="intensity" step="0.1" min="0" value="0" title="爆炸强度">
20
+ <button onclick="tool.activate()">激活工具</button>
21
+ <button onclick="tool.deactivate()">停用工具</button>
22
+ <button onclick="tool.toggle()">切换状态</button>
24
23
  </div>
25
24
  </div>
26
25
 
27
26
  <script type="module">
28
27
 
29
28
  import { Viewer } from '../../index.ts'
30
- import * as THREE from 'three'
31
29
 
32
30
  const container = document.getElementById('container')
33
31
 
@@ -37,41 +35,21 @@
37
35
  cache: {
38
36
  enabled: false
39
37
  }
40
- },
41
- style: {
42
- type: 1,
43
- axes: {
44
- // display: true,
45
- }
46
38
  }
47
39
  })
48
40
 
49
41
  // 加载测试模型
50
- // await viewer.loadZipAsync('../../assets/dgz/建筑.dgz')
51
- // await viewer.loadZipAsync('../../assets/dgz/机电综合.dgz')
52
42
  await viewer.loadZipAsync('../../assets/new.dgz')
53
- // await viewer.loadZipAsync('../../assets/new2.dgz')
54
- // await viewer.loadZipAsync('../../assets/new3.dgz')
55
-
56
- viewer.initExplosion()
57
43
 
58
- const intensity = document.getElementById('intensity');
44
+ // 获取工具实例
45
+ const tool = viewer.explosionTool;
59
46
 
60
- intensity.max = viewer.explosion.getMaxIntensity();
61
- intensity.step = viewer.explosion.getStep();
47
+ // 激活工具
48
+ tool.activate();
62
49
 
63
-
64
- // 实时调整爆炸强度
65
- const intensityValue = document.getElementById('intensityValue');
66
- intensity.addEventListener('input', (e) => {
67
- const value = parseFloat(e.target.value);
68
- intensityValue.textContent = value.toFixed(1);
69
- viewer.setEdgeVisible(false)
70
- viewer.explosion.applyExplosion(value);
71
- });
72
-
73
- window.v = viewer
50
+ window.tool = tool
74
51
  window.viewer = viewer
52
+ window.v = viewer
75
53
  </script>
76
54
 
77
55
  </body>
@@ -13,19 +13,19 @@
13
13
  <a href="index.html" class="back-button">返回示例列表</a>
14
14
  <div class="demo">
15
15
  <h2>✂️ 模型剖切工具演示</h2>
16
- <p>对模型进行切片查看。支持多个剖切面,可以从不同角度查看模型内部结构。</p>
16
+ <p>通过点击模型表面创建剖切平面,工具会自动显示控制面板,包含拖动条控制剖切程度等信息。支持多个剖切面,可以从不同角度查看模型内部结构。</p>
17
+
18
+ <!-- 工具控制按钮 -->
17
19
  <div class="control-group">
18
- <button onclick="viewer.clipper.activate()">激活工具</button>
19
- <button onclick="viewer.clipper.deactivate()">停用工具</button>
20
- </div>
21
- <div class="control-group">
22
- <button onclick="viewer.clipper.clear()" class="danger">移除所有剖切面</button>
20
+ <button onclick="tool.activate()">激活工具</button>
21
+ <button onclick="tool.deactivate()">停用工具</button>
22
+ <button onclick="tool.toggle()">切换状态</button>
23
23
  </div>
24
24
  </div>
25
25
 
26
26
  <script type="module">
27
27
 
28
- import { Viewer, HUDLabelTool, ModelClipperTool } from '../../index.ts'
28
+ import { Viewer } from '../../index.ts'
29
29
 
30
30
  const container = document.getElementById('container')
31
31
 
@@ -51,9 +51,15 @@
51
51
  await viewer.loadZipAsync('./dgz/样板间.dgz')
52
52
  // await viewer.loadZipAsync('../../../assets/dgz/机电综合.dgz')
53
53
 
54
- viewer.clipper.activate()
54
+ // 获取工具实例
55
+ const tool = viewer.clipper;
56
+
57
+ // 激活工具
58
+ tool.activate();
55
59
 
60
+ window.tool = tool
56
61
  window.viewer = viewer
62
+ window.v = viewer
57
63
  </script>
58
64
 
59
65
  </body>
@@ -0,0 +1,310 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>相机切换演示 - Bc-model-viewer</title>
8
+ <link rel="stylesheet" href="common-styles.css">
9
+ <style>
10
+ .camera-info {
11
+ margin-top: 15px;
12
+ padding: 12px;
13
+ background: rgba(102, 126, 234, 0.1);
14
+ border-radius: 6px;
15
+ border-left: 3px solid #667eea;
16
+ }
17
+
18
+ .camera-info-label {
19
+ font-size: 12px;
20
+ color: #666;
21
+ margin-bottom: 4px;
22
+ }
23
+
24
+ .camera-info-value {
25
+ font-size: 16px;
26
+ font-weight: 600;
27
+ color: #667eea;
28
+ }
29
+
30
+ .camera-params {
31
+ margin-top: 15px;
32
+ padding: 12px;
33
+ background: rgba(255, 255, 255, 0.05);
34
+ border-radius: 6px;
35
+ border: 1px solid rgba(255, 255, 255, 0.1);
36
+ }
37
+
38
+ .camera-param-group {
39
+ margin-bottom: 12px;
40
+ }
41
+
42
+ .camera-param-group:last-child {
43
+ margin-bottom: 0;
44
+ }
45
+
46
+ .camera-param-label {
47
+ display: flex;
48
+ justify-content: space-between;
49
+ align-items: center;
50
+ margin-bottom: 6px;
51
+ font-size: 12px;
52
+ color: rgba(255, 255, 255, 0.8);
53
+ }
54
+
55
+ .camera-param-value {
56
+ color: #4CAF50;
57
+ font-weight: 600;
58
+ font-size: 13px;
59
+ }
60
+
61
+ .camera-param-input {
62
+ width: 100%;
63
+ height: 6px;
64
+ border-radius: 3px;
65
+ background: rgba(255, 255, 255, 0.2);
66
+ outline: none;
67
+ -webkit-appearance: none;
68
+ appearance: none;
69
+ }
70
+
71
+ .camera-param-input::-webkit-slider-thumb {
72
+ -webkit-appearance: none;
73
+ appearance: none;
74
+ width: 16px;
75
+ height: 16px;
76
+ border-radius: 50%;
77
+ background: #4CAF50;
78
+ cursor: pointer;
79
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
80
+ transition: background 0.2s;
81
+ }
82
+
83
+ .camera-param-input::-webkit-slider-thumb:hover {
84
+ background: #45a049;
85
+ }
86
+
87
+ .camera-param-input::-moz-range-thumb {
88
+ width: 16px;
89
+ height: 16px;
90
+ border-radius: 50%;
91
+ background: #4CAF50;
92
+ cursor: pointer;
93
+ border: none;
94
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
95
+ transition: background 0.2s;
96
+ }
97
+
98
+ .camera-param-input::-moz-range-thumb:hover {
99
+ background: #45a049;
100
+ }
101
+
102
+ .camera-type-badge {
103
+ display: inline-block;
104
+ padding: 4px 10px;
105
+ border-radius: 12px;
106
+ font-size: 12px;
107
+ font-weight: 600;
108
+ text-transform: uppercase;
109
+ }
110
+
111
+ .camera-type-perspective {
112
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
113
+ color: white;
114
+ }
115
+
116
+ .camera-type-orthographic {
117
+ background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
118
+ color: white;
119
+ }
120
+
121
+ .info-text {
122
+ font-size: 12px;
123
+ color: rgba(255, 255, 255, 0.6);
124
+ line-height: 1.6;
125
+ margin-top: 10px;
126
+ }
127
+ </style>
128
+ </head>
129
+
130
+ <body>
131
+ <div id="container"></div>
132
+ <a href="index.html" class="back-button">返回示例列表</a>
133
+ <div class="demo">
134
+ <h2>📷 相机切换演示</h2>
135
+ <p>在透视相机和正交相机之间切换,体验不同的视图效果。</p>
136
+
137
+ <div class="control-group">
138
+ <button onclick="switchToPerspective()">切换到透视相机</button>
139
+ <button onclick="switchToOrthographic()" class="secondary">切换到正交相机</button>
140
+ </div>
141
+
142
+ <div class="camera-info">
143
+ <div class="camera-info-label">当前相机类型</div>
144
+ <div class="camera-info-value" id="cameraType">透视相机</div>
145
+ </div>
146
+
147
+ <div class="camera-params" id="cameraParams">
148
+ <!-- 动态生成的相机参数控制 -->
149
+ </div>
150
+
151
+ <div class="info-text">
152
+ <strong>透视相机:</strong>模拟人眼视角,近大远小,适合查看整体场景。<br>
153
+ <strong>正交相机:</strong>无透视变形,平行投影,适合查看精确尺寸。
154
+ </div>
155
+ </div>
156
+
157
+ <script type="module">
158
+
159
+ import { Viewer } from '../../index.ts'
160
+
161
+ const container = document.getElementById('container')
162
+
163
+ // 实例化 Viewer 对象
164
+ const viewer = new Viewer(container, {
165
+ style: {
166
+ type: 1
167
+ },
168
+ load: {
169
+ cache: {
170
+ enabled: false,
171
+ }
172
+ },
173
+ gui: {
174
+ enabled: true
175
+ }
176
+ })
177
+
178
+ // 加载测试模型
179
+ try {
180
+ await viewer.loadZipAsync('./dgz/样板间.dgz')
181
+ console.log('模型加载成功')
182
+ } catch (error) {
183
+ console.error('模型加载失败:', error)
184
+ alert('无法加载测试模型,请确保模型文件存在')
185
+ }
186
+
187
+ // 更新相机信息显示
188
+ function updateCameraInfo() {
189
+ const isPerspective = viewer.isPerspective();
190
+ const cameraTypeElement = document.getElementById('cameraType');
191
+ const cameraParamsElement = document.getElementById('cameraParams');
192
+
193
+ if (cameraTypeElement) {
194
+ if (isPerspective) {
195
+ cameraTypeElement.innerHTML = '<span class="camera-type-badge camera-type-perspective">透视相机</span>';
196
+ } else {
197
+ cameraTypeElement.innerHTML = '<span class="camera-type-badge camera-type-orthographic">正交相机</span>';
198
+ }
199
+ }
200
+
201
+ // 更新相机参数控制
202
+ if (cameraParamsElement) {
203
+ if (isPerspective) {
204
+ const fov = viewer.camera.fov || 45;
205
+ cameraParamsElement.innerHTML = `
206
+ <div class="camera-param-group">
207
+ <div class="camera-param-label">
208
+ <span>视野角度 (FOV)</span>
209
+ <span class="camera-param-value" id="fovValue">${fov}°</span>
210
+ </div>
211
+ <input
212
+ type="range"
213
+ class="camera-param-input"
214
+ min="10"
215
+ max="120"
216
+ step="1"
217
+ value="${fov}"
218
+ oninput="updateFOV(this.value)"
219
+ />
220
+ </div>
221
+ `;
222
+ } else {
223
+ // 计算当前 viewSize(基于 orthographicCamera 的 zoom)
224
+ const orthoCamera = viewer.orthographicCamera;
225
+ const zoom = orthoCamera ? orthoCamera.zoom : 1;
226
+ // 估算 viewSize(实际值需要根据 boxSize 计算)
227
+ const estimatedViewSize = 10 / zoom;
228
+
229
+ cameraParamsElement.innerHTML = `
230
+ <div class="camera-param-group">
231
+ <div class="camera-param-label">
232
+ <span>视图大小 (View Size)</span>
233
+ <span class="camera-param-value" id="viewSizeValue">${estimatedViewSize.toFixed(1)}</span>
234
+ </div>
235
+ <input
236
+ type="range"
237
+ class="camera-param-input"
238
+ min="1"
239
+ max="50"
240
+ step="0.5"
241
+ value="${estimatedViewSize}"
242
+ oninput="updateViewSize(this.value)"
243
+ />
244
+ </div>
245
+ `;
246
+ }
247
+ }
248
+ }
249
+
250
+ // 切换到透视相机
251
+ function switchToPerspective() {
252
+ viewer.toggleCamera('perspective');
253
+ updateCameraInfo();
254
+ console.log('已切换到透视相机');
255
+ }
256
+
257
+ // 切换到正交相机
258
+ function switchToOrthographic() {
259
+ viewer.toggleCamera('orthographic');
260
+ updateCameraInfo();
261
+ console.log('已切换到正交相机');
262
+ }
263
+
264
+ // 更新 FOV(仅透视相机)
265
+ function updateFOV(value) {
266
+ if (!viewer.isPerspective()) return;
267
+
268
+ const fov = parseFloat(value);
269
+ viewer.camera.fov = fov;
270
+ viewer.camera.updateProjectionMatrix();
271
+
272
+ const fovValueElement = document.getElementById('fovValue');
273
+ if (fovValueElement) {
274
+ fovValueElement.textContent = `${fov}°`;
275
+ }
276
+ }
277
+
278
+ // 更新 ViewSize(仅正交相机)
279
+ function updateViewSize(value) {
280
+ if (viewer.isPerspective()) return;
281
+
282
+ const viewSize = parseFloat(value);
283
+ viewer.updateOrthographicCamera(viewSize);
284
+
285
+ const viewSizeValueElement = document.getElementById('viewSizeValue');
286
+ if (viewSizeValueElement) {
287
+ viewSizeValueElement.textContent = viewSize.toFixed(1);
288
+ }
289
+ }
290
+
291
+ // 暴露函数到全局
292
+ window.viewer = viewer;
293
+ window.switchToPerspective = switchToPerspective;
294
+ window.switchToOrthographic = switchToOrthographic;
295
+ window.updateFOV = updateFOV;
296
+ window.updateViewSize = updateViewSize;
297
+
298
+ // 初始更新一次
299
+ updateCameraInfo();
300
+
301
+ // 监听窗口大小变化,更新相机信息
302
+ window.addEventListener('resize', () => {
303
+ setTimeout(updateCameraInfo, 100);
304
+ });
305
+ </script>
306
+
307
+ </body>
308
+
309
+ </html>
310
+
@@ -280,7 +280,7 @@
280
280
  <body>
281
281
  <div class="container">
282
282
  <header>
283
- <h1>🚀 Bc-model-viewer</h1>
283
+ <h1>🚀 model-viewer</h1>
284
284
  <p>3D 模型查看器示例导航</p>
285
285
  </header>
286
286
 
@@ -423,6 +423,17 @@
423
423
  <a href="PositionCameraTool.html" class="link-button">查看示例 →</a>
424
424
  </div>
425
425
 
426
+ <div class="example-card" data-name="相机切换" data-desc="透视正交切换">
427
+ <h3><span class="icon">📷</span>相机切换</h3>
428
+ <div class="description">演示在透视相机和正交相机之间切换。透视相机模拟人眼视角,正交相机无透视变形,适合查看精确尺寸。</div>
429
+ <div class="tags">
430
+ <span class="tag tag-tool">相机工具</span>
431
+ <span class="tag tag-feature">透视相机</span>
432
+ <span class="tag tag-feature">正交相机</span>
433
+ </div>
434
+ <a href="ToggleCamera.html" class="link-button">查看示例 →</a>
435
+ </div>
436
+
426
437
  <div class="example-card" data-name="框选放大" data-desc="选择缩放">
427
438
  <h3><span class="icon">🔍</span>框选放大工具</h3>
428
439
  <div class="description">演示如何使用框选工具来放大查看模型的特定区域。框选范围越小,放大倍数越大,适合查看细节。</div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bc-model-viewer",
3
- "version": "1.7.18",
3
+ "version": "1.7.20",
4
4
  "main": "./dist/bc-model-viewer.min.js",
5
5
  "module": "./dist/bc-model-viewer.min.js",
6
6
  "description": "A model viewer",