bc-model-viewer 1.7.19 → 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.
|
@@ -13,33 +13,19 @@
|
|
|
13
13
|
<a href="index.html" class="back-button">返回示例列表</a>
|
|
14
14
|
<div class="demo">
|
|
15
15
|
<h2>💥 模型爆炸图演示</h2>
|
|
16
|
-
<p
|
|
16
|
+
<p>通过调整爆炸强度来分离和展示模型的不同部件,便于查看内部结构。工具自带拖动条控制强度。</p>
|
|
17
17
|
|
|
18
|
-
<!--
|
|
18
|
+
<!-- 工具控制按钮 -->
|
|
19
19
|
<div class="control-group">
|
|
20
|
-
<
|
|
21
|
-
<button onclick="
|
|
22
|
-
<button onclick="
|
|
23
|
-
<button onclick="viewer.explosion.setPreset('large')">大爆炸 (75%)</button>
|
|
24
|
-
<button onclick="viewer.explosion.setPreset('max')">最大 (100%)</button>
|
|
25
|
-
</div>
|
|
26
|
-
|
|
27
|
-
<!-- 基础控制 -->
|
|
28
|
-
<div class="control-group">
|
|
29
|
-
<button onclick="viewer.explosion.resetExplosion()" id="resetBtn" class="secondary">复位</button>
|
|
30
|
-
</div>
|
|
31
|
-
|
|
32
|
-
<!-- 滑块控制 -->
|
|
33
|
-
<div class="control-group">
|
|
34
|
-
<label for="intensity">爆炸强度: <span id="intensityValue">0</span></label>
|
|
35
|
-
<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>
|
|
36
23
|
</div>
|
|
37
24
|
</div>
|
|
38
25
|
|
|
39
26
|
<script type="module">
|
|
40
27
|
|
|
41
28
|
import { Viewer } from '../../index.ts'
|
|
42
|
-
import * as THREE from 'three'
|
|
43
29
|
|
|
44
30
|
const container = document.getElementById('container')
|
|
45
31
|
|
|
@@ -55,45 +41,15 @@
|
|
|
55
41
|
// 加载测试模型
|
|
56
42
|
await viewer.loadZipAsync('../../assets/new.dgz')
|
|
57
43
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const intensity = document.getElementById('intensity');
|
|
44
|
+
// 获取工具实例
|
|
45
|
+
const tool = viewer.explosionTool;
|
|
61
46
|
|
|
62
|
-
|
|
63
|
-
|
|
47
|
+
// 激活工具
|
|
48
|
+
tool.activate();
|
|
64
49
|
|
|
65
|
-
|
|
66
|
-
// 实时调整爆炸强度
|
|
67
|
-
const intensityValue = document.getElementById('intensityValue');
|
|
68
|
-
intensity.addEventListener('input', (e) => {
|
|
69
|
-
const value = parseFloat(e.target.value);
|
|
70
|
-
intensityValue.textContent = value.toFixed(1);
|
|
71
|
-
viewer.explosion.applyExplosion(value);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
// 更新滑块值(当使用预设时)
|
|
75
|
-
const updateSlider = () => {
|
|
76
|
-
const currentIntensity = viewer.explosion.getCurrentIntensity();
|
|
77
|
-
intensity.value = currentIntensity;
|
|
78
|
-
intensityValue.textContent = currentIntensity.toFixed(1);
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
// 重写预设方法以更新滑块
|
|
82
|
-
const originalSetPreset = viewer.explosion.setPreset.bind(viewer.explosion);
|
|
83
|
-
viewer.explosion.setPreset = function(presetName) {
|
|
84
|
-
originalSetPreset(presetName);
|
|
85
|
-
updateSlider();
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
// 重写复位方法以更新滑块
|
|
89
|
-
const originalReset = viewer.explosion.resetExplosion.bind(viewer.explosion);
|
|
90
|
-
viewer.explosion.resetExplosion = function() {
|
|
91
|
-
originalReset();
|
|
92
|
-
updateSlider();
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
window.v = viewer
|
|
50
|
+
window.tool = tool
|
|
96
51
|
window.viewer = viewer
|
|
52
|
+
window.v = viewer
|
|
97
53
|
</script>
|
|
98
54
|
|
|
99
55
|
</body>
|
|
@@ -6,122 +6,6 @@
|
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>模型剖切工具演示 - Bc-model-viewer</title>
|
|
8
8
|
<link rel="stylesheet" href="common-styles.css">
|
|
9
|
-
<style>
|
|
10
|
-
.clipper-controls {
|
|
11
|
-
margin-top: 20px;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
.plane-control {
|
|
15
|
-
margin-bottom: 15px;
|
|
16
|
-
padding: 12px;
|
|
17
|
-
background: rgba(255, 255, 255, 0.05);
|
|
18
|
-
border-radius: 6px;
|
|
19
|
-
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.plane-control-header {
|
|
23
|
-
display: flex;
|
|
24
|
-
justify-content: space-between;
|
|
25
|
-
align-items: center;
|
|
26
|
-
margin-bottom: 8px;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
.plane-control-label {
|
|
30
|
-
font-weight: 500;
|
|
31
|
-
color: #fff;
|
|
32
|
-
font-size: 14px;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
.plane-control-value {
|
|
36
|
-
color: #4CAF50;
|
|
37
|
-
font-size: 13px;
|
|
38
|
-
font-weight: 600;
|
|
39
|
-
min-width: 50px;
|
|
40
|
-
text-align: right;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.plane-control-slider {
|
|
44
|
-
width: 100%;
|
|
45
|
-
height: 6px;
|
|
46
|
-
border-radius: 3px;
|
|
47
|
-
background: rgba(255, 255, 255, 0.2);
|
|
48
|
-
outline: none;
|
|
49
|
-
-webkit-appearance: none;
|
|
50
|
-
appearance: none;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
.plane-control-slider::-webkit-slider-thumb {
|
|
54
|
-
-webkit-appearance: none;
|
|
55
|
-
appearance: none;
|
|
56
|
-
width: 18px;
|
|
57
|
-
height: 18px;
|
|
58
|
-
border-radius: 50%;
|
|
59
|
-
background: #4CAF50;
|
|
60
|
-
cursor: pointer;
|
|
61
|
-
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
|
62
|
-
transition: background 0.2s;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
.plane-control-slider::-webkit-slider-thumb:hover {
|
|
66
|
-
background: #45a049;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.plane-control-slider::-moz-range-thumb {
|
|
70
|
-
width: 18px;
|
|
71
|
-
height: 18px;
|
|
72
|
-
border-radius: 50%;
|
|
73
|
-
background: #4CAF50;
|
|
74
|
-
cursor: pointer;
|
|
75
|
-
border: none;
|
|
76
|
-
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
|
77
|
-
transition: background 0.2s;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.plane-control-slider::-moz-range-thumb:hover {
|
|
81
|
-
background: #45a049;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
.plane-control-actions {
|
|
85
|
-
display: flex;
|
|
86
|
-
gap: 8px;
|
|
87
|
-
margin-top: 8px;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
.plane-control-actions button {
|
|
91
|
-
flex: 1;
|
|
92
|
-
padding: 6px 12px;
|
|
93
|
-
font-size: 12px;
|
|
94
|
-
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
95
|
-
background: rgba(255, 255, 255, 0.1);
|
|
96
|
-
color: #fff;
|
|
97
|
-
border-radius: 4px;
|
|
98
|
-
cursor: pointer;
|
|
99
|
-
transition: all 0.2s;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
.plane-control-actions button:hover {
|
|
103
|
-
background: rgba(255, 255, 255, 0.2);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
.plane-control-actions button.danger {
|
|
107
|
-
background: rgba(244, 67, 54, 0.2);
|
|
108
|
-
border-color: rgba(244, 67, 54, 0.4);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
.plane-control-actions button.danger:hover {
|
|
112
|
-
background: rgba(244, 67, 54, 0.3);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
.no-planes-message {
|
|
116
|
-
padding: 20px;
|
|
117
|
-
text-align: center;
|
|
118
|
-
color: rgba(255, 255, 255, 0.6);
|
|
119
|
-
font-size: 14px;
|
|
120
|
-
background: rgba(255, 255, 255, 0.05);
|
|
121
|
-
border-radius: 6px;
|
|
122
|
-
border: 1px dashed rgba(255, 255, 255, 0.2);
|
|
123
|
-
}
|
|
124
|
-
</style>
|
|
125
9
|
</head>
|
|
126
10
|
|
|
127
11
|
<body>
|
|
@@ -129,27 +13,19 @@
|
|
|
129
13
|
<a href="index.html" class="back-button">返回示例列表</a>
|
|
130
14
|
<div class="demo">
|
|
131
15
|
<h2>✂️ 模型剖切工具演示</h2>
|
|
132
|
-
<p
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
<button onclick="activateClipper()">激活工具</button>
|
|
136
|
-
<button onclick="deactivateClipper()">停用工具</button>
|
|
137
|
-
</div>
|
|
138
|
-
|
|
16
|
+
<p>通过点击模型表面创建剖切平面,工具会自动显示控制面板,包含拖动条控制剖切程度等信息。支持多个剖切面,可以从不同角度查看模型内部结构。</p>
|
|
17
|
+
|
|
18
|
+
<!-- 工具控制按钮 -->
|
|
139
19
|
<div class="control-group">
|
|
140
|
-
<button onclick="
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
<div class="clipper-controls" id="clipperControls">
|
|
144
|
-
<div class="no-planes-message">
|
|
145
|
-
点击模型表面创建剖切平面,然后使用拖动条调整剖切位置
|
|
146
|
-
</div>
|
|
20
|
+
<button onclick="tool.activate()">激活工具</button>
|
|
21
|
+
<button onclick="tool.deactivate()">停用工具</button>
|
|
22
|
+
<button onclick="tool.toggle()">切换状态</button>
|
|
147
23
|
</div>
|
|
148
24
|
</div>
|
|
149
25
|
|
|
150
26
|
<script type="module">
|
|
151
27
|
|
|
152
|
-
import { Viewer
|
|
28
|
+
import { Viewer } from '../../index.ts'
|
|
153
29
|
|
|
154
30
|
const container = document.getElementById('container')
|
|
155
31
|
|
|
@@ -175,153 +51,15 @@
|
|
|
175
51
|
await viewer.loadZipAsync('./dgz/样板间.dgz')
|
|
176
52
|
// await viewer.loadZipAsync('../../../assets/dgz/机电综合.dgz')
|
|
177
53
|
|
|
178
|
-
//
|
|
179
|
-
|
|
180
|
-
const controlsContainer = document.getElementById('clipperControls');
|
|
181
|
-
const clipper = viewer.clipper;
|
|
182
|
-
|
|
183
|
-
if (!clipper || clipper.clippingPlanes.length === 0) {
|
|
184
|
-
controlsContainer.innerHTML = `
|
|
185
|
-
<div class="no-planes-message">
|
|
186
|
-
点击模型表面创建剖切平面,然后使用拖动条调整剖切位置
|
|
187
|
-
</div>
|
|
188
|
-
`;
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
let html = '';
|
|
193
|
-
clipper.clippingPlanes.forEach((plane, index) => {
|
|
194
|
-
const position = clipper.getPlanePositionByIndex(index);
|
|
195
|
-
const percentage = Math.round(position * 100);
|
|
196
|
-
|
|
197
|
-
html += `
|
|
198
|
-
<div class="plane-control" data-index="${index}">
|
|
199
|
-
<div class="plane-control-header">
|
|
200
|
-
<span class="plane-control-label">剖切面 #${index + 1}</span>
|
|
201
|
-
<span class="plane-control-value">${percentage}%</span>
|
|
202
|
-
</div>
|
|
203
|
-
<input
|
|
204
|
-
type="range"
|
|
205
|
-
class="plane-control-slider"
|
|
206
|
-
min="0"
|
|
207
|
-
max="1"
|
|
208
|
-
step="0.01"
|
|
209
|
-
value="${position}"
|
|
210
|
-
data-index="${index}"
|
|
211
|
-
oninput="updatePlanePosition(${index}, this.value)"
|
|
212
|
-
/>
|
|
213
|
-
<div class="plane-control-actions">
|
|
214
|
-
<button onclick="resetPlanePosition(${index})">重置</button>
|
|
215
|
-
<button onclick="removePlane(${index})" class="danger">删除</button>
|
|
216
|
-
</div>
|
|
217
|
-
</div>
|
|
218
|
-
`;
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
controlsContainer.innerHTML = html;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// 更新剖切平面位置
|
|
225
|
-
function updatePlanePosition(index, value) {
|
|
226
|
-
const clipper = viewer.clipper;
|
|
227
|
-
if (!clipper) return;
|
|
228
|
-
|
|
229
|
-
clipper.setPlanePositionByIndex(index, parseFloat(value));
|
|
230
|
-
|
|
231
|
-
// 更新显示的值
|
|
232
|
-
const control = document.querySelector(`.plane-control[data-index="${index}"]`);
|
|
233
|
-
if (control) {
|
|
234
|
-
const valueDisplay = control.querySelector('.plane-control-value');
|
|
235
|
-
if (valueDisplay) {
|
|
236
|
-
const percentage = Math.round(parseFloat(value) * 100);
|
|
237
|
-
valueDisplay.textContent = `${percentage}%`;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// 重置剖切平面位置到中间
|
|
243
|
-
function resetPlanePosition(index) {
|
|
244
|
-
updatePlanePosition(index, 0.5);
|
|
245
|
-
const slider = document.querySelector(`.plane-control-slider[data-index="${index}"]`);
|
|
246
|
-
if (slider) {
|
|
247
|
-
slider.value = 0.5;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// 删除剖切平面
|
|
252
|
-
function removePlane(index) {
|
|
253
|
-
const clipper = viewer.clipper;
|
|
254
|
-
if (!clipper) return;
|
|
255
|
-
|
|
256
|
-
clipper.removeByIndex(index);
|
|
257
|
-
updateClipperControls();
|
|
258
|
-
}
|
|
54
|
+
// 获取工具实例
|
|
55
|
+
const tool = viewer.clipper;
|
|
259
56
|
|
|
260
57
|
// 激活工具
|
|
261
|
-
|
|
262
|
-
viewer.clipper.activate();
|
|
263
|
-
updateClipperControls();
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// 停用工具
|
|
267
|
-
function deactivateClipper() {
|
|
268
|
-
viewer.clipper.deactivate();
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// 清除所有剖切面
|
|
272
|
-
function clearAllPlanes() {
|
|
273
|
-
viewer.clipper.clear();
|
|
274
|
-
updateClipperControls();
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
// 监听鼠标抬起事件,当创建新平面时更新UI
|
|
278
|
-
let lastPlaneCount = 0;
|
|
279
|
-
function checkPlaneChanges() {
|
|
280
|
-
const clipper = viewer.clipper;
|
|
281
|
-
if (!clipper) return;
|
|
282
|
-
|
|
283
|
-
if (clipper.clippingPlanes.length !== lastPlaneCount) {
|
|
284
|
-
lastPlaneCount = clipper.clippingPlanes.length;
|
|
285
|
-
updateClipperControls();
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// 使用 requestAnimationFrame 监听变化(比 setInterval 更高效)
|
|
290
|
-
function startMonitoring() {
|
|
291
|
-
function monitor() {
|
|
292
|
-
checkPlaneChanges();
|
|
293
|
-
requestAnimationFrame(monitor);
|
|
294
|
-
}
|
|
295
|
-
monitor();
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// 监听工具事件
|
|
299
|
-
viewer.clipper.addEventListener('activate', () => {
|
|
300
|
-
lastPlaneCount = viewer.clipper.clippingPlanes.length;
|
|
301
|
-
updateClipperControls();
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
viewer.clipper.addEventListener('deactivate', () => {
|
|
305
|
-
// 停用时可以停止监听
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
// 初始激活工具
|
|
309
|
-
viewer.clipper.activate();
|
|
310
|
-
|
|
311
|
-
// 开始监听变化
|
|
312
|
-
startMonitoring();
|
|
313
|
-
|
|
314
|
-
// 暴露函数到全局
|
|
315
|
-
window.viewer = viewer;
|
|
316
|
-
window.updatePlanePosition = updatePlanePosition;
|
|
317
|
-
window.resetPlanePosition = resetPlanePosition;
|
|
318
|
-
window.removePlane = removePlane;
|
|
319
|
-
window.activateClipper = activateClipper;
|
|
320
|
-
window.deactivateClipper = deactivateClipper;
|
|
321
|
-
window.clearAllPlanes = clearAllPlanes;
|
|
58
|
+
tool.activate();
|
|
322
59
|
|
|
323
|
-
|
|
324
|
-
|
|
60
|
+
window.tool = tool
|
|
61
|
+
window.viewer = viewer
|
|
62
|
+
window.v = viewer
|
|
325
63
|
</script>
|
|
326
64
|
|
|
327
65
|
</body>
|