fl-web-component 2.0.4 → 2.0.6
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 +2 -0
- package/dist/fl-web-component.common.js +440 -75
- 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-flcanvas/index.vue +156 -0
- package/packages/components/com-graphics/index.vue +27 -14
- package/src/utils/threejs/measure-height.js +213 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
@charset "UTF-8";#fl-model[data-v-
|
|
1
|
+
@charset "UTF-8";#fl-model[data-v-78d8f350]{width:100%;height:100%;cursor:pointer}[data-v-78d8f350] .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-78d8f350] .measure-label{max-width:100px;margin-top:-1em;border:10px;border-radius:5px;padding:3px 10px;cursor:pointer;color:#009bea;background-color:#f4f4f4;-webkit-box-shadow:0 1px 3px 1px rgba(0,0,0,.25);box-shadow:0 1px 3px 1px rgba(0,0,0,.25)}[data-v-78d8f350] .circle-tag{width:10px;height:10px;margin-top:5px;border-radius:50%;background-color:#ff5000}[data-v-78d8f350] .measure-label-font{word-break:break-all}[data-v-78d8f350] .mark-label-img{padding-top:5px;width:20px;height:20px}.loading-overlay[data-v-78d8f350]{position:absolute;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,.7);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;z-index:1000;opacity:0;visibility:hidden;-webkit-transition:opacity .3s ease,visibility .3s ease;transition:opacity .3s ease,visibility .3s ease}.loading-overlay--visible[data-v-78d8f350]{opacity:1;visibility:visible}.loading-content[data-v-78d8f350]{background:#fff;border-radius:12px;padding:30px;text-align:center;-webkit-box-shadow:0 8px 32px rgba(0,0,0,.3);box-shadow:0 8px 32px rgba(0,0,0,.3);min-width:300px;max-width:400px}.loading-spinner[data-v-78d8f350]{width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #409eff;border-radius:50%;-webkit-animation:spin-78d8f350 1s linear infinite;animation:spin-78d8f350 1s linear infinite;margin:0 auto 20px}@-webkit-keyframes spin-78d8f350{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}@keyframes spin-78d8f350{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}.loading-text[data-v-78d8f350]{font-size:16px;font-weight:500;color:#333;margin-bottom:20px}.loading-progress-bar[data-v-78d8f350]{width:100%;height:8px;background-color:#f0f0f0;border-radius:4px;overflow:hidden;margin-bottom:15px}.loading-progress-fill[data-v-78d8f350]{height:100%;background:-webkit-gradient(linear,left top,right top,from(#409eff),to(#67c23a));background:linear-gradient(90deg,#409eff,#67c23a);border-radius:4px;-webkit-transition:width .3s ease;transition:width .3s ease}.loading-details[data-v-78d8f350]{font-size:12px;color:#666;line-height:1.5}.lil-gui{background:hsla(0,0%,100%,.95)!important;border:1px solid #e0e0e0!important;border-radius:8px!important;-webkit-box-shadow:0 4px 12px rgba(0,0,0,.15)!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;-webkit-box-shadow:0 0 0 2px rgba(0,123,255,.25)!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;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.2)!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;-webkit-transition:all .2s ease!important;transition:all .2s ease!important}.lil-gui .controller button:hover{background:linear-gradient(135deg,#0056b3,#004085)!important;-webkit-transform:translateY(-1px)!important;transform:translateY(-1px)!important;-webkit-box-shadow:0 4px 8px rgba(0,123,255,.3)!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;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.1)!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-7c2dd8bb]{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:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;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:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;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:""}.main_body[data-v-4b17bce0]{position:relative;width:100%;height:100%;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden}.classification_title[data-v-4b17bce0]{margin:0 0 10px 0;color:#fff;font-size:14px;cursor:default}.toolbar[data-v-4b17bce0]{z-index:10;position:absolute;width:520px;padding:8px 16px;border-radius:6px;-webkit-box-shadow:0 2px 10px 0 rgba(6,29,44,.25);box-shadow:0 2px 10px 0 rgba(6,29,44,.25);background-color:#fff;top:10px;left:50%;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transform:translateX(-50%);transform:translateX(-50%);display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-pack:distribute;justify-content:space-around}.icon_toolbar[data-v-4b17bce0],.text_toolbar[data-v-4b17bce0]{float:left;width:32px;height:32px;padding:0!important;background-repeat:no-repeat;background-size:24px;background-position:50%}.icon_active[data-v-4b17bce0],.icon_toolbar[data-v-4b17bce0]:hover,.text_toolbar[data-v-4b17bce0]:hover{background-color:#eee}[data-v-4b17bce0].icon_color .el-color-picker__trigger{height:24px;margin-top:4px;width:24px!important}[data-v-4b17bce0].el-color-picker--medium,[data-v-4b17bce0].el-color-picker--medium .el-color-picker__trigger{width:24px!important;height:24px!important}.canvas_container[data-v-4b17bce0]{position:relative;width:100%;height:100%;overflow:auto;-webkit-box-sizing:border-box;box-sizing:border-box}.canvas_container canvas[data-v-4b17bce0]{position:absolute;left:0}.canvas_container #ctx_front[data-v-4b17bce0]{z-index:5;background-color:transparent}.canvas_container #ctx_back[data-v-4b17bce0]{z-index:3}.canvas_container #ctx_base[data-v-4b17bce0]{z-index:1}#text[data-v-4b17bce0]{position:absolute;z-index:-1;resize:none;outline:none;border:1px dashed #9c9c9c;overflow:hidden;background:transparent;line-height:30px;display:none}#text[data-v-4b17bce0]:hover{border:1px dashed #53a8ff}#svg-component[data-v-2572c0e2],#svg-tigger[data-v-2572c0e2]{cursor:pointer;height:100%;width:100%;position:relative}#toolbar-show[data-v-2572c0e2]{z-index:20;position:absolute;width:100%;height:100%;top:0;left:0;overflow:hidden;background:#fff}
|
package/package.json
CHANGED
|
@@ -368,6 +368,162 @@ export default {
|
|
|
368
368
|
//doc.text("Hello world!", 10, 10);
|
|
369
369
|
//doc.save("a4.pdf");
|
|
370
370
|
},
|
|
371
|
+
toPdfs(list) {
|
|
372
|
+
let _this = this;
|
|
373
|
+
const pdf = new jsPDF('l', 'px', [konvaStage.width(), konvaStage.height()]);
|
|
374
|
+
const exportPixelRatio = 2; // 可以 2/3/4 自己调
|
|
375
|
+
|
|
376
|
+
for (let i = 0; i < list.length; i++) {
|
|
377
|
+
let data = list[i];
|
|
378
|
+
//先绘制图面
|
|
379
|
+
konvaLayer.destroyChildren();
|
|
380
|
+
const parser = new DxfParser();
|
|
381
|
+
let dxf = parser.parse(data);
|
|
382
|
+
let entities = formatEntity(dxf.entities);
|
|
383
|
+
let layers = dxf.tables.layer.layers;
|
|
384
|
+
for (let key in entities) {
|
|
385
|
+
if (entities[key]) {
|
|
386
|
+
let group = [];
|
|
387
|
+
let l = entities[key].length;
|
|
388
|
+
let layerConfig = recordLayerConfig[key];
|
|
389
|
+
let configParams =
|
|
390
|
+
layerConfig && Object.keys(layerConfig).length > 0 ? layerConfig : null;
|
|
391
|
+
for (let i = 0; i < l; i++) {
|
|
392
|
+
let type = entities[key][i].type;
|
|
393
|
+
handleFn(
|
|
394
|
+
type,
|
|
395
|
+
dxf,
|
|
396
|
+
entities[key][i],
|
|
397
|
+
group,
|
|
398
|
+
key,
|
|
399
|
+
configParams,
|
|
400
|
+
konvaLayer,
|
|
401
|
+
recordLayerConfig
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
if (!konvaLayer) return;
|
|
405
|
+
for (let i = 0; i < group.length; i++) {
|
|
406
|
+
let entity = group[i];
|
|
407
|
+
if (entity.type === 'text') {
|
|
408
|
+
if (konvaLayer) konvaLayer.add(entity.obj);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if (group[0].stroke == undefined) {
|
|
413
|
+
console.log(group);
|
|
414
|
+
group[0].stroke = '#000';
|
|
415
|
+
}
|
|
416
|
+
let customShape = new Konva.Shape({
|
|
417
|
+
x: 0,
|
|
418
|
+
y: 0,
|
|
419
|
+
strokeWidth: 0.2,
|
|
420
|
+
name: key.replace(/\s*/g, ''),
|
|
421
|
+
entityId: key,
|
|
422
|
+
stroke: group[0].stroke,
|
|
423
|
+
customColor: configParams ? configParams.color : '',
|
|
424
|
+
//visible: configParams ? configParams.visible :true,
|
|
425
|
+
sceneFunc(context, shape) {
|
|
426
|
+
context.beginPath();
|
|
427
|
+
for (let i = 0; i < group.length; i++) {
|
|
428
|
+
let entity = group[i];
|
|
429
|
+
|
|
430
|
+
if (entity.type === 'line') {
|
|
431
|
+
context.strokeStyle = entity.stroke;
|
|
432
|
+
let x1 = entity.x1;
|
|
433
|
+
let y1 = entity.y1;
|
|
434
|
+
let x2 = entity.x2;
|
|
435
|
+
let y2 = entity.y2;
|
|
436
|
+
if (x1 != undefined && y1 != undefined && x2 != undefined && y2 != undefined) {
|
|
437
|
+
context.moveTo(x1, -parseFloat(y1));
|
|
438
|
+
context.lineTo(x2, -parseFloat(y2));
|
|
439
|
+
}
|
|
440
|
+
let v1 = {};
|
|
441
|
+
v1.x = x1;
|
|
442
|
+
v1.y = y1;
|
|
443
|
+
let v2 = {};
|
|
444
|
+
v2.x = x2;
|
|
445
|
+
v2.y = y2;
|
|
446
|
+
_this.updateBounds(v1);
|
|
447
|
+
_this.updateBounds(v2);
|
|
448
|
+
}
|
|
449
|
+
if (entity.type === 'polyline') {
|
|
450
|
+
context.strokeStyle = entity.stroke;
|
|
451
|
+
|
|
452
|
+
let flag = false;
|
|
453
|
+
|
|
454
|
+
let points = entity.points;
|
|
455
|
+
let closed = entity.closed;
|
|
456
|
+
|
|
457
|
+
for (let j = 0; j < points.length; j++) {
|
|
458
|
+
let index = j % 2;
|
|
459
|
+
if (index === 0) {
|
|
460
|
+
let x = points[j];
|
|
461
|
+
let y = points[j + 1];
|
|
462
|
+
|
|
463
|
+
let point = {};
|
|
464
|
+
point.x = x;
|
|
465
|
+
point.y = y;
|
|
466
|
+
_this.updateBounds(point);
|
|
467
|
+
|
|
468
|
+
if (j === 0) {
|
|
469
|
+
context.moveTo(x, y);
|
|
470
|
+
} else {
|
|
471
|
+
context.lineTo(x, y);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if (closed) {
|
|
476
|
+
if (j === points.length - 1) {
|
|
477
|
+
context.lineTo(points[0], points[1]);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
// context.closePath();
|
|
484
|
+
context.fillStrokeShape(shape);
|
|
485
|
+
},
|
|
486
|
+
});
|
|
487
|
+
if (konvaLayer) konvaLayer.add(customShape);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
konvaStage.scale({
|
|
491
|
+
x: 2,
|
|
492
|
+
y: 2,
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
konvaStage.setX(0);
|
|
496
|
+
konvaStage.setY(750); // 750
|
|
497
|
+
//添加成功移动视口位置
|
|
498
|
+
|
|
499
|
+
if (i == 0) {
|
|
500
|
+
alert('0');
|
|
501
|
+
pdf.addImage(
|
|
502
|
+
konvaStage.toDataURL({ pixelRatio: 2 }),
|
|
503
|
+
0,
|
|
504
|
+
0,
|
|
505
|
+
konvaStage.width(),
|
|
506
|
+
konvaStage.height()
|
|
507
|
+
);
|
|
508
|
+
} else {
|
|
509
|
+
alert('调没调用konvaStage');
|
|
510
|
+
pdf.addPage();
|
|
511
|
+
pdf.addImage(
|
|
512
|
+
konvaStage.toDataURL({ pixelRatio: 2 }),
|
|
513
|
+
0,
|
|
514
|
+
0,
|
|
515
|
+
konvaStage.width(),
|
|
516
|
+
konvaStage.height()
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
pdf.save('批量导出.pdf');
|
|
522
|
+
|
|
523
|
+
// var imgData = canvas.toDataURL('image/png');
|
|
524
|
+
//doc.text("Hello world!", 10, 10);
|
|
525
|
+
//doc.save("a4.pdf");
|
|
526
|
+
},
|
|
371
527
|
clearCache() {
|
|
372
528
|
konvaLayer && konvaLayer.destroyChildren();
|
|
373
529
|
konvaLayer && konvaLayer.destroy();
|
|
@@ -131,6 +131,7 @@ import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
|
|
|
131
131
|
import MeasureDistance from '@/utils/threejs/measure-distance.js';
|
|
132
132
|
import MeasureArea from '@/utils/threejs/measure-area.js';
|
|
133
133
|
import MeasureAngle from '@/utils/threejs/measure-angle.js';
|
|
134
|
+
import MeasureHeight from '@/utils/threejs/measure-height.js';
|
|
134
135
|
import { parseData, processMeshData, processNodeData } from '@/utils/flgltf-parser';
|
|
135
136
|
import {
|
|
136
137
|
handleInstancedMeshModel,
|
|
@@ -265,7 +266,10 @@ export default {
|
|
|
265
266
|
raycaster = new this.THREE.Raycaster();
|
|
266
267
|
sceneClock = new this.THREE.Clock();
|
|
267
268
|
mouse = new this.THREE.Vector2();
|
|
268
|
-
|
|
269
|
+
const initialRect = instructions
|
|
270
|
+
? instructions.getBoundingClientRect()
|
|
271
|
+
: { width: window.innerWidth, height: window.innerHeight };
|
|
272
|
+
renderTarget = new this.THREE.WebGLRenderTarget(initialRect.width, initialRect.height, {
|
|
269
273
|
minFilter: this.THREE.LinearFilter,
|
|
270
274
|
magFilter: this.THREE.LinearFilter,
|
|
271
275
|
format: this.THREE.RGBAFormat,
|
|
@@ -2491,11 +2495,8 @@ export default {
|
|
|
2491
2495
|
const renderPass = new RenderPass(scene, camera);
|
|
2492
2496
|
outlineComposer.addPass(renderPass);
|
|
2493
2497
|
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
scene,
|
|
2497
|
-
camera
|
|
2498
|
-
);
|
|
2498
|
+
const rect = instructions.getBoundingClientRect();
|
|
2499
|
+
outlinePass = new OutlinePass(new this.THREE.Vector2(rect.width, rect.height), scene, camera);
|
|
2499
2500
|
outlinePass.edgeStrength = 3;
|
|
2500
2501
|
outlinePass.edgeGlow = 0.5; // 边缘模糊度
|
|
2501
2502
|
outlinePass.edgeThickness = 2; // 轮廓线宽度
|
|
@@ -2515,12 +2516,8 @@ export default {
|
|
|
2515
2516
|
}
|
|
2516
2517
|
},
|
|
2517
2518
|
initCamera() {
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
window.innerWidth / window.innerHeight,
|
|
2521
|
-
0.1,
|
|
2522
|
-
1000000
|
|
2523
|
-
);
|
|
2519
|
+
const rect = instructions.getBoundingClientRect();
|
|
2520
|
+
camera = new this.THREE.PerspectiveCamera(45, rect.width / rect.height, 0.1, 1000000);
|
|
2524
2521
|
// camera.position.set(0, 100, 150);
|
|
2525
2522
|
},
|
|
2526
2523
|
initControl() {
|
|
@@ -2722,7 +2719,7 @@ export default {
|
|
|
2722
2719
|
labelRenderer.setSize(rect.width, rect.height);
|
|
2723
2720
|
labelRenderer.domElement.style.position = 'absolute';
|
|
2724
2721
|
|
|
2725
|
-
labelRenderer.domElement.style.top =
|
|
2722
|
+
labelRenderer.domElement.style.top = '0';
|
|
2726
2723
|
labelRenderer.domElement.style.pointerEvents = 'none';
|
|
2727
2724
|
instructions.appendChild(labelRenderer.domElement);
|
|
2728
2725
|
},
|
|
@@ -2893,9 +2890,15 @@ export default {
|
|
|
2893
2890
|
camera.aspect = width / height;
|
|
2894
2891
|
camera.updateProjectionMatrix();
|
|
2895
2892
|
renderer.setSize(width, height, true);
|
|
2893
|
+
if (renderTarget) {
|
|
2894
|
+
renderTarget.setSize(width, height);
|
|
2895
|
+
}
|
|
2896
2896
|
if (outlineComposer) {
|
|
2897
2897
|
outlineComposer.setSize(width, height);
|
|
2898
2898
|
}
|
|
2899
|
+
if (outlinePass) {
|
|
2900
|
+
outlinePass.setSize(width, height);
|
|
2901
|
+
}
|
|
2899
2902
|
labelRenderer.setSize(width, height);
|
|
2900
2903
|
// this.timeRender()
|
|
2901
2904
|
// 这里也要更新测量
|
|
@@ -4346,7 +4349,7 @@ export default {
|
|
|
4346
4349
|
},
|
|
4347
4350
|
// 测量
|
|
4348
4351
|
/*
|
|
4349
|
-
|
|
4352
|
+
参数: type: '', distance、area、angle、height, 暂时只提供距离、面积、角度、高度这四种方式
|
|
4350
4353
|
*/
|
|
4351
4354
|
openMeasure(type) {
|
|
4352
4355
|
if (threeMeasure) {
|
|
@@ -4386,6 +4389,16 @@ export default {
|
|
|
4386
4389
|
);
|
|
4387
4390
|
threeMeasure.start();
|
|
4388
4391
|
break;
|
|
4392
|
+
case 'height':
|
|
4393
|
+
threeMeasure = new MeasureHeight.MeasureHeight(
|
|
4394
|
+
renderer,
|
|
4395
|
+
scene,
|
|
4396
|
+
camera,
|
|
4397
|
+
instructions.offsetWidth,
|
|
4398
|
+
instructions.offsetHeight
|
|
4399
|
+
);
|
|
4400
|
+
threeMeasure.start();
|
|
4401
|
+
break;
|
|
4389
4402
|
}
|
|
4390
4403
|
// 添加键盘事件监听器
|
|
4391
4404
|
document.addEventListener('keydown', this.handleMeasureKeyDown, false);
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer';
|
|
3
|
+
import { Message } from 'element-ui';
|
|
4
|
+
|
|
5
|
+
var _this = null;
|
|
6
|
+
var MeasureHeight = function (renderer, scene, camera, width, height) {
|
|
7
|
+
this.renderer = renderer;
|
|
8
|
+
this.scene = scene;
|
|
9
|
+
this.camera = camera;
|
|
10
|
+
this.pointArray = [];
|
|
11
|
+
this.raycaster = new THREE.Raycaster();
|
|
12
|
+
this.points = [];
|
|
13
|
+
this.polyline = [];
|
|
14
|
+
this.labels = [];
|
|
15
|
+
this.tempPoints = undefined;
|
|
16
|
+
this.tempLine = undefined;
|
|
17
|
+
this.tempLabel = undefined;
|
|
18
|
+
this.tipsLabel = undefined;
|
|
19
|
+
this.isCompleted = false;
|
|
20
|
+
this.timer = null;
|
|
21
|
+
this.width = width;
|
|
22
|
+
this.height = height;
|
|
23
|
+
this.firstTime = 0;
|
|
24
|
+
this.plane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
MeasureHeight.prototype = {
|
|
28
|
+
start() {
|
|
29
|
+
_this = this;
|
|
30
|
+
this.renderer.domElement.style.cursor = 'crosshair';
|
|
31
|
+
this.renderer.domElement.addEventListener('mousedown', this.mousedown, false);
|
|
32
|
+
this.renderer.domElement.addEventListener('mouseup', this.click, false);
|
|
33
|
+
this.renderer.domElement.addEventListener('contextmenu', this.rightClick, false);
|
|
34
|
+
},
|
|
35
|
+
updateParams(width, height) {
|
|
36
|
+
this.camera.aspect = width / height;
|
|
37
|
+
this.camera.updateProjectionMatrix();
|
|
38
|
+
this.renderer.setSize(width, height, true);
|
|
39
|
+
this.width = width;
|
|
40
|
+
this.height = height;
|
|
41
|
+
},
|
|
42
|
+
getPosition(e) {
|
|
43
|
+
const mouse = new THREE.Vector2();
|
|
44
|
+
const elRect = this.renderer.domElement.getBoundingClientRect();
|
|
45
|
+
const canvasX = e.clientX - elRect.left;
|
|
46
|
+
const canvasY = e.clientY - elRect.top;
|
|
47
|
+
|
|
48
|
+
mouse.x = (canvasX / elRect.width) * 2.0 - 1.0;
|
|
49
|
+
mouse.y = -(canvasY / elRect.height) * 2.0 + 1.0;
|
|
50
|
+
|
|
51
|
+
_this.raycaster.setFromCamera(mouse, this.camera);
|
|
52
|
+
const intersects = _this.raycaster.intersectObjects(_this.scene.children, true);
|
|
53
|
+
if (intersects.length > 0) {
|
|
54
|
+
return { point: intersects[0].point, isModel: true };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (_this.pointArray && _this.pointArray.length > 0) {
|
|
58
|
+
const lastPoint =
|
|
59
|
+
_this.pointArray.length === 1
|
|
60
|
+
? _this.pointArray[0]
|
|
61
|
+
: _this.pointArray[_this.pointArray.length - 2];
|
|
62
|
+
const cameraDir = new THREE.Vector3();
|
|
63
|
+
_this.camera.getWorldDirection(cameraDir);
|
|
64
|
+
const plane = new THREE.Plane().setFromNormalAndCoplanarPoint(cameraDir, lastPoint);
|
|
65
|
+
const target = new THREE.Vector3();
|
|
66
|
+
_this.raycaster.ray.intersectPlane(plane, target);
|
|
67
|
+
if (target) {
|
|
68
|
+
return { point: target, isModel: false };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const target = new THREE.Vector3();
|
|
73
|
+
_this.raycaster.ray.intersectPlane(_this.plane, target);
|
|
74
|
+
if (target) {
|
|
75
|
+
return { point: target, isModel: false };
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
},
|
|
79
|
+
createLine(p1, p2, config = { color: 0xff0000 }) {
|
|
80
|
+
const lineMaterial = new THREE.LineBasicMaterial({
|
|
81
|
+
color: config.color,
|
|
82
|
+
linewidth: 15,
|
|
83
|
+
depthTest: false,
|
|
84
|
+
depthWrite: false,
|
|
85
|
+
transparent: true,
|
|
86
|
+
});
|
|
87
|
+
const lineGeometry = new THREE.BufferGeometry().setFromPoints([p1, p2]);
|
|
88
|
+
const line = new THREE.Line(lineGeometry, lineMaterial);
|
|
89
|
+
line.renderOrder = 999;
|
|
90
|
+
line.frustumCulled = false;
|
|
91
|
+
return line;
|
|
92
|
+
},
|
|
93
|
+
createLabel(name, text, position) {
|
|
94
|
+
const div = document.createElement('div');
|
|
95
|
+
div.className = name;
|
|
96
|
+
div.textContent = text;
|
|
97
|
+
const divLabel = new CSS2DObject(div);
|
|
98
|
+
divLabel.position.set(position.x, position.y, position.z);
|
|
99
|
+
return divLabel;
|
|
100
|
+
},
|
|
101
|
+
getXozPlanePoint(point) {
|
|
102
|
+
return new THREE.Vector3(point.x, 0, point.z);
|
|
103
|
+
},
|
|
104
|
+
createHeightMeasure(point) {
|
|
105
|
+
const planePoint = _this.getXozPlanePoint(point);
|
|
106
|
+
const height = Math.abs(point.y - planePoint.y);
|
|
107
|
+
const labelPosition = new THREE.Vector3(point.x, (point.y + planePoint.y) / 2, point.z);
|
|
108
|
+
const circleTag = _this.createLabel('circle-tag', '', point);
|
|
109
|
+
const line = _this.createLine(point.clone(), planePoint.clone());
|
|
110
|
+
const label = _this.createLabel(
|
|
111
|
+
'measure-label',
|
|
112
|
+
`${_this.numberToString(height)}`,
|
|
113
|
+
labelPosition
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
_this.points.push(circleTag);
|
|
117
|
+
_this.polyline.push(line);
|
|
118
|
+
_this.labels.push(label);
|
|
119
|
+
_this.scene.add(circleTag);
|
|
120
|
+
_this.scene.add(line);
|
|
121
|
+
_this.scene.add(label);
|
|
122
|
+
},
|
|
123
|
+
createTipsLabel(label, position) {
|
|
124
|
+
const div = document.createElement('div');
|
|
125
|
+
div.className = 'tips-label';
|
|
126
|
+
div.textContent = label;
|
|
127
|
+
const tipsLabel = new CSS2DObject(div);
|
|
128
|
+
tipsLabel.position.set(position.x + 0.1, position.y, position.z + 0.05);
|
|
129
|
+
return tipsLabel;
|
|
130
|
+
},
|
|
131
|
+
mousedown() {
|
|
132
|
+
this.firstTime = new Date().getTime();
|
|
133
|
+
},
|
|
134
|
+
click(e) {
|
|
135
|
+
const lastTime = new Date().getTime();
|
|
136
|
+
if (lastTime - this.firstTime < 300) {
|
|
137
|
+
clearTimeout(_this.timer);
|
|
138
|
+
_this.timer = setTimeout(() => {
|
|
139
|
+
_this.isCompleted = false;
|
|
140
|
+
const positionResult = _this.getPosition(e);
|
|
141
|
+
if (positionResult) {
|
|
142
|
+
const { point, isModel } = positionResult;
|
|
143
|
+
if (!isModel) {
|
|
144
|
+
Message.warning('请点击模型进行测量');
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
// if (_this.tipsLabel) {
|
|
148
|
+
// _this.tipsLabel.position.set(point.x + 0.1, point.y, point.z + 0.05);
|
|
149
|
+
// } else {
|
|
150
|
+
// _this.tipsLabel = _this.createTipsLabel('点击测量', point);
|
|
151
|
+
// _this.scene.add(_this.tipsLabel);
|
|
152
|
+
// }
|
|
153
|
+
_this.createHeightMeasure(point);
|
|
154
|
+
}
|
|
155
|
+
}, 0);
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
rightClick(e) {
|
|
159
|
+
_this.preventContextMenu(e);
|
|
160
|
+
// if (_this.tipsLabel) {
|
|
161
|
+
// _this.scene.remove(_this.tipsLabel);
|
|
162
|
+
// _this.tipsLabel = undefined;
|
|
163
|
+
// }
|
|
164
|
+
clearTimeout(_this.timer);
|
|
165
|
+
const positionResult = _this.getPosition(e);
|
|
166
|
+
if (positionResult) {
|
|
167
|
+
_this.isCompleted = true;
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
close() {
|
|
171
|
+
this.renderer.domElement.removeEventListener('mousedown', this.mousedown);
|
|
172
|
+
this.renderer.domElement.removeEventListener('mouseup', this.click);
|
|
173
|
+
this.renderer.domElement.removeEventListener('contextmenu', this.rightClick);
|
|
174
|
+
this.remove(this.points);
|
|
175
|
+
this.remove(this.polyline);
|
|
176
|
+
this.remove(this.labels);
|
|
177
|
+
this.pointArray.splice(0);
|
|
178
|
+
this.points.splice(0);
|
|
179
|
+
this.polyline.splice(0);
|
|
180
|
+
this.labels.splice(0);
|
|
181
|
+
this.scene.remove(this.tipsLabel);
|
|
182
|
+
this.tipsLabel = undefined;
|
|
183
|
+
this.renderer.domElement.style.cursor = 'pointer';
|
|
184
|
+
this.firstTime = 0;
|
|
185
|
+
},
|
|
186
|
+
remove(array) {
|
|
187
|
+
for (let index = 0; index < array.length; index++) {
|
|
188
|
+
const element = array[index];
|
|
189
|
+
if (element.geometry) {
|
|
190
|
+
element.geometry.dispose();
|
|
191
|
+
}
|
|
192
|
+
this.scene.remove(element);
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
numberToString(num) {
|
|
196
|
+
if (num < 0.0001) {
|
|
197
|
+
return num.toString();
|
|
198
|
+
}
|
|
199
|
+
let fractionDigits = 2;
|
|
200
|
+
if (num < 0.01) {
|
|
201
|
+
fractionDigits = 4;
|
|
202
|
+
} else if (num < 0.1) {
|
|
203
|
+
fractionDigits = 3;
|
|
204
|
+
}
|
|
205
|
+
return num.toFixed(fractionDigits);
|
|
206
|
+
},
|
|
207
|
+
preventContextMenu(event) {
|
|
208
|
+
event.preventDefault();
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
export default {
|
|
212
|
+
MeasureHeight,
|
|
213
|
+
};
|