fl-web-component 1.3.14 → 1.3.16
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 +5 -1
- package/dist/fl-web-component.common.js +123 -114
- package/dist/fl-web-component.common.js.map +1 -1
- package/dist/fl-web-component.css +1 -1
- package/package.json +1 -1
- package/packages/components/com-graphics/index.vue +17 -1
- package/src/utils/flgltf-parser.js +4 -2
- package/src/utils/instance-parser.js +76 -67
|
@@ -1 +1 @@
|
|
|
1
|
-
@charset "UTF-8";#fl-model[data-v-
|
|
1
|
+
@charset "UTF-8";#fl-model[data-v-c496e868]{width:100%;height:100%;cursor:pointer}[data-v-c496e868] .tips-label{width:60px;color:#000;font:12px Helvetica;margin-top:-3em;padding:5px;text-align:center;vertical-align:middle;background-color:khaki}[data-v-c496e868] .measure-label{max-width:100px;margin-top:-1em;border:10px;border-radius:5px;padding:3px 10px;cursor:pointer;color:#009bea;background-color:#f4f4f4;box-shadow:0 1px 3px 1px rgba(0,0,0,.25)}[data-v-c496e868] .circle-tag{width:10px;height:10px;margin-top:5px;border-radius:50%;background-color:#ff5000}[data-v-c496e868] .measure-label-font{word-break:break-all}[data-v-c496e868] .mark-label-img{padding-top:5px;width:20px;height:20px}.lil-gui{background:hsla(0,0%,100%,.95)!important;border:1px solid #e0e0e0!important;border-radius:8px!important;box-shadow:0 4px 12px rgba(0,0,0,.15)!important;backdrop-filter:blur(10px)!important;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif!important}.lil-gui .title{background:linear-gradient(135deg,#f8f9fa,#e9ecef)!important;color:#495057!important;border-bottom:1px solid #dee2e6!important;font-weight:600!important;padding:0 12px!important;border-radius:8px 8px 0 0!important}.lil-gui .controller{border-bottom:1px solid #f1f3f4!important;background:transparent!important}.lil-gui .controller:last-child{border-bottom:none!important}.lil-gui .controller .name{color:#495057!important;font-weight:500!important;font-size:12px!important}.lil-gui .controller .widget{background:#f8f9fa!important;border:1px solid #ced4da!important;border-radius:4px!important;color:#495057!important}.lil-gui .controller .widget:focus,.lil-gui .controller .widget:hover{border-color:#80bdff!important;box-shadow:0 0 0 2px rgba(0,123,255,.25)!important}.lil-gui .controller .widget:focus{outline:none!important}.lil-gui .controller input[type=range]{background:#e9ecef!important;height:4px!important;-webkit-appearance:none!important;-moz-appearance:none!important;appearance:none!important;border-radius:2px!important}.lil-gui .controller.number .fill{border-right:solid #008de9}.lil-gui .controller input[type=range]::-webkit-slider-thumb{background:#007bff!important;border:2px solid #fff!important;box-shadow:0 2px 4px rgba(0,0,0,.2)!important;width:16px!important;height:16px!important;border-radius:50%!important;-webkit-appearance:none!important;appearance:none!important;cursor:pointer!important}.lil-gui .controller input[type=range]::-moz-range-thumb{background:#007bff!important;border:2px solid #fff!important;box-shadow:0 2px 4px rgba(0,0,0,.2)!important;width:16px!important;height:16px!important;border-radius:50%!important;cursor:pointer!important}.lil-gui .controller .option{background:#fff!important;color:#495057!important;border-bottom:1px solid #f1f3f4!important}.lil-gui .controller .option:hover{background:#f8f9fa!important}.lil-gui .controller .option:last-child{border-bottom:none!important}.lil-gui input:active{background:#e6eff4}.lil-gui .controller button{background:linear-gradient(135deg,#007bff,#0056b3)!important;color:#fff!important;border:none!important;border-radius:4px!important;font-weight:500!important;transition:all .2s ease!important}.lil-gui .controller button:hover{background:linear-gradient(135deg,#0056b3,#004085)!important;transform:translateY(-1px)!important;box-shadow:0 4px 8px rgba(0,123,255,.3)!important}.lil-gui .controller .color{border:2px solid #fff!important;border-radius:4px!important;box-shadow:0 2px 4px rgba(0,0,0,.1)!important}.lil-gui .controller.number .slider,.lil-gui .controller.number .slider:hover{background-color:#e6eff4}.lil-gui input,.lil-gui input:hover,.lil-gui input[type=number]:focus,.lil-gui input[type=text]:focus{background:#e6eff4}.lil-gui .controller>.name{min-width:25px}.lil-gui .controller.number input{color:#2e3136}.lil-gui .controller.number .slider:active{background-color:#e6eff4}.lil-gui .folder>.title{background:linear-gradient(135deg,#f1f3f4,#e9ecef)!important;color:#495057!important;border-bottom:1px solid #dee2e6!important}.lil-gui .folder>.title:before{color:#6c757d!important}.lil-gui .folder.closed>.children{display:none!important}#konva-container[data-v-1b43deb6]{z-index:3;width:100%;height:100%;cursor:pointer;overflow:hidden}span[data-v-f547d5c6]{font-weight:bolder}.text[data-v-f547d5c6]{margin-top:20px}.line[data-v-f547d5c6]{border-bottom:1px solid #dcdfe6;margin:20px 0}.center[data-v-f547d5c6]{display:flex;flex-direction:column;align-items:center}.center .cen span[data-v-f547d5c6],.center .top span[data-v-f547d5c6]{color:"#53a8ff";display:inline-block;width:30px;height:30px;text-align:center;line-height:30px;border:1px solid;padding:5px;margin-bottom:10px;background-color:#e9f3ff}.center .cen span[data-v-f547d5c6]{margin:10px}.button[data-v-f547d5c6]{display:flex;justify-content:end;margin-top:20px}@font-face{font-family:iconfont;src:url(//at.alicdn.com/t/font_3226805_qqvo3ag3r8.woff2?t=1646635700216) format("woff2"),url(//at.alicdn.com/t/font_3226805_qqvo3ag3r8.woff?t=1646635700216) format("woff"),url(//at.alicdn.com/t/font_3226805_qqvo3ag3r8.ttf?t=1646635700216) format("truetype")}.iconfont[data-v-f547d5c6]{font-family:iconfont!important;font-size:50px;font-style:normal;color:"#53a8ff";-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-shubiao[data-v-f547d5c6]:before{content:""}#svg-tigger[data-v-0ec35ee4]{cursor:pointer;height:100%;width:100%}
|
package/package.json
CHANGED
|
@@ -220,7 +220,7 @@
|
|
|
220
220
|
color: '' 初始化模型的颜色 在业务方 有这个需求
|
|
221
221
|
meshNameConfig: {}
|
|
222
222
|
*/
|
|
223
|
-
drawModel(data, color = '', meshNameConfig = {}) {
|
|
223
|
+
drawModel(data, color = '', meshNameConfig = {}, options = {}) {
|
|
224
224
|
if (Object.keys(data).length === 0) {
|
|
225
225
|
return;
|
|
226
226
|
}
|
|
@@ -282,6 +282,9 @@
|
|
|
282
282
|
this.$emit('modelLoaded');
|
|
283
283
|
// cameraControls.saveState();
|
|
284
284
|
}
|
|
285
|
+
|
|
286
|
+
// 动态设置视角滚轮的距离
|
|
287
|
+
this.setCameraConfig();
|
|
285
288
|
},
|
|
286
289
|
// 获取mesh的中心点
|
|
287
290
|
getMeshCenterAndVolume(mesh) {
|
|
@@ -1563,6 +1566,19 @@
|
|
|
1563
1566
|
left && (cameraControls.mouseButtons.left = ACTION_ENUM[left]);
|
|
1564
1567
|
right && (cameraControls.mouseButtons.right = ACTION_ENUM[right]);
|
|
1565
1568
|
},
|
|
1569
|
+
// 动态设置视角滚轮的距离
|
|
1570
|
+
setCameraConfig() {
|
|
1571
|
+
let box3 = new this.THREE.Box3().setFromObject(scene);
|
|
1572
|
+
let size = new this.THREE.Vector3();
|
|
1573
|
+
box3.getSize(size);
|
|
1574
|
+
const maxBorder = Math.max(size.x, size.y, size.z);
|
|
1575
|
+
|
|
1576
|
+
cameraControls.camera.far = maxBorder * 50; // 设置相机的远裁剪面
|
|
1577
|
+
|
|
1578
|
+
cameraControls.minDistance = maxBorder * 0.05; // 动态设置视角滚轮的距离
|
|
1579
|
+
|
|
1580
|
+
camera.updateProjectionMatrix();
|
|
1581
|
+
},
|
|
1566
1582
|
},
|
|
1567
1583
|
};
|
|
1568
1584
|
</script>
|
|
@@ -69,7 +69,8 @@ function parseData(input) {
|
|
|
69
69
|
italic: material?.italic,
|
|
70
70
|
linepacing: 1, // 默认值
|
|
71
71
|
linewidth: material?.linewidth !== undefined ? material?.linewidth : 1, // 默认值
|
|
72
|
-
visible: material?.visible === false ? false : true
|
|
72
|
+
visible: material?.visible === false ? false : true,
|
|
73
|
+
transparent: material?.transp,
|
|
73
74
|
};
|
|
74
75
|
|
|
75
76
|
const identity = new THREE.Matrix4().identity();
|
|
@@ -161,7 +162,8 @@ function parseNode(node) {
|
|
|
161
162
|
}
|
|
162
163
|
});
|
|
163
164
|
if (isRoot) {
|
|
164
|
-
|
|
165
|
+
// 根节点父ID应为空字符串
|
|
166
|
+
const processed = processInstance(instance, '', instanceMap);
|
|
165
167
|
rootInstances.push(processed);
|
|
166
168
|
}
|
|
167
169
|
});
|
|
@@ -65,14 +65,16 @@ function handleInstancedMeshModel(
|
|
|
65
65
|
let targetGroup, instancedMeshIndex, drawObjectName;
|
|
66
66
|
const drawObjInstance = drawObjMapInstance[instances[i].drawObject];
|
|
67
67
|
if (drawObjInstance.MapMesh?.length > 0) {
|
|
68
|
+
// 确保始终使用当前实例的 drawObject 设置分组名
|
|
69
|
+
drawObjectName = instances[i].drawObject;
|
|
68
70
|
drawObjInstance.MapInstance.forEach((instance, index) => {
|
|
69
71
|
if (instance.instanceId == instances[i].instanceId) {
|
|
70
72
|
instancedMeshIndex = index;
|
|
71
|
-
drawObjectName = instances[i].drawObject;
|
|
72
73
|
}
|
|
73
74
|
});
|
|
75
|
+
// 在 modelGroup 中查找,避免因尚未加入 scene 而重复创建
|
|
74
76
|
if (drawObjectName) {
|
|
75
|
-
targetGroup =
|
|
77
|
+
targetGroup = modelGroup.getObjectByName(drawObjectName);
|
|
76
78
|
}
|
|
77
79
|
if (!targetGroup) {
|
|
78
80
|
const drawObj = drawObjMapInstance[instances[i].drawObject];
|
|
@@ -104,46 +106,48 @@ function handleInstancedMeshModel(
|
|
|
104
106
|
model.userData[key] = meshNameConfig[key];
|
|
105
107
|
meshName += ':' + meshNameConfig[key];
|
|
106
108
|
}
|
|
109
|
+
// 一次性为该 drawObject 的所有实例设置矩阵与颜色
|
|
107
110
|
drawObj.MapInstance.forEach((item, index) => {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
geomMatrix.multiply(alignMatrix).multiply(positionMatrix);
|
|
132
|
-
}
|
|
133
|
-
m4.multiplyMatrices(meshMatrix, geomMatrix);
|
|
134
|
-
|
|
135
|
-
model.setMatrixAt(index, m4);
|
|
136
|
-
const copyMatrix = new THREE.Matrix4().copy(m4);
|
|
137
|
-
model.userData.copyMatrix = copyMatrix;
|
|
111
|
+
model.userData.instanceIndex = index;
|
|
112
|
+
model.userData.instanceId = item.instanceId;
|
|
113
|
+
model.userData.primId = mesh.prmid;
|
|
114
|
+
model.name = meshName !== '' ? item.instanceId + meshName : item.instanceId;
|
|
115
|
+
|
|
116
|
+
const matrixVal = item.matrix?.val;
|
|
117
|
+
if (matrixVal) {
|
|
118
|
+
const m4 = new THREE.Matrix4();
|
|
119
|
+
const meshMatrix = new THREE.Matrix4();
|
|
120
|
+
const geomMatrix = new THREE.Matrix4();
|
|
121
|
+
// m4.setPosition(new THREE.Vector3(9999999, 9999999, 9999999)); // TODO 临时隐藏方案
|
|
122
|
+
meshMatrix.elements = item.matrix.val;
|
|
123
|
+
geomMatrix.elements = mesh.matrix.val;
|
|
124
|
+
|
|
125
|
+
// 处理文本居中对齐
|
|
126
|
+
const { points, alignType } = mesh;
|
|
127
|
+
if (isTextType(mesh.type)) {
|
|
128
|
+
const positionMatrix = new THREE.Matrix4();
|
|
129
|
+
|
|
130
|
+
const alignMatrix = createAlignedText(alignType, model.geometry);
|
|
131
|
+
|
|
132
|
+
positionMatrix.identity().makeTranslation(points[0], points[1], points[2]);
|
|
133
|
+
geomMatrix.multiply(alignMatrix).multiply(positionMatrix);
|
|
138
134
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
model.setColorAt(index, meshColor);
|
|
135
|
+
m4.multiplyMatrices(meshMatrix, geomMatrix);
|
|
136
|
+
|
|
137
|
+
model.setMatrixAt(index, m4);
|
|
138
|
+
const copyMatrix = new THREE.Matrix4().copy(m4);
|
|
139
|
+
model.userData.copyMatrix = copyMatrix;
|
|
145
140
|
}
|
|
141
|
+
// 需要先设置全部实例颜色,否则后续设置颜色无效
|
|
142
|
+
const { color } = mesh.prop;
|
|
143
|
+
const meshColor = customColor
|
|
144
|
+
? new THREE.Color(customColor)
|
|
145
|
+
: new THREE.Color(`rgb(${color[0]}, ${color[1]}, ${color[2]})`);
|
|
146
|
+
model.setColorAt(index, meshColor);
|
|
146
147
|
});
|
|
148
|
+
// 标记实例属性更新
|
|
149
|
+
if (model.instanceMatrix) model.instanceMatrix.needsUpdate = true;
|
|
150
|
+
if (model.instanceColor) model.instanceColor.needsUpdate = true;
|
|
147
151
|
// model.instanceColor.needsUpdate = true;
|
|
148
152
|
group.add(model);
|
|
149
153
|
});
|
|
@@ -343,7 +347,7 @@ function draw3Dmodel(geom, instanceName, instanceCount, nColor, nOpacity) {
|
|
|
343
347
|
const normal = new Float32Array(normals);
|
|
344
348
|
geometry.setAttribute('normal', new THREE.BufferAttribute(normal, 3));
|
|
345
349
|
}
|
|
346
|
-
const { color } = prop;
|
|
350
|
+
const { color, transparent } = prop;
|
|
347
351
|
let material, mesh, colors, opacity;
|
|
348
352
|
if (Array.isArray(color) && color.length) {
|
|
349
353
|
colors = color;
|
|
@@ -356,6 +360,11 @@ function draw3Dmodel(geom, instanceName, instanceCount, nColor, nOpacity) {
|
|
|
356
360
|
opacity = 1;
|
|
357
361
|
}
|
|
358
362
|
|
|
363
|
+
// 处理transparent透明度
|
|
364
|
+
if (transparent) {
|
|
365
|
+
opacity = 1 - transparent;
|
|
366
|
+
}
|
|
367
|
+
|
|
359
368
|
// 使用自定义材质或创建标准材质(默认参数配置)
|
|
360
369
|
let materialOptions = {
|
|
361
370
|
userData: {
|
|
@@ -392,34 +401,34 @@ function draw3Dmodel(geom, instanceName, instanceCount, nColor, nOpacity) {
|
|
|
392
401
|
geometry.setAttribute('opacity', new THREE.InstancedBufferAttribute(opacities, 1));
|
|
393
402
|
|
|
394
403
|
// 自定义着色器逻辑
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
404
|
+
if (!customMaterial) {
|
|
405
|
+
material.onBeforeCompile = shader => {
|
|
406
|
+
// 添加顶点着色器输入
|
|
407
|
+
shader.vertexShader = `
|
|
408
|
+
in float opacity; // 实例透明度属性
|
|
409
|
+
out float vAlpha;
|
|
410
|
+
${shader.vertexShader}
|
|
411
|
+
`.replace(
|
|
412
|
+
'#include <begin_vertex>',
|
|
413
|
+
`
|
|
414
|
+
#include <begin_vertex>
|
|
415
|
+
vAlpha = opacity; // 传递透明度到片段着色器
|
|
416
|
+
`
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
// 修改片段着色器
|
|
420
|
+
shader.fragmentShader = `
|
|
421
|
+
in float vAlpha;
|
|
422
|
+
${shader.fragmentShader}
|
|
423
|
+
`.replace(
|
|
424
|
+
'#include <alphatest_fragment>',
|
|
425
|
+
`
|
|
426
|
+
#include <alphatest_fragment>
|
|
427
|
+
diffuseColor.a *= vAlpha; // 应用实例透明度
|
|
428
|
+
`
|
|
429
|
+
);
|
|
430
|
+
};
|
|
431
|
+
}
|
|
423
432
|
mesh = new THREE.InstancedMesh(geometry, material, instanceCount);
|
|
424
433
|
|
|
425
434
|
const { visible } = prop;
|