fl-web-component 1.0.11 → 1.1.0
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 +12 -1
- package/dist/fl-web-component.common.js +10677 -2954
- package/dist/fl-web-component.css +1 -1
- package/package.json +2 -1
- package/packages/components/com-flcanvas/index.vue +58 -9
- package/packages/components/com-graphics/index.vue +173 -69
- package/packages/components/com-graphics/pid.vue +31 -16
- package/src/main.js +5 -2
- package/src/utils/instance-parser.js +8 -2
- package/src/utils/threejs/measure-angle.js +40 -30
- package/src/utils/threejs/measure-area.js +52 -44
- package/src/utils/threejs/measure-distance.js +39 -29
- package/src/utils/threejs/rain-shader.js +58 -0
- package/src/utils/threejs/snow-shader.js +75 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
@charset "UTF-8";#fl-model[data-v-
|
|
1
|
+
@charset "UTF-8";#fl-model[data-v-574500c1],#konva-container[data-v-300b3063]{width:100%;height:100%;cursor:pointer}#konva-container[data-v-300b3063]{z-index:3;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-51e374ea]{cursor:pointer;height:100%;width:100%}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fl-web-component",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "vue-cli-service serve",
|
|
6
6
|
"lint": "eslint \"{src,packages}/**/*.{vue,js}\" --fix",
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
"lodash": "^4.17.21",
|
|
29
29
|
"meshline": "^3.3.1",
|
|
30
30
|
"regenerator-runtime": "^0.14.1",
|
|
31
|
+
"svg-pan-zoom": "^3.6.2",
|
|
31
32
|
"three": "^0.176.0",
|
|
32
33
|
"three.path": "^1.0.1",
|
|
33
34
|
"vue": "^2.6.11"
|
|
@@ -4,6 +4,26 @@
|
|
|
4
4
|
</template>
|
|
5
5
|
|
|
6
6
|
<script>
|
|
7
|
+
function base64ToBlob(base64) {
|
|
8
|
+
const byteCharacters = atob(base64);
|
|
9
|
+
const byteArrays = [];
|
|
10
|
+
|
|
11
|
+
for (let offset = 0; offset < byteCharacters.length; offset += 512) {
|
|
12
|
+
const slice = byteCharacters.slice(offset, offset + 512);
|
|
13
|
+
const byteNumbers = new Array(slice.length);
|
|
14
|
+
for (let i = 0; i < slice.length; i++) {
|
|
15
|
+
byteNumbers[i] = slice.charCodeAt(i);
|
|
16
|
+
}
|
|
17
|
+
const byteArray = new Uint8Array(byteNumbers);
|
|
18
|
+
byteArrays.push(byteArray);
|
|
19
|
+
}
|
|
20
|
+
return new Blob(byteArrays, { type: 'application/pdf' });
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
function createObjectURL(blob) {
|
|
25
|
+
return URL.createObjectURL(blob);
|
|
26
|
+
}
|
|
7
27
|
|
|
8
28
|
|
|
9
29
|
|
|
@@ -100,11 +120,21 @@
|
|
|
100
120
|
|
|
101
121
|
methods: {
|
|
102
122
|
loadDxf(data){
|
|
123
|
+
|
|
124
|
+
console.log("ok");
|
|
125
|
+
|
|
103
126
|
const parser = new DxfParser();
|
|
104
127
|
let dxf = parser.parse(data);
|
|
105
128
|
let entities = formatEntity(dxf.entities);
|
|
129
|
+
|
|
130
|
+
console.log(entities);
|
|
131
|
+
|
|
106
132
|
let layers = dxf.tables.layer.layers;
|
|
107
133
|
//加载图纸
|
|
134
|
+
|
|
135
|
+
console.log("layers");
|
|
136
|
+
console.log(layers);
|
|
137
|
+
|
|
108
138
|
for (let key in layers) {
|
|
109
139
|
if (entities[key]) {
|
|
110
140
|
let group = [];
|
|
@@ -142,12 +172,25 @@
|
|
|
142
172
|
let y1=entity.y1;
|
|
143
173
|
let x2=entity.x2;
|
|
144
174
|
let y2=entity.y2;
|
|
145
|
-
|
|
146
|
-
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
if(x1!=undefined&&y1!=undefined&&x2!=undefined&&y2!=undefined) {
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
context.moveTo(x1, -parseFloat(y1));
|
|
181
|
+
context.lineTo(x2, -parseFloat(y2));
|
|
182
|
+
}
|
|
147
183
|
}
|
|
148
184
|
if(entity.type === "polyline"){
|
|
185
|
+
let flag=false;
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
149
189
|
let points=entity.points;
|
|
150
190
|
let closed = entity.closed;
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
|
|
151
194
|
for(let j = 0; j < points.length; j++){
|
|
152
195
|
let index = j % 2;
|
|
153
196
|
if(index === 0){
|
|
@@ -183,10 +226,11 @@
|
|
|
183
226
|
scale = Number((boundingRect.width / boundingRect.height).toFixed(1));
|
|
184
227
|
scale = scale < 2 ? 2 : scale
|
|
185
228
|
}
|
|
229
|
+
/*
|
|
186
230
|
konvaStage.scale({
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
})
|
|
231
|
+
x: scale,
|
|
232
|
+
y: scale,
|
|
233
|
+
})*/
|
|
190
234
|
const boundingScale = konvaLayer.getClientRect();
|
|
191
235
|
//平移视口
|
|
192
236
|
const x =
|
|
@@ -195,14 +239,19 @@
|
|
|
195
239
|
const y =
|
|
196
240
|
this.$refs.svgDraw.clientHeight / 2 -
|
|
197
241
|
(Math.ceil(boundingScale.height) / 2 + boundingScale.y);
|
|
198
|
-
|
|
199
|
-
konvaStage.
|
|
242
|
+
|
|
243
|
+
konvaStage.scale({
|
|
244
|
+
x:2,
|
|
245
|
+
y:2
|
|
246
|
+
})
|
|
247
|
+
// konvaStage.setX(x);
|
|
248
|
+
konvaStage.setY(750);
|
|
200
249
|
|
|
201
250
|
|
|
202
251
|
|
|
203
252
|
|
|
204
253
|
},
|
|
205
|
-
toPdf(){
|
|
254
|
+
toPdf(name){
|
|
206
255
|
// get data URL with default settings
|
|
207
256
|
|
|
208
257
|
// open in new window
|
|
@@ -228,7 +277,7 @@
|
|
|
228
277
|
konvaStage.height()
|
|
229
278
|
);
|
|
230
279
|
|
|
231
|
-
pdf.save(
|
|
280
|
+
pdf.save(name+".pdf");
|
|
232
281
|
// var imgData = canvas.toDataURL('image/png');
|
|
233
282
|
//doc.text("Hello world!", 10, 10);
|
|
234
283
|
//doc.save("a4.pdf");
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
threeMeasure,
|
|
22
22
|
modelGroup,
|
|
23
23
|
gui,
|
|
24
|
-
animateId
|
|
24
|
+
animateId, scenePass, outlineComposer, renderTarget, sceneClock
|
|
25
25
|
] = (function* (v) {
|
|
26
26
|
while (true) yield v;
|
|
27
27
|
})(null);
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
var [lastTime, firstTime, fpsClock, timeStamp, progress] = (function* (v) {
|
|
30
30
|
while (true) yield v;
|
|
31
31
|
})(0);
|
|
32
|
+
var singleFrameTime = 1 / 30;
|
|
32
33
|
|
|
33
34
|
var [
|
|
34
35
|
roaming,
|
|
@@ -47,7 +48,7 @@
|
|
|
47
48
|
while (true) yield v;
|
|
48
49
|
})(true);
|
|
49
50
|
|
|
50
|
-
var clippingMesh = []
|
|
51
|
+
var clippingMesh = [], modelActive = [], modelActions = []
|
|
51
52
|
var removeSpeed = 200,
|
|
52
53
|
upSpeed = 200; //控制器移动速度 , //控制跳起时的速度
|
|
53
54
|
var roamConfig = {
|
|
@@ -66,13 +67,18 @@
|
|
|
66
67
|
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer';
|
|
67
68
|
import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer';
|
|
68
69
|
import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls.js';
|
|
70
|
+
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
|
69
71
|
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js'
|
|
70
72
|
import MeasureDistance from '@/utils/threejs/measure-distance.js';
|
|
71
73
|
import MeasureArea from '@/utils/threejs/measure-area.js';
|
|
72
74
|
import MeasureAngle from '@/utils/threejs/measure-angle.js';
|
|
73
75
|
import { parseData } from '@/utils/flgltf-parser';
|
|
74
76
|
import { handleInstancedMeshModel } from '@/utils/instance-parser';
|
|
75
|
-
|
|
77
|
+
import { RainShader } from '@/utils/threejs/rain-shader.js';
|
|
78
|
+
import { SnowShader } from '@/utils/threejs/snow-shader.js';
|
|
79
|
+
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js';
|
|
80
|
+
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
|
|
81
|
+
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js';
|
|
76
82
|
export default {
|
|
77
83
|
name: 'FlModel',
|
|
78
84
|
props: {
|
|
@@ -91,7 +97,14 @@
|
|
|
91
97
|
CameraControls.install({ THREE: this.THREE });
|
|
92
98
|
fpsClock = new this.THREE.Clock();
|
|
93
99
|
raycaster = new this.THREE.Raycaster();
|
|
100
|
+
sceneClock = new this.THREE.Clock();
|
|
94
101
|
mouse = new this.THREE.Vector2();
|
|
102
|
+
renderTarget = new this.THREE.WebGLRenderTarget(window.innerWidth, window.innerHeight, {
|
|
103
|
+
minFilter: this.THREE.LinearFilter,
|
|
104
|
+
magFilter: this.THREE.LinearFilter,
|
|
105
|
+
format: this.THREE.RGBAFormat,
|
|
106
|
+
stencilBuffer: true
|
|
107
|
+
})
|
|
95
108
|
},
|
|
96
109
|
mounted() {
|
|
97
110
|
instructions = document.getElementById('fl-model');
|
|
@@ -119,6 +132,7 @@
|
|
|
119
132
|
// 暂时注释这句 还有worker里面的 这跟渲染出的模型浅或暗有关系
|
|
120
133
|
renderer.outputEncoding = this.THREE.sRGBEncoding;
|
|
121
134
|
instructions.appendChild(renderer.domElement);
|
|
135
|
+
renderer.setClearAlpha(0);
|
|
122
136
|
renderer.autoClear = false;
|
|
123
137
|
renderer.autoClearColor = false;
|
|
124
138
|
renderer.autoClearDepth = false;
|
|
@@ -127,12 +141,6 @@
|
|
|
127
141
|
initScene() {
|
|
128
142
|
modelGroup = new this.THREE.Group();
|
|
129
143
|
scene = new this.THREE.Scene();
|
|
130
|
-
// scene.userData.recordEntity = []
|
|
131
|
-
|
|
132
|
-
// 适配客户端的坐标系,threejs坐标需绕x轴旋转90度
|
|
133
|
-
const mat4 = new this.THREE.Matrix4();
|
|
134
|
-
mat4.makeRotationX(-Math.PI / 2);
|
|
135
|
-
scene.applyMatrix4(mat4);
|
|
136
144
|
},
|
|
137
145
|
initCamera() {
|
|
138
146
|
camera = new this.THREE.PerspectiveCamera(
|
|
@@ -161,7 +169,7 @@
|
|
|
161
169
|
// 初始化文字画布
|
|
162
170
|
initLabelRender() {
|
|
163
171
|
labelRenderer = new CSS2DRenderer();
|
|
164
|
-
labelRenderer.setSize(
|
|
172
|
+
labelRenderer.setSize(window.innerWidth, window.innerHeight);
|
|
165
173
|
labelRenderer.domElement.style.position = 'absolute';
|
|
166
174
|
labelRenderer.domElement.style.top = '0px';
|
|
167
175
|
labelRenderer.domElement.style.pointerEvents = 'none';
|
|
@@ -184,6 +192,10 @@
|
|
|
184
192
|
modelBox3.expandByObject(modelGroup);
|
|
185
193
|
let modelWorldPs = new this.THREE.Vector3().addVectors(modelBox3.max, modelBox3.min).multiplyScalar(0.5)
|
|
186
194
|
scene.add(modelGroup);
|
|
195
|
+
// 适配客户端的坐标系,threejs坐标需绕x轴旋转90度
|
|
196
|
+
const mat4 = new this.THREE.Matrix4();
|
|
197
|
+
mat4.makeRotationX(-Math.PI / 2);
|
|
198
|
+
modelGroup.applyMatrix4(mat4);
|
|
187
199
|
modelGroup.traverse(child => {
|
|
188
200
|
if (child.isMesh) {
|
|
189
201
|
const json = this.getMeshCenterAndVolume(child)
|
|
@@ -422,31 +434,18 @@
|
|
|
422
434
|
// obj.material.needsUpdate = true;
|
|
423
435
|
}
|
|
424
436
|
},
|
|
425
|
-
//
|
|
426
|
-
|
|
427
|
-
{
|
|
428
|
-
attr: '', 需要修改属性名(color、visible(true / false)、opacity(0-1),
|
|
429
|
-
value: , 需要修改成的值
|
|
430
|
-
}
|
|
431
|
-
*/
|
|
432
|
-
updateWholeProperty(params) {
|
|
437
|
+
// 恢复模型原来的状态
|
|
438
|
+
updateWholeProperty() {
|
|
433
439
|
if (scene) {
|
|
434
440
|
scene.traverse(obj => {
|
|
435
441
|
if (obj instanceof this.THREE.Mesh) {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
break;
|
|
444
|
-
case 'opacity':
|
|
445
|
-
obj.material.opacity = params.value;
|
|
446
|
-
obj.material.transparent = true;
|
|
447
|
-
break;
|
|
448
|
-
}
|
|
449
|
-
obj.material.needsUpdate = true;
|
|
442
|
+
// 恢复颜色
|
|
443
|
+
obj.setColorAt(obj.userData.instanceIndex, obj.material.userData.nColor)
|
|
444
|
+
obj.instanceColor.needsUpdate = true
|
|
445
|
+
// 修改可见性
|
|
446
|
+
const restoreMatrix = new this.THREE.Matrix4().copy(obj.userData.copyMatrix);
|
|
447
|
+
obj.setMatrixAt(index, restoreMatrix);
|
|
448
|
+
obj.instanceMatrix.needsUpdate = true;
|
|
450
449
|
}
|
|
451
450
|
});
|
|
452
451
|
}
|
|
@@ -488,7 +487,11 @@
|
|
|
488
487
|
let obj = scene.getObjectByName(name);
|
|
489
488
|
if (obj) {
|
|
490
489
|
// cameraControls.fitToSphere(obj.parent, true); // TODO 待处理,先用 setModelCenter 进行定位
|
|
491
|
-
|
|
490
|
+
if (obj.isGroup) {
|
|
491
|
+
this.setModelCenter(obj);
|
|
492
|
+
} else if (obj.isMesh) {
|
|
493
|
+
this.setModelCenter(obj.parent);
|
|
494
|
+
}
|
|
492
495
|
// cameraControls.fitToBox( obj, true);
|
|
493
496
|
}
|
|
494
497
|
},
|
|
@@ -545,6 +548,23 @@
|
|
|
545
548
|
);
|
|
546
549
|
cameraControls.update(0);
|
|
547
550
|
},
|
|
551
|
+
// 使用中心点和实体的长宽高进行定位
|
|
552
|
+
/*
|
|
553
|
+
center: {x: 0, y: 0, z: 0},
|
|
554
|
+
box: {x: 0, y: 0, z: 0}
|
|
555
|
+
*/
|
|
556
|
+
locateByCenterBox(center, box) {
|
|
557
|
+
let cameraCenter = new this.THREE.Vector3(center.x, center.y, center.z).addScalar((Math.max(box.x, box.y, box.z)));
|
|
558
|
+
cameraControls.setLookAt(
|
|
559
|
+
cameraCenter.x,
|
|
560
|
+
cameraCenter.y,
|
|
561
|
+
cameraCenter.z,
|
|
562
|
+
center.x,
|
|
563
|
+
center.y,
|
|
564
|
+
center.z,
|
|
565
|
+
true
|
|
566
|
+
)
|
|
567
|
+
},
|
|
548
568
|
// 添加广告牌
|
|
549
569
|
/*
|
|
550
570
|
参数:
|
|
@@ -558,6 +578,10 @@
|
|
|
558
578
|
const divLabel = new CSS2DObject(data.billboard);
|
|
559
579
|
divLabel.name = data.labelClass; // 这个是用来清除广告牌用的
|
|
560
580
|
divLabel.position.set(data.x, data.y, data.z);
|
|
581
|
+
// 由于场景做了翻转 所以要把它翻转回来
|
|
582
|
+
// const mat4 = new this.THREE.Matrix4();
|
|
583
|
+
// mat4.makeRotationX(Math.PI / 2);
|
|
584
|
+
// divLabel.applyMatrix4(mat4);
|
|
561
585
|
scene.add(divLabel);
|
|
562
586
|
return divLabel;
|
|
563
587
|
},
|
|
@@ -593,14 +617,12 @@
|
|
|
593
617
|
removeObjectByName(name) {
|
|
594
618
|
let array = this.getObjectByName(name);
|
|
595
619
|
array.forEach(item => {
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
item.clear();
|
|
601
|
-
}
|
|
602
|
-
scene.remove(item);
|
|
620
|
+
item.material && item.material.dispose();
|
|
621
|
+
item.geometry && item.geometry.dispose();
|
|
622
|
+
if (item.isMesh) {
|
|
623
|
+
item.clear();
|
|
603
624
|
}
|
|
625
|
+
scene.remove(item);
|
|
604
626
|
});
|
|
605
627
|
},
|
|
606
628
|
// 删除场景中所有的实体
|
|
@@ -721,7 +743,6 @@
|
|
|
721
743
|
path: params.path,
|
|
722
744
|
});
|
|
723
745
|
roaming = true
|
|
724
|
-
// clock = new this.THREE.Clock();
|
|
725
746
|
},
|
|
726
747
|
// 更新漫游的配置
|
|
727
748
|
/*
|
|
@@ -752,6 +773,7 @@
|
|
|
752
773
|
lineTexture.offset.x -= 0.05;
|
|
753
774
|
// 相机和控制器的偏移
|
|
754
775
|
let offset = 10 / curve.getLength();
|
|
776
|
+
// progress 取值范围为0~1。getPoint(0)表示曲线起点,getPoint(1)表示曲线终点
|
|
755
777
|
if (progress <= 1 - offset) {
|
|
756
778
|
// this.timeRender()
|
|
757
779
|
const point = curve.getPointAt(progress);
|
|
@@ -790,11 +812,11 @@
|
|
|
790
812
|
// 单个实体模型炸开
|
|
791
813
|
/*
|
|
792
814
|
参数:
|
|
793
|
-
|
|
815
|
+
name: '',当前选中的实体对象的id
|
|
794
816
|
value: 0 - 100 整数
|
|
795
817
|
*/
|
|
796
|
-
localBomb(
|
|
797
|
-
let target = scene.
|
|
818
|
+
localBomb(name, value) {
|
|
819
|
+
let target = scene.getObjectByName(name);
|
|
798
820
|
if (target) {
|
|
799
821
|
this.computedBomb(target, value);
|
|
800
822
|
}
|
|
@@ -1033,13 +1055,11 @@
|
|
|
1033
1055
|
control.position.y = 3 - 0 / 10;
|
|
1034
1056
|
canJump = true;
|
|
1035
1057
|
}
|
|
1036
|
-
// this.timeRender()
|
|
1037
1058
|
}
|
|
1038
1059
|
},
|
|
1039
1060
|
// 键盘监听事件
|
|
1040
1061
|
onKeyDown(event) {
|
|
1041
1062
|
if (!event.keyCode) return;
|
|
1042
|
-
// this.timeRender()
|
|
1043
1063
|
switch (event.keyCode) {
|
|
1044
1064
|
// 前进
|
|
1045
1065
|
case 38:
|
|
@@ -1213,22 +1233,15 @@
|
|
|
1213
1233
|
},
|
|
1214
1234
|
// 隔离
|
|
1215
1235
|
/*
|
|
1216
|
-
参数: object, 目标实体,
|
|
1236
|
+
参数: object, 目标实体,
|
|
1217
1237
|
*/
|
|
1218
|
-
isolate(object
|
|
1219
|
-
// 隔离
|
|
1238
|
+
isolate(object) {
|
|
1239
|
+
// 隔离 将目标实体以外的实体隐藏掉
|
|
1220
1240
|
scene.traverse(item => {
|
|
1221
1241
|
if (item.isMesh && item.name !== object.name) {
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
break;
|
|
1226
|
-
case 'opacity':
|
|
1227
|
-
object.material.opacity = params.value;
|
|
1228
|
-
object.material.transparent = true;
|
|
1229
|
-
break;
|
|
1230
|
-
}
|
|
1231
|
-
item.material.needsUpdate = true;
|
|
1242
|
+
const offsetMatrix = new this.THREE.Matrix4().copy(item.userData.copyMatrix).makeTranslation(9999999, 9999999, 9999999);
|
|
1243
|
+
item.setMatrixAt(item.userData.instanceIndex, offsetMatrix);
|
|
1244
|
+
item.instanceMatrix.needsUpdate = true;
|
|
1232
1245
|
}
|
|
1233
1246
|
});
|
|
1234
1247
|
},
|
|
@@ -1236,11 +1249,8 @@
|
|
|
1236
1249
|
restore() {
|
|
1237
1250
|
scene.traverse(item => {
|
|
1238
1251
|
if (item.isMesh) {
|
|
1239
|
-
item.
|
|
1240
|
-
item.
|
|
1241
|
-
item.material.transparent = true;
|
|
1242
|
-
item.material.color = item.material.userData.nColor;
|
|
1243
|
-
item.material.needsUpdate = true;
|
|
1252
|
+
item.setColorAt(item.userData.instanceIndex, item.material.userData.nColor);
|
|
1253
|
+
item.instanceColor.needsUpdate = true;
|
|
1244
1254
|
item.userData.translate = {
|
|
1245
1255
|
x: 0,
|
|
1246
1256
|
y: 0,
|
|
@@ -1263,18 +1273,112 @@
|
|
|
1263
1273
|
});
|
|
1264
1274
|
item.userData.combineMatrixInvert = null;
|
|
1265
1275
|
}
|
|
1276
|
+
const offsetMatrix = new this.THREE.Matrix4().copy(item.userData.copyMatrix);
|
|
1277
|
+
item.setMatrixAt(item.userData.instanceIndex, offsetMatrix);
|
|
1278
|
+
item.instanceMatrix.needsUpdate = true;
|
|
1266
1279
|
}
|
|
1267
1280
|
});
|
|
1268
1281
|
},
|
|
1282
|
+
// 添加自定义模型, 暂时只支持glb、gltf格式
|
|
1283
|
+
addCustomModel(name, position, url, scale, immediately = false, callback) {
|
|
1284
|
+
const loader = new GLTFLoader()
|
|
1285
|
+
let locationModel = null;
|
|
1286
|
+
loader.load(url, (gltf) => {
|
|
1287
|
+
locationModel = gltf.scene
|
|
1288
|
+
locationModel.scale.set(scale, scale, scale)
|
|
1289
|
+
locationModel.updateMatrixWorld()
|
|
1290
|
+
if (immediately) {
|
|
1291
|
+
cameraControls.fitToSphere(gltf.scene, true)
|
|
1292
|
+
}
|
|
1293
|
+
// 动画混合器
|
|
1294
|
+
// 不参与裁剪
|
|
1295
|
+
locationModel.userData.cull = false;
|
|
1296
|
+
locationModel.name = name;
|
|
1297
|
+
scene.add(locationModel)
|
|
1298
|
+
locationModel.position.copy(new this.THREE.Vector3(position.x, position.y, position.z))
|
|
1299
|
+
if (gltf.animations.length > 0) {
|
|
1300
|
+
let actionMixer = new this.THREE.AnimationMixer(gltf.scene);
|
|
1301
|
+
const walkActive = actionMixer.clipAction(gltf.animations[0])
|
|
1302
|
+
walkActive.play()
|
|
1303
|
+
modelActive.push(walkActive);
|
|
1304
|
+
modelActions.push(actionMixer);
|
|
1305
|
+
}
|
|
1306
|
+
callback && callback()
|
|
1307
|
+
})
|
|
1308
|
+
},
|
|
1309
|
+
// 删除添加的自定义模型
|
|
1310
|
+
removeCustomModel(name) {
|
|
1311
|
+
let obj = this.getObjectByName(name);
|
|
1312
|
+
obj.forEach((item, index) => {
|
|
1313
|
+
if (item.animations > 0) {
|
|
1314
|
+
item.removeFromParent();
|
|
1315
|
+
modelActions[index].uncacheRoot(item);
|
|
1316
|
+
modelActions[index].uncacheRoot(modelActive[index]);
|
|
1317
|
+
}
|
|
1318
|
+
item.traverse((child) => {
|
|
1319
|
+
if (child instanceof this.THREE.Mesh) {
|
|
1320
|
+
child.geometry.dispose()
|
|
1321
|
+
child.material.dispose()
|
|
1322
|
+
}
|
|
1323
|
+
})
|
|
1324
|
+
scene.remove(item);
|
|
1325
|
+
})
|
|
1326
|
+
modelActions.splice(0);
|
|
1327
|
+
modelActive.splice(0);
|
|
1328
|
+
},
|
|
1329
|
+
// 修改天空背景
|
|
1330
|
+
skyBoxScene(url) {
|
|
1331
|
+
const textureCube = new this.THREE.CubeTextureLoader().load(url)
|
|
1332
|
+
scene.background = textureCube
|
|
1333
|
+
},
|
|
1334
|
+
// 清除天空背景
|
|
1335
|
+
clearSkyBoxScene() {
|
|
1336
|
+
scene.background = null
|
|
1337
|
+
},
|
|
1338
|
+
// 下雨模拟
|
|
1339
|
+
sceneSimu(type) {
|
|
1340
|
+
if (!outlineComposer) {
|
|
1341
|
+
outlineComposer = new EffectComposer(renderer, renderTarget);
|
|
1342
|
+
outlineComposer.addPass(new RenderPass(scene, camera));
|
|
1343
|
+
}
|
|
1344
|
+
if(type === 'rain') {
|
|
1345
|
+
scenePass = new ShaderPass(RainShader);
|
|
1346
|
+
scenePass.uniforms['iResolution'].value = new this.THREE.Vector2(window.innerWidth, window.innerHeight);
|
|
1347
|
+
outlineComposer.addPass(scenePass);
|
|
1348
|
+
} else if (type === 'snow') {
|
|
1349
|
+
scenePass = new ShaderPass(SnowShader);
|
|
1350
|
+
scenePass.uniforms['iResolution'].value = new this.THREE.Vector2(window.innerWidth, window.innerHeight);
|
|
1351
|
+
outlineComposer.addPass(scenePass);
|
|
1352
|
+
}
|
|
1353
|
+
},
|
|
1354
|
+
clearSceneSim() {
|
|
1355
|
+
if (scenePass && outlineComposer) {
|
|
1356
|
+
outlineComposer.removePass(scenePass);
|
|
1357
|
+
}
|
|
1358
|
+
scenePass = null;
|
|
1359
|
+
},
|
|
1269
1360
|
animate() {
|
|
1270
1361
|
const delta = fpsClock.getDelta();
|
|
1271
1362
|
timeStamp += delta;
|
|
1272
1363
|
animateId = requestAnimationFrame(this.animate);
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1364
|
+
if (timeStamp > singleFrameTime) {
|
|
1365
|
+
if (modelActions.length > 0) {
|
|
1366
|
+
modelActions.forEach(item => {
|
|
1367
|
+
item.update(timeStamp);
|
|
1368
|
+
})
|
|
1369
|
+
}
|
|
1370
|
+
cameraControls.enabled && cameraControls.update(timeStamp);
|
|
1371
|
+
this.cameraTrack();
|
|
1372
|
+
this.firstPerspective();
|
|
1373
|
+
if (scenePass) {
|
|
1374
|
+
let d = sceneClock.getDelta()
|
|
1375
|
+
scenePass.uniforms['iTime'].value += d;
|
|
1376
|
+
}
|
|
1377
|
+
labelRenderer.render(scene, camera);
|
|
1378
|
+
renderer.render(scene, camera);
|
|
1379
|
+
timeStamp = timeStamp % singleFrameTime;
|
|
1380
|
+
outlineComposer && outlineComposer.render();
|
|
1381
|
+
}
|
|
1278
1382
|
},
|
|
1279
1383
|
},
|
|
1280
1384
|
};
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<embed type="image/svg+xml" id="svg-tigger" :src="currentSvg" />
|
|
4
|
-
</div>
|
|
2
|
+
<embed type="image/svg+xml" id="svg-tigger" :src="currentSvg" />
|
|
5
3
|
</template>
|
|
6
4
|
<script>
|
|
7
|
-
|
|
5
|
+
import svgPanZoom from 'svg-pan-zoom';
|
|
8
6
|
var svgCon = {},
|
|
9
7
|
svgTigger = {},
|
|
10
8
|
svgEmbed = {};
|
|
@@ -15,20 +13,37 @@
|
|
|
15
13
|
var inspectionRect = null,
|
|
16
14
|
pointerRect = null;
|
|
17
15
|
export default {
|
|
18
|
-
name: '
|
|
16
|
+
name: 'FlSvg',
|
|
17
|
+
props: {
|
|
18
|
+
src: {
|
|
19
|
+
typeof: String,
|
|
20
|
+
default: ''
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
watch: {
|
|
24
|
+
src(newVal) {
|
|
25
|
+
this.currentSvg = newVal
|
|
26
|
+
}
|
|
27
|
+
},
|
|
19
28
|
data() {
|
|
20
29
|
return {
|
|
21
|
-
currentSvg:
|
|
30
|
+
currentSvg: '',
|
|
22
31
|
};
|
|
23
32
|
},
|
|
33
|
+
created() {
|
|
34
|
+
this.currentSvg = this.src
|
|
35
|
+
},
|
|
24
36
|
mounted() {
|
|
25
37
|
svgEmbed = document.getElementById('svg-tigger');
|
|
26
38
|
svgEmbed.addEventListener('resize', () => {
|
|
27
39
|
this.onWindowResize;
|
|
28
40
|
});
|
|
29
41
|
svgEmbed.addEventListener('load', () => {
|
|
42
|
+
console.log(svgPanZoom)
|
|
30
43
|
svgTigger = svgPanZoom('#svg-tigger', {
|
|
31
44
|
viewportSelector: '.svg-pan-zoom_viewport',
|
|
45
|
+
panEnabled: true,
|
|
46
|
+
zoomEnabled: true,
|
|
32
47
|
preventMouseEventsDefault: false,
|
|
33
48
|
});
|
|
34
49
|
svgCon = svgEmbed.getSVGDocument().querySelector('svg');
|
|
@@ -51,6 +66,11 @@
|
|
|
51
66
|
});
|
|
52
67
|
},
|
|
53
68
|
methods: {
|
|
69
|
+
changeSvg(url) {
|
|
70
|
+
this.$set(this, 'currentSvg', url)
|
|
71
|
+
preTargetCon.splice(0)
|
|
72
|
+
preTargetStyle.splice(0)
|
|
73
|
+
},
|
|
54
74
|
// 改变窗口大小
|
|
55
75
|
onWindowResize() {
|
|
56
76
|
svgCon.removeAttribute('width');
|
|
@@ -80,7 +100,7 @@
|
|
|
80
100
|
}
|
|
81
101
|
if (evt.button === 0) {
|
|
82
102
|
this.$emit('leftClick', targetElement);
|
|
83
|
-
} else if (
|
|
103
|
+
} else if (evt.button === 2) {
|
|
84
104
|
this.$emit('rightClick', targetElement);
|
|
85
105
|
}
|
|
86
106
|
}
|
|
@@ -90,20 +110,21 @@
|
|
|
90
110
|
参数:svgIds: [], 需要高亮的id的集合, flag: true / false, 是否要定位目标元素, color: '', 高亮的颜色
|
|
91
111
|
*/
|
|
92
112
|
highLight(svgIds, flag, color) {
|
|
113
|
+
console.log(svgIds)
|
|
93
114
|
if (svgIds === null || svgIds === undefined) {
|
|
94
115
|
throw new Error('svgIds should be an array');
|
|
95
116
|
} else {
|
|
96
117
|
for (let index = 0; index < svgIds.length; index++) {
|
|
97
118
|
let element = svgIds[index];
|
|
98
|
-
let targetCon = svgCon.getElementById(element);
|
|
119
|
+
let targetCon = svgCon.getElementById(element.svgId);
|
|
99
120
|
if (!targetCon) return;
|
|
100
121
|
this.depthTraversal(targetCon.children, color);
|
|
101
122
|
}
|
|
102
123
|
if (flag) {
|
|
103
124
|
svgTigger.reset();
|
|
104
|
-
let firstCon = svgCon.getElementById(svgIds[0]);
|
|
125
|
+
let firstCon = svgCon.getElementById(svgIds[0].svgId);
|
|
105
126
|
setTimeout(() => {
|
|
106
|
-
svgTigger.zoomAtPoint(
|
|
127
|
+
svgTigger.zoomAtPoint(2, {
|
|
107
128
|
x: firstCon.getBoundingClientRect().x,
|
|
108
129
|
y: firstCon.getBoundingClientRect().y,
|
|
109
130
|
});
|
|
@@ -154,12 +175,6 @@
|
|
|
154
175
|
};
|
|
155
176
|
</script>
|
|
156
177
|
<style lang="scss" scoped>
|
|
157
|
-
#pid-svg {
|
|
158
|
-
cursor: pointer;
|
|
159
|
-
height: 100%;
|
|
160
|
-
width: 100%;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
178
|
#svg-tigger {
|
|
164
179
|
cursor: pointer;
|
|
165
180
|
height: 100%;
|