w-plot-vue 1.0.5 → 1.0.7
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/.github/workflows/ci-test.yml +24 -0
- package/README.md +12 -11
- package/dist/w-plot-vue.umd.js +13 -2
- package/dist/w-plot-vue.umd.js.map +1 -1
- package/docs/examples/app.html +1 -1
- package/docs/examples/app.umd.js +13 -2
- package/docs/examples/app.umd.js.map +1 -1
- package/docs/examples/w-bar_horizontal_multi-set(color).html +26 -16
- package/docs/examples/w-bar_horizontal_multi-set(color, gradient).html +26 -16
- package/docs/examples/w-bar_horizontal_multi-set(series color).html +26 -16
- package/docs/examples/w-bar_horizontal_multi-set(series color, gradient).html +26 -16
- package/docs/examples/w-bar_horizontal_multi-set.html +26 -16
- package/docs/examples/w-bar_horizontal_multi-set__barDisplay(stackNormal).html +26 -16
- package/docs/examples/w-bar_horizontal_multi-set__barDisplay(stackPercent).html +26 -16
- package/docs/examples/w-bar_horizontal_multi-set__hide legned.html +26 -16
- package/docs/examples/w-bar_horizontal_multi-set__show labels.html +26 -16
- package/docs/examples/w-bar_horizontal_multi-set_barKpColor(gradient).html +26 -16
- package/docs/examples/w-bar_horizontal_multi-set_barKpColor.html +26 -16
- package/docs/examples/w-bar_horizontal_multi-set_barUseInnerLabelsForHorizontal_barGroupWidthRatio.html +26 -16
- package/docs/examples/w-bar_horizontal_multi-set_barWidthRatio.html +26 -16
- package/docs/examples/w-bar_horizontal_multi-set_barWidthRatio_barGroupWidthRatio.html +26 -16
- package/docs/examples/w-bar_horizontal_one-set(color).html +26 -16
- package/docs/examples/w-bar_horizontal_one-set(color, gradient).html +26 -16
- package/docs/examples/w-bar_horizontal_one-set.html +26 -16
- package/docs/examples/w-bar_horizontal_one-set_barColor(gradient).html +26 -16
- package/docs/examples/w-bar_horizontal_one-set_barColor.html +26 -16
- package/docs/examples/w-bar_horizontal_one-set_barKpColor(gradient).html +26 -16
- package/docs/examples/w-bar_horizontal_one-set_barKpColor.html +26 -16
- package/docs/examples/w-bar_horizontal_one-set_barUseInnerLabelsForHorizontal.html +26 -16
- package/docs/examples/w-bar_horizontal_one-set_barWidthRatio.html +26 -16
- package/docs/examples/w-bar_horizontal_one-set_barWidthRatio_barGroupWidthRatio.html +26 -16
- package/docs/examples/w-bar_horizontal_one-set_hide labels.html +26 -16
- package/docs/examples/w-bar_horizontal_one-set_marginLeft_marginRight.html +26 -16
- package/docs/examples/w-bar_horizontal_one-set_show legned.html +26 -16
- package/docs/examples/w-bar_multi-set(color).html +26 -16
- package/docs/examples/w-bar_multi-set(color, gradient).html +26 -16
- package/docs/examples/w-bar_multi-set(series color).html +26 -16
- package/docs/examples/w-bar_multi-set(series color, gradient).html +26 -16
- package/docs/examples/w-bar_multi-set.html +26 -16
- package/docs/examples/w-bar_multi-set__barDisplay(stackNormal).html +26 -16
- package/docs/examples/w-bar_multi-set__barDisplay(stackNormal)_.html +26 -16
- package/docs/examples/w-bar_multi-set__barDisplay(stackPercent).html +26 -16
- package/docs/examples/w-bar_multi-set__hide legned.html +26 -16
- package/docs/examples/w-bar_multi-set__show labels.html +26 -16
- package/docs/examples/w-bar_multi-set_barKpColor(gradient).html +26 -16
- package/docs/examples/w-bar_multi-set_barKpColor.html +26 -16
- package/docs/examples/w-bar_multi-set_barWidthRatio.html +26 -16
- package/docs/examples/w-bar_multi-set_barWidthRatio_barGroupWidthRatio_barBorderRadius.html +26 -16
- package/docs/examples/w-bar_one-set(color).html +26 -16
- package/docs/examples/w-bar_one-set(color, gradient).html +26 -16
- package/docs/examples/w-bar_one-set.html +26 -16
- package/docs/examples/w-bar_one-set_barColor(gradient).html +26 -16
- package/docs/examples/w-bar_one-set_barColor.html +26 -16
- package/docs/examples/w-bar_one-set_barKpColor(gradient).html +26 -16
- package/docs/examples/w-bar_one-set_barKpColor.html +26 -16
- package/docs/examples/w-bar_one-set_barWidthRatio.html +26 -16
- package/docs/examples/w-bar_one-set_barWidthRatio_barGroupWidthRatio_barBorderRadius.html +26 -16
- package/docs/examples/w-bar_one-set_hide labels.html +26 -16
- package/docs/examples/w-bar_one-set_marginLeft_marginRight_marginTop.html +26 -16
- package/docs/examples/w-bar_one-set_show legned.html +26 -16
- package/docs/examples/w-pie_one-set(color).html +26 -16
- package/docs/examples/w-pie_one-set(color, gradient).html +26 -16
- package/docs/examples/w-pie_one-set.html +26 -16
- package/docs/examples/w-pie_one-set_hide labels.html +26 -16
- package/docs/examples/w-pie_one-set_hide legned.html +26 -16
- package/docs/examples/w-pie_one-set_marginLeft_marginRight_marginTop.html +26 -16
- package/docs/examples/w-pie_one-set_pieBorderRadius.html +26 -16
- package/docs/examples/w-pie_one-set_pieBorderWidth_pieBorderRadius.html +26 -16
- package/docs/examples/w-pie_one-set_pieKpColor(gradient).html +26 -16
- package/docs/examples/w-pie_one-set_pieKpColor.html +26 -16
- package/docs/examples/w-pie_one-set_pieThicknessRatio.html +26 -16
- package/docs/examples/{w-plot_default.html → w-plot-2d_default.html} +29 -19
- package/docs/examples/w-plot-3d_default.html +209 -0
- package/docs/examples/w-rose_multi-set(color).html +26 -16
- package/docs/examples/w-rose_multi-set(color, gradient).html +26 -16
- package/docs/examples/w-rose_multi-set(series color).html +26 -16
- package/docs/examples/w-rose_multi-set(series color, gradient).html +26 -16
- package/docs/examples/w-rose_multi-set.html +26 -16
- package/docs/examples/w-rose_multi-set__hide legned.html +26 -16
- package/docs/examples/w-rose_multi-set__show labels.html +26 -16
- package/docs/examples/w-rose_multi-set_roseBorderWidth.html +26 -16
- package/docs/examples/w-rose_multi-set_roseKpColor(gradient).html +26 -16
- package/docs/examples/w-rose_multi-set_roseKpColor.html +26 -16
- package/docs/examples/w-rose_multi-set_roseWidthRatio.html +26 -16
- package/docs/examples/w-rose_one-set(color).html +26 -16
- package/docs/examples/w-rose_one-set(color, gradient).html +26 -16
- package/docs/examples/w-rose_one-set.html +26 -16
- package/docs/examples/w-rose_one-set_marginLeft_marginRight_marginTop.html +26 -16
- package/docs/examples/w-rose_one-set_roseBorderWidth.html +26 -16
- package/docs/examples/w-rose_one-set_roseKpColor(gradient).html +26 -16
- package/docs/examples/w-rose_one-set_roseKpColor.html +26 -16
- package/docs/examples/w-rose_one-set_roseShowLabels.html +26 -16
- package/docs/examples/w-rose_one-set_roseWidthRatio.html +26 -16
- package/docs/examples/w-rose_one-set_showLegend.html +26 -16
- package/docs/examples/w-rose_one-set_showLegend_legendPosition.html +26 -16
- package/docs/examples/w-set-multi_default.html +26 -16
- package/docs/examples/w-set-multi_hide labels.html +26 -16
- package/docs/examples/w-set-multi_hide legned.html +26 -16
- package/docs/examples/w-set-multi_keySelect.html +26 -16
- package/docs/examples/w-set-multi_slot head.html +26 -16
- package/docs/examples/w-set-multi_textPlotType_kpSelectText_widthSelect.html +26 -16
- package/docs/examples/w-set-one_default.html +26 -16
- package/docs/examples/w-set-one_hide labels.html +26 -16
- package/docs/examples/w-set-one_keySelect.html +26 -16
- package/docs/examples/w-set-one_show legned.html +26 -16
- package/docs/examples/w-set-one_slot head.html +26 -16
- package/docs/examples/w-set-one_textPlotType_kpSelectText_widthSelect.html +26 -16
- package/docs/getDefAxis.mjs.html +3 -3
- package/docs/getDefChart.mjs.html +3 -3
- package/docs/getDefLegend.mjs.html +3 -3
- package/docs/getDefOpt.mjs.html +3 -3
- package/docs/global.html +2 -2
- package/docs/index.html +2 -2
- package/docs/module-WBar.html +2 -2
- package/docs/module-WPie.html +2 -2
- package/docs/{module-WPlot.html → module-WPlot2d.html} +4 -4
- package/docs/module-WPlot3d.html +216 -0
- package/docs/module-WRose.html +2 -2
- package/docs/module-WSetMulti.html +2 -2
- package/docs/module-WSetOne.html +2 -2
- package/docs/setLegendLoc.mjs.html +3 -3
- package/package.json +7 -5
- package/script.txt +27 -0
- package/src/App.vue +83 -41
- package/src/AppZoneWBar.vue +1 -1
- package/src/AppZoneWPie.vue +1 -1
- package/src/{AppZoneWPlot.vue → AppZoneWPlot2d.vue} +9 -9
- package/src/AppZoneWPlot3d.vue +106 -0
- package/src/AppZoneWRose.vue +1 -1
- package/src/AppZoneWSetMulti.vue +1 -1
- package/src/AppZoneWSetOne.vue +1 -1
- package/src/components/WBar.vue +8 -8
- package/src/components/WPie.vue +7 -7
- package/src/components/{WPlot.vue → WPlot2d.vue} +1 -1
- package/src/components/WPlot3d.vue +1256 -0
- package/src/components/WPlotVue.vue +4 -2
- package/src/components/WRose.vue +7 -7
- package/src/components/WSetMulti.vue +6 -6
- package/src/js/genBarOpt.mjs +8 -8
- package/src/js/genPieOpt.mjs +7 -7
- package/src/js/genRoseOpt.mjs +7 -7
- package/src/js/getDefAxis.mjs +1 -1
- package/src/js/getDefChart.mjs +1 -1
- package/src/js/getDefLegend.mjs +1 -1
- package/src/js/getDefOpt.mjs +1 -1
- package/src/js/setLegendLoc.mjs +1 -1
- package/toolg/cvCasename.mjs +7 -7
- package/toolg/gExtractHtml.mjs +22 -15
|
@@ -0,0 +1,1256 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
:style="`display:inline-block; width:${widthInp}px; min-width:${widthInp}px; height:${heightInp}px; overflow-y:hidden;`"
|
|
4
|
+
:changeOptions="changeOptions"
|
|
5
|
+
>
|
|
6
|
+
|
|
7
|
+
<div
|
|
8
|
+
ref="panel"
|
|
9
|
+
:style="`position:relative; width:${widthInp}px; height:${heightInp}px;`"
|
|
10
|
+
v-domresize
|
|
11
|
+
@domresize="updatePanel"
|
|
12
|
+
></div>
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<script>
|
|
18
|
+
import get from 'lodash-es/get.js'
|
|
19
|
+
import set from 'lodash-es/set.js'
|
|
20
|
+
import size from 'lodash-es/size.js'
|
|
21
|
+
import each from 'lodash-es/each.js'
|
|
22
|
+
import map from 'lodash-es/map.js'
|
|
23
|
+
import min from 'lodash-es/min.js'
|
|
24
|
+
import max from 'lodash-es/max.js'
|
|
25
|
+
import isNumber from 'lodash-es/isNumber.js'
|
|
26
|
+
import cloneDeep from 'lodash-es/cloneDeep.js'
|
|
27
|
+
import evem from 'wsemi/src/evem.mjs'
|
|
28
|
+
import waitFun from 'wsemi/src/waitFun.mjs'
|
|
29
|
+
import isnum from 'wsemi/src/isnum.mjs'
|
|
30
|
+
import isestr from 'wsemi/src/isestr.mjs'
|
|
31
|
+
import isbol from 'wsemi/src/isbol.mjs'
|
|
32
|
+
import isearr from 'wsemi/src/isearr.mjs'
|
|
33
|
+
import iseobj from 'wsemi/src/iseobj.mjs'
|
|
34
|
+
import isEle from 'wsemi/src/isEle.mjs'
|
|
35
|
+
import isfun from 'wsemi/src/isfun.mjs'
|
|
36
|
+
import pmSeries from 'wsemi/src/pmSeries.mjs'
|
|
37
|
+
import cdbl from 'wsemi/src/cdbl.mjs'
|
|
38
|
+
import oc from 'wsemi/src/color.mjs'
|
|
39
|
+
import domRemove from 'wsemi/src/domRemove.mjs'
|
|
40
|
+
import domResize from 'w-component-vue/src/js/domResize.mjs'
|
|
41
|
+
import * as THREE from 'three'
|
|
42
|
+
// import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
|
|
43
|
+
import { STLLoader } from 'three/addons/loaders/STLLoader.js'
|
|
44
|
+
// import { STLExporter } from 'three/addons/exporters/STLExporter.js';
|
|
45
|
+
import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js'
|
|
46
|
+
import CameraControls from 'camera-controls'
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
let toRad = Math.PI / 180
|
|
50
|
+
let toDeg = 180 / Math.PI
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
let colorToHex = (c) => {
|
|
54
|
+
// console.log(colorToHex('#ffffff')) // => 16777215
|
|
55
|
+
// console.log(colorToHex('#f26')) // => 16720486
|
|
56
|
+
let h = oc.toHexString(c)
|
|
57
|
+
h = h.replace('#', '')
|
|
58
|
+
h = parseInt(h, 16)
|
|
59
|
+
return h
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
let addStl = async(ev, url, opt = {}) => {
|
|
64
|
+
|
|
65
|
+
//color
|
|
66
|
+
let color = get(opt, 'color', null)
|
|
67
|
+
if (!isestr(color)) {
|
|
68
|
+
color = '#fff'
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
//opacity
|
|
72
|
+
let opacity = get(opt, 'opacity', null)
|
|
73
|
+
if (!isNumber(opacity)) {
|
|
74
|
+
opacity = 1
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
//transparent
|
|
78
|
+
let transparent = opacity < 1
|
|
79
|
+
|
|
80
|
+
//loader
|
|
81
|
+
let loader = new STLLoader()
|
|
82
|
+
let geometry = await loader.loadAsync(url, (xhr) => {
|
|
83
|
+
let prog = (xhr.loaded / xhr.total) * 100
|
|
84
|
+
ev.emit('loading', prog)
|
|
85
|
+
})
|
|
86
|
+
// console.log('geometry',geometry)
|
|
87
|
+
|
|
88
|
+
//material, MeshLambertMaterial, MeshPhysicalMaterial
|
|
89
|
+
let material = new THREE.MeshLambertMaterial({
|
|
90
|
+
|
|
91
|
+
// visible:false,
|
|
92
|
+
|
|
93
|
+
color: colorToHex(color),
|
|
94
|
+
// wireframe: true,
|
|
95
|
+
|
|
96
|
+
depthTest: true,
|
|
97
|
+
depthWrite: true,
|
|
98
|
+
|
|
99
|
+
transparent,
|
|
100
|
+
opacity,
|
|
101
|
+
|
|
102
|
+
side: THREE.DoubleSide,
|
|
103
|
+
|
|
104
|
+
// polygonOffset: true,
|
|
105
|
+
// polygonOffsetFactor: 1, // positive value pushes polygon further away
|
|
106
|
+
// polygonOffsetUnits: 1,
|
|
107
|
+
|
|
108
|
+
// //for MeshPhysicalMaterial
|
|
109
|
+
// clearcoat: 1.0,//物体表面清漆层或者说透明涂层的厚度
|
|
110
|
+
// clearcoatRoughness: 0.1,//透明涂层表面的粗糙度
|
|
111
|
+
// envMap: envTexture,
|
|
112
|
+
// metalness: 0.25,
|
|
113
|
+
// roughness: 0.1,
|
|
114
|
+
// transmission: 0.99,
|
|
115
|
+
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
//mesh
|
|
119
|
+
let mesh = new THREE.Mesh(geometry, material)
|
|
120
|
+
// console.log('mesh', mesh)
|
|
121
|
+
|
|
122
|
+
// // wireframe, 若要使用也需要座標平移
|
|
123
|
+
// var geo = new THREE.WireframeGeometry( geometry ); // or WireframeGeometry
|
|
124
|
+
// var mat = new THREE.LineBasicMaterial( { color: 0x000000 } );
|
|
125
|
+
// var wireframe = new THREE.LineSegments( geo, mat );
|
|
126
|
+
// mesh.add( wireframe )
|
|
127
|
+
|
|
128
|
+
return mesh
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
let getCsrdFromMesh = (mesh) => {
|
|
133
|
+
// console.log('mesh',mesh)
|
|
134
|
+
let geometry = mesh.geometry
|
|
135
|
+
// console.log('geometry',geometry)
|
|
136
|
+
let cs = geometry.boundingSphere.center
|
|
137
|
+
// console.log('cs',cloneDeep(cs))
|
|
138
|
+
let rd = geometry.boundingSphere.radius
|
|
139
|
+
// console.log('rd',rd)
|
|
140
|
+
return {
|
|
141
|
+
cs,
|
|
142
|
+
rd,
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
let BoxFromMesh = (mesh) => {
|
|
148
|
+
let r = getCsrdFromMesh(mesh)
|
|
149
|
+
let xmin = r.cs.x - r.rd
|
|
150
|
+
let xmax = r.cs.x + r.rd
|
|
151
|
+
let ymin = r.cs.y - r.rd
|
|
152
|
+
let ymax = r.cs.y + r.rd
|
|
153
|
+
let zmin = r.cs.z - r.rd
|
|
154
|
+
let zmax = r.cs.z + r.rd
|
|
155
|
+
return {
|
|
156
|
+
xmin,
|
|
157
|
+
xmax,
|
|
158
|
+
ymin,
|
|
159
|
+
ymax,
|
|
160
|
+
zmin,
|
|
161
|
+
zmax,
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
let getBoxFromMeshs = (meshs) => {
|
|
167
|
+
let bxs = map(meshs, (mesh) => {
|
|
168
|
+
let bx = BoxFromMesh(mesh)
|
|
169
|
+
// console.log('bx',bx)
|
|
170
|
+
return bx
|
|
171
|
+
})
|
|
172
|
+
let xmin = min(map(bxs, 'xmin'))
|
|
173
|
+
let xmax = max(map(bxs, 'xmax'))
|
|
174
|
+
let ymin = min(map(bxs, 'ymin'))
|
|
175
|
+
let ymax = max(map(bxs, 'ymax'))
|
|
176
|
+
let zmin = min(map(bxs, 'zmin'))
|
|
177
|
+
let zmax = max(map(bxs, 'zmax'))
|
|
178
|
+
return {
|
|
179
|
+
xmin,
|
|
180
|
+
xmax,
|
|
181
|
+
ymin,
|
|
182
|
+
ymax,
|
|
183
|
+
zmin,
|
|
184
|
+
zmax,
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
let getCsrdFromMeshs = (meshs) => {
|
|
190
|
+
let bx = getBoxFromMeshs(meshs)
|
|
191
|
+
// console.log('bx(all)',bx)
|
|
192
|
+
let xrng = bx.xmax - bx.xmin
|
|
193
|
+
let yrng = bx.ymax - bx.ymin
|
|
194
|
+
let zrng = bx.zmax - bx.zmin
|
|
195
|
+
let xc = (bx.xmax + bx.xmin) / 2
|
|
196
|
+
let yc = (bx.ymax + bx.ymin) / 2
|
|
197
|
+
let zc = (bx.zmax + bx.zmin) / 2
|
|
198
|
+
let rd = max([xrng, yrng, zrng])
|
|
199
|
+
return {
|
|
200
|
+
cs: {
|
|
201
|
+
x: xc,
|
|
202
|
+
y: yc,
|
|
203
|
+
z: zc,
|
|
204
|
+
},
|
|
205
|
+
rd,
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
async function plot3d(items, opt = {}) {
|
|
211
|
+
|
|
212
|
+
//如果是多个网格模型组成一个模型对象,分别去平移每个网格模型对应的几何体可能比较麻烦,对于这种情况也可以给该模型对象嵌套一个父对象,然后把该模型对象相对于父对象平移一定距离,然后旋转该模型的父对象,不旋转模型本身,可以看到该模型的旋转效果,视觉效果上旋转轴改变了。
|
|
213
|
+
//http://www.yanhuangxueyuan.com/doc/Three.js/translateAxis.html
|
|
214
|
+
|
|
215
|
+
//有使用labels時OrbitControls得使用rendererLabels.domElement掛載, 否則會失去監聽無法操作
|
|
216
|
+
//https://blog.csdn.net/weixin_41111068/article/details/83650977
|
|
217
|
+
|
|
218
|
+
//How to completely clean up a Three.js scene
|
|
219
|
+
//https://discourse.threejs.org/t/when-to-dispose-how-to-completely-clean-up-a-three-js-scene/1549/10
|
|
220
|
+
|
|
221
|
+
//In general, attributes are freed if you call dispose() on the respective geometry object. However, if attributes needs to be replaced, it could be indeed a source of a memory leak because there it’s not possible so far to selectively free a single buffer attribute.
|
|
222
|
+
//https://discourse.threejs.org/t/disposal-of-buffers-colors-vectors-etc/13094
|
|
223
|
+
|
|
224
|
+
//MeshPhysicalMaterial清漆层
|
|
225
|
+
//https://www.mvrlink.com/threejs-meshphysicalmaterial-clearcoat-layer/
|
|
226
|
+
|
|
227
|
+
//check
|
|
228
|
+
if (!isearr(items)) {
|
|
229
|
+
items = []
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
//domPanel
|
|
233
|
+
let domPanel = get(opt, 'domPanel')
|
|
234
|
+
if (!isEle(domPanel)) {
|
|
235
|
+
domPanel = document.body
|
|
236
|
+
// console.log('domPanel use document.body')
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
let gs = (ele) => {
|
|
240
|
+
let w = 0
|
|
241
|
+
if (isNumber(ele.innerWidth)) {
|
|
242
|
+
w = ele.innerWidth
|
|
243
|
+
}
|
|
244
|
+
else if (isNumber(ele.clientWidth)) {
|
|
245
|
+
w = ele.clientWidth
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
console.log('ele', ele)
|
|
249
|
+
throw new Error(`can not get width from ele`)
|
|
250
|
+
}
|
|
251
|
+
let h = 0
|
|
252
|
+
if (isNumber(ele.innerWidth)) {
|
|
253
|
+
h = ele.innerHeight
|
|
254
|
+
}
|
|
255
|
+
else if (isNumber(ele.clientWidth)) {
|
|
256
|
+
h = ele.clientHeight
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
console.log('ele', ele)
|
|
260
|
+
throw new Error(`can not get height from ele`)
|
|
261
|
+
}
|
|
262
|
+
return { w, h }
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
//rendererWidth, rendererHeight
|
|
266
|
+
let rwh = gs(domPanel)
|
|
267
|
+
let rendererWidth = rwh.w
|
|
268
|
+
let rendererHeight = rwh.h
|
|
269
|
+
|
|
270
|
+
//backgroundColor
|
|
271
|
+
let backgroundColor = get(opt, 'backgroundColor')
|
|
272
|
+
if (!isestr(backgroundColor)) {
|
|
273
|
+
backgroundColor = '#222'
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
//useHelperAxes
|
|
277
|
+
let useHelperAxes = get(opt, 'useHelperAxes')
|
|
278
|
+
if (!isbol(useHelperAxes)) {
|
|
279
|
+
useHelperAxes = true
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
//helperAxesType
|
|
283
|
+
let helperAxesType = get(opt, 'helperAxesType')
|
|
284
|
+
if (!isnum(helperAxesType)) {
|
|
285
|
+
helperAxesType = 5
|
|
286
|
+
}
|
|
287
|
+
helperAxesType = cdbl(helperAxesType)
|
|
288
|
+
|
|
289
|
+
//useHelperGrid
|
|
290
|
+
let useHelperGrid = get(opt, 'useHelperGrid')
|
|
291
|
+
if (!isbol(useHelperGrid)) {
|
|
292
|
+
useHelperGrid = true
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
//helperGridSize
|
|
296
|
+
let helperGridSize = get(opt, 'helperGridSize')
|
|
297
|
+
if (!isnum(helperGridSize)) {
|
|
298
|
+
helperGridSize = 5
|
|
299
|
+
}
|
|
300
|
+
helperGridSize = cdbl(helperGridSize)
|
|
301
|
+
|
|
302
|
+
//helperGridDivisions
|
|
303
|
+
let helperGridDivisions = get(opt, 'helperGridDivisions')
|
|
304
|
+
if (!isnum(helperGridDivisions)) {
|
|
305
|
+
helperGridDivisions = 50
|
|
306
|
+
}
|
|
307
|
+
helperGridDivisions = cdbl(helperGridDivisions)
|
|
308
|
+
|
|
309
|
+
//helperGridPosratZ
|
|
310
|
+
let helperGridPosratZ = get(opt, 'helperGridPosratZ')
|
|
311
|
+
if (!isnum(helperGridPosratZ)) {
|
|
312
|
+
helperGridPosratZ = -1
|
|
313
|
+
}
|
|
314
|
+
helperGridPosratZ = cdbl(helperGridPosratZ)
|
|
315
|
+
|
|
316
|
+
//useLightAmbient
|
|
317
|
+
let useLightAmbient = get(opt, 'useLightAmbient')
|
|
318
|
+
if (!isbol(useLightAmbient)) {
|
|
319
|
+
useLightAmbient = true
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
//lightAmbientColor
|
|
323
|
+
let lightAmbientColor = get(opt, 'lightAmbientColor')
|
|
324
|
+
if (!isestr(lightAmbientColor)) {
|
|
325
|
+
lightAmbientColor = '#999'
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
//useLightPoint
|
|
329
|
+
let useLightPoint = get(opt, 'useLightPoint')
|
|
330
|
+
if (!isbol(useLightPoint)) {
|
|
331
|
+
useLightPoint = false
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
//lightPointPoss
|
|
335
|
+
let lightPointPoss = get(opt, 'lightPointPoss')
|
|
336
|
+
if (!isearr(lightPointPoss)) {
|
|
337
|
+
lightPointPoss = [
|
|
338
|
+
[5, 5, 5],
|
|
339
|
+
[-5, 5, 5],
|
|
340
|
+
[5, -5, 5],
|
|
341
|
+
]
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
//lightPointColor
|
|
345
|
+
let lightPointColor = get(opt, 'lightPointColor')
|
|
346
|
+
if (!isestr(lightPointColor)) {
|
|
347
|
+
lightPointColor = '#fff'
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
//lightPointIntensity
|
|
351
|
+
let lightPointIntensity = get(opt, 'lightPointIntensity')
|
|
352
|
+
if (!isnum(lightPointIntensity)) {
|
|
353
|
+
lightPointIntensity = 100
|
|
354
|
+
}
|
|
355
|
+
lightPointIntensity = cdbl(lightPointIntensity)
|
|
356
|
+
|
|
357
|
+
//lightPointDistance
|
|
358
|
+
let lightPointDistance = get(opt, 'lightPointDistance')
|
|
359
|
+
if (!isnum(lightPointDistance)) {
|
|
360
|
+
lightPointDistance = 0 //無限遠
|
|
361
|
+
}
|
|
362
|
+
lightPointDistance = cdbl(lightPointDistance)
|
|
363
|
+
|
|
364
|
+
//lightPointDecay
|
|
365
|
+
let lightPointDecay = get(opt, 'lightPointDecay')
|
|
366
|
+
if (!isnum(lightPointDecay)) {
|
|
367
|
+
lightPointDecay = 2
|
|
368
|
+
}
|
|
369
|
+
lightPointDecay = cdbl(lightPointDecay)
|
|
370
|
+
|
|
371
|
+
//useLightDirection
|
|
372
|
+
let useLightDirection = get(opt, 'useLightDirection')
|
|
373
|
+
if (!isbol(useLightDirection)) {
|
|
374
|
+
useLightDirection = true
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
//lightDirectionColor
|
|
378
|
+
let lightDirectionColor = get(opt, 'lightDirectionColor')
|
|
379
|
+
if (!isestr(lightDirectionColor)) {
|
|
380
|
+
lightDirectionColor = '#fff'
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
//lightDirectionIntensity
|
|
384
|
+
let lightDirectionIntensity = get(opt, 'lightDirectionIntensity')
|
|
385
|
+
if (!isnum(lightDirectionIntensity)) {
|
|
386
|
+
lightDirectionIntensity = 3
|
|
387
|
+
}
|
|
388
|
+
lightDirectionIntensity = cdbl(lightDirectionIntensity)
|
|
389
|
+
|
|
390
|
+
//lightDirectionPos
|
|
391
|
+
let lightDirectionPos = get(opt, 'lightDirectionPos')
|
|
392
|
+
if (!isearr(lightDirectionPos)) {
|
|
393
|
+
lightDirectionPos = [10, 10, 10]
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
//cameraType
|
|
397
|
+
let cameraType = get(opt, 'cameraType')
|
|
398
|
+
if (cameraType !== 'perspective' && cameraType !== 'orthographic') {
|
|
399
|
+
cameraType = 'perspective'
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
//cameraFov
|
|
403
|
+
let cameraFov = get(opt, 'cameraFov')
|
|
404
|
+
if (!isnum(cameraFov)) {
|
|
405
|
+
cameraFov = 30
|
|
406
|
+
}
|
|
407
|
+
cameraFov = cdbl(cameraFov)
|
|
408
|
+
|
|
409
|
+
//cameraNear
|
|
410
|
+
let cameraNear = get(opt, 'cameraNear')
|
|
411
|
+
if (!isnum(cameraNear)) {
|
|
412
|
+
cameraNear = 0.1
|
|
413
|
+
}
|
|
414
|
+
cameraNear = cdbl(cameraNear)
|
|
415
|
+
|
|
416
|
+
//cameraFar
|
|
417
|
+
let cameraFar = get(opt, 'cameraFar')
|
|
418
|
+
if (!isnum(cameraFar)) {
|
|
419
|
+
cameraFar = 1000
|
|
420
|
+
}
|
|
421
|
+
cameraFar = cdbl(cameraFar)
|
|
422
|
+
|
|
423
|
+
//cameraOrthographicRatio
|
|
424
|
+
let cameraOrthographicRatio = get(opt, 'cameraOrthographicRatio')
|
|
425
|
+
if (!isnum(cameraOrthographicRatio)) {
|
|
426
|
+
cameraOrthographicRatio = 0.5
|
|
427
|
+
}
|
|
428
|
+
cameraOrthographicRatio = cdbl(cameraOrthographicRatio)
|
|
429
|
+
|
|
430
|
+
//cameraPos
|
|
431
|
+
let cameraPos = get(opt, 'cameraPos')
|
|
432
|
+
if (!isearr(cameraPos)) {
|
|
433
|
+
cameraPos = [1, 1.3, 1]
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
//labelColor
|
|
437
|
+
let labelColor = get(opt, 'labelColor')
|
|
438
|
+
if (!isestr(labelColor)) {
|
|
439
|
+
labelColor = '#fff'
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
//labelFontFamily
|
|
443
|
+
let labelFontFamily = get(opt, 'labelFontFamily')
|
|
444
|
+
if (!isestr(labelFontFamily)) {
|
|
445
|
+
labelFontFamily = 'Microsoft JhengHei'
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
//labelFontSize
|
|
449
|
+
let labelFontSize = get(opt, 'labelFontSize')
|
|
450
|
+
if (!isestr(labelFontSize)) {
|
|
451
|
+
labelFontSize = '0.8rem'
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
//useAutoRotate
|
|
455
|
+
let useAutoRotate = get(opt, 'useAutoRotate')
|
|
456
|
+
if (!isbol(useAutoRotate)) {
|
|
457
|
+
useAutoRotate = false
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
//setUseAutoRotate
|
|
461
|
+
let setUseAutoRotate = (b) => {
|
|
462
|
+
useAutoRotate = b
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
//autoRotateDir
|
|
466
|
+
let autoRotateDir = get(opt, 'autoRotateDir')
|
|
467
|
+
if (autoRotateDir !== 'clockwise' && autoRotateDir !== 'counterclockwise') {
|
|
468
|
+
autoRotateDir = 'counterclockwise'
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
//autoRotateDeg
|
|
472
|
+
let autoRotateDeg = get(opt, 'autoRotateDeg')
|
|
473
|
+
if (!isnum(autoRotateDeg)) {
|
|
474
|
+
autoRotateDeg = 20
|
|
475
|
+
}
|
|
476
|
+
autoRotateDeg = cdbl(autoRotateDeg)
|
|
477
|
+
|
|
478
|
+
//ev
|
|
479
|
+
let ev = evem()
|
|
480
|
+
|
|
481
|
+
//clock
|
|
482
|
+
let clock = new THREE.Clock()
|
|
483
|
+
// console.log('clock',clock)
|
|
484
|
+
|
|
485
|
+
//scene
|
|
486
|
+
let scene = new THREE.Scene()
|
|
487
|
+
|
|
488
|
+
//backgroundColor
|
|
489
|
+
scene.background = new THREE.Color(colorToHex(backgroundColor))
|
|
490
|
+
|
|
491
|
+
//helperAxes
|
|
492
|
+
let helperAxes = null
|
|
493
|
+
if (useHelperAxes) {
|
|
494
|
+
helperAxes = new THREE.AxesHelper(helperAxesType)
|
|
495
|
+
scene.add(helperAxes)
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
//helperGrid
|
|
499
|
+
let helperGrid = null
|
|
500
|
+
if (useHelperGrid) {
|
|
501
|
+
helperGrid = new THREE.GridHelper(helperGridSize, helperGridDivisions)
|
|
502
|
+
helperGrid.geometry.rotateX(Math.PI * 0.5)
|
|
503
|
+
helperGrid.geometry.translate(0, 0, helperGridPosratZ)
|
|
504
|
+
scene.add(helperGrid)
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// //fog
|
|
508
|
+
// let fogColor='#aaa'
|
|
509
|
+
// let fog = new THREE.Fog( colorToHex(fogColor) , 0, 3 )
|
|
510
|
+
// scene.fog = fog
|
|
511
|
+
|
|
512
|
+
//lightAmbient
|
|
513
|
+
if (useLightAmbient) {
|
|
514
|
+
let lightAmbient = new THREE.AmbientLight(colorToHex(lightAmbientColor))
|
|
515
|
+
scene.add(lightAmbient)
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
//lightPoint
|
|
519
|
+
if (useLightPoint) {
|
|
520
|
+
each(lightPointPoss, (lp) => {
|
|
521
|
+
let lightPoint = new THREE.PointLight(colorToHex(lightPointColor), lightPointIntensity, lightPointDistance, lightPointDecay)
|
|
522
|
+
let x = get(lp, 0, 0)
|
|
523
|
+
let y = get(lp, 1, 0)
|
|
524
|
+
let z = get(lp, 2, 0)
|
|
525
|
+
lightPoint.position.set([x, y, z])
|
|
526
|
+
scene.add(lightPoint)
|
|
527
|
+
})
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
//lightDirection
|
|
531
|
+
if (useLightDirection) {
|
|
532
|
+
let lightDirection = new THREE.DirectionalLight(colorToHex(lightDirectionColor), lightDirectionIntensity)
|
|
533
|
+
let x = get(lightDirectionPos, 0, 0)
|
|
534
|
+
let y = get(lightDirectionPos, 1, 0)
|
|
535
|
+
let z = get(lightDirectionPos, 2, 0)
|
|
536
|
+
lightDirection.position.set(x, y, z)
|
|
537
|
+
// lightDirection.castShadow = true
|
|
538
|
+
scene.add(lightDirection)
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
let gasp = (w, h) => {
|
|
542
|
+
let r = 1
|
|
543
|
+
if (h > 0) {
|
|
544
|
+
r = w / h
|
|
545
|
+
}
|
|
546
|
+
return r
|
|
547
|
+
}
|
|
548
|
+
//cameraAspect
|
|
549
|
+
let cameraAspect = gasp(rendererWidth, rendererHeight)
|
|
550
|
+
|
|
551
|
+
//camera
|
|
552
|
+
let camera
|
|
553
|
+
if (cameraType === 'perspective') {
|
|
554
|
+
camera = new THREE.PerspectiveCamera(
|
|
555
|
+
cameraFov, //攝像機視錐體垂直視野角度
|
|
556
|
+
cameraAspect, //攝像機視錐體長寬比
|
|
557
|
+
cameraNear, //攝像機視錐體近端面
|
|
558
|
+
cameraFar, //攝像機視錐體遠端面
|
|
559
|
+
)
|
|
560
|
+
}
|
|
561
|
+
else if (cameraType === 'orthographic') {
|
|
562
|
+
let s = cameraOrthographicRatio
|
|
563
|
+
camera = new THREE.OrthographicCamera(
|
|
564
|
+
-s * cameraAspect, // left: 攝像機視錐體左側面
|
|
565
|
+
s * cameraAspect, // right: 攝像機視錐體右側面
|
|
566
|
+
s, // top: 攝像機視錐體上側面
|
|
567
|
+
-s, // bottom : 攝像機視錐體下側面
|
|
568
|
+
cameraNear, //攝像機視錐體近端面
|
|
569
|
+
cameraFar, //攝像機視錐體遠端面
|
|
570
|
+
)
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
//camera位置
|
|
574
|
+
if (true) {
|
|
575
|
+
let x = get(cameraPos, 0, 0)
|
|
576
|
+
let y = get(cameraPos, 1, 0)
|
|
577
|
+
let z = get(cameraPos, 2, 0)
|
|
578
|
+
camera.position.set(x, y, z) //旋轉物件面向世界空間中的一個點
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
//camera的z軸朝上
|
|
582
|
+
camera.up.x = 0
|
|
583
|
+
camera.up.y = 0
|
|
584
|
+
camera.up.z = 1
|
|
585
|
+
|
|
586
|
+
//renderer
|
|
587
|
+
let renderer = new THREE.WebGLRenderer({
|
|
588
|
+
antialias: true,
|
|
589
|
+
})
|
|
590
|
+
renderer.setSize(rendererWidth, rendererHeight)
|
|
591
|
+
// renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
|
592
|
+
// renderer.toneMappingExposure = 2.2;
|
|
593
|
+
// renderer.physicallyCorrectLights = true;
|
|
594
|
+
// renderer.outputEncoding = THREE.sRGBEncoding;
|
|
595
|
+
domPanel.appendChild(renderer.domElement)
|
|
596
|
+
|
|
597
|
+
//rendererLabels
|
|
598
|
+
let rendererLabels = new CSS2DRenderer()
|
|
599
|
+
rendererLabels.setSize(rendererWidth, rendererHeight)
|
|
600
|
+
rendererLabels.domElement.style.position = 'absolute'
|
|
601
|
+
rendererLabels.domElement.style.top = '0px'
|
|
602
|
+
rendererLabels.domElement.style.left = '0px'
|
|
603
|
+
domPanel.appendChild(rendererLabels.domElement)
|
|
604
|
+
|
|
605
|
+
// let updateSceneRotation = (alpha, theta)=>{
|
|
606
|
+
// let r=rotangToXyz(alpha, theta)
|
|
607
|
+
// console.log('rotangToXyz',r)
|
|
608
|
+
// // scene.rotation.x=r.x
|
|
609
|
+
// // scene.rotation.y=r.y
|
|
610
|
+
// // scene.rotation.z=r.z
|
|
611
|
+
// }
|
|
612
|
+
|
|
613
|
+
// //有使用labels時OrbitControls得使用rendererLabels.domElement掛載監聽事件, 因renderer.domElement已失去監聽無法操作
|
|
614
|
+
// let renderArea = rendererLabels.domElement
|
|
615
|
+
// let isDragging=false
|
|
616
|
+
// let previousMousePosition = {
|
|
617
|
+
// x: 0,
|
|
618
|
+
// y: 0
|
|
619
|
+
// }
|
|
620
|
+
|
|
621
|
+
// renderArea.addEventListener('mousedown', (e) => {
|
|
622
|
+
// console.log('renderArea mousedown',e)
|
|
623
|
+
// isDragging = true
|
|
624
|
+
// });
|
|
625
|
+
|
|
626
|
+
// renderArea.addEventListener('mousemove', (e) => {
|
|
627
|
+
// // console.log('renderArea mousemove',e)
|
|
628
|
+
|
|
629
|
+
// //dt
|
|
630
|
+
// let dt = {
|
|
631
|
+
// x: e.offsetX-previousMousePosition.x,
|
|
632
|
+
// y: e.offsetY-previousMousePosition.y
|
|
633
|
+
// };
|
|
634
|
+
|
|
635
|
+
// if (isDragging) {
|
|
636
|
+
// console.log('renderArea mousemove',e,dt)
|
|
637
|
+
// // let deltaRotationQuaternion = new THREE.Quaternion().
|
|
638
|
+
// // setFromEuler(
|
|
639
|
+
// // new THREE.Euler(toRad(dt.y * 1), toRad(dt.x * 1), 0, 'XYZ')
|
|
640
|
+
// // );
|
|
641
|
+
// // sphere.quaternion.multiplyQuaternions(deltaRotationQuaternion, sphere.quaternion);
|
|
642
|
+
// let radians=1
|
|
643
|
+
// alpha += radians*dt.x
|
|
644
|
+
// theta += radians*dt.y
|
|
645
|
+
// console.log('alpha',alpha,'theta',theta)
|
|
646
|
+
// updateSceneRotation(theta,alpha)
|
|
647
|
+
// }
|
|
648
|
+
|
|
649
|
+
// //update
|
|
650
|
+
// previousMousePosition = {
|
|
651
|
+
// x: e.offsetX,
|
|
652
|
+
// y: e.offsetY
|
|
653
|
+
// }
|
|
654
|
+
|
|
655
|
+
// });
|
|
656
|
+
|
|
657
|
+
// document.addEventListener('mouseup', (e) => {
|
|
658
|
+
// console.log('renderArea mouseup',e)
|
|
659
|
+
// isDragging = false;
|
|
660
|
+
// });
|
|
661
|
+
|
|
662
|
+
//OrbitControls
|
|
663
|
+
// let controls = new OrbitControls(camera, rendererLabels.domElement)
|
|
664
|
+
|
|
665
|
+
//CameraControls
|
|
666
|
+
CameraControls.install({ THREE })
|
|
667
|
+
let controls = new CameraControls(camera, rendererLabels.domElement)
|
|
668
|
+
// console.log('controls.mouseButtons',controls.mouseButtons)
|
|
669
|
+
|
|
670
|
+
//controls
|
|
671
|
+
// // controls.target.set( 0, 0, -0.1 )
|
|
672
|
+
// // controls.enableDamping = true
|
|
673
|
+
// controls.enablePan=true //平移
|
|
674
|
+
// controls.enableRotate=true //旋轉
|
|
675
|
+
// controls.enableZoom=true //縮放
|
|
676
|
+
// // controls.autoRotate=true //自動旋轉
|
|
677
|
+
// // controls.screenSpacePanning=false
|
|
678
|
+
// controls.zoomToCursor=true //針對滑鼠位置zoom
|
|
679
|
+
controls.mouseButtons = { //PAN ROTATE DOLLY
|
|
680
|
+
|
|
681
|
+
//鍵名大寫為OrbitControls使用
|
|
682
|
+
// LEFT: THREE.MOUSE.PAN,
|
|
683
|
+
// MIDDLE: THREE.MOUSE.DOLLY,
|
|
684
|
+
// RIGHT: THREE.MOUSE.ROTATE,
|
|
685
|
+
|
|
686
|
+
//鍵名小寫為CameraControls使用
|
|
687
|
+
left: CameraControls.ACTION.ROTATE,
|
|
688
|
+
middle: CameraControls.ACTION.DOLLY,
|
|
689
|
+
right: CameraControls.ACTION.OFFSET,
|
|
690
|
+
wheel: CameraControls.ACTION.ZOOM,
|
|
691
|
+
|
|
692
|
+
}
|
|
693
|
+
controls.touches = {
|
|
694
|
+
|
|
695
|
+
//鍵名小寫為CameraControls使用
|
|
696
|
+
one: CameraControls.ACTION.TOUCH_ROTATE,
|
|
697
|
+
two: CameraControls.ACTION.TOUCH_DOLLY_OFFSET,
|
|
698
|
+
three: CameraControls.ACTION.TOUCH_OFFSET,
|
|
699
|
+
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
//setViewAngle
|
|
703
|
+
let setViewAngle = (az, polar) => {
|
|
704
|
+
set(controls, 'azimuthAngle', az * toRad)
|
|
705
|
+
set(controls, 'polarAngle', polar * toRad)
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
//getViewAngle
|
|
709
|
+
let getViewAngle = () => {
|
|
710
|
+
let az = get(controls, 'azimuthAngle')
|
|
711
|
+
let polar = get(controls, 'polarAngle')
|
|
712
|
+
return {
|
|
713
|
+
azimuthAngle: az * toDeg,
|
|
714
|
+
polarAngle: polar * toDeg,
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
//dollyTo( distance, enableTransition )
|
|
719
|
+
//zoomTo( zoom, enableTransition )
|
|
720
|
+
|
|
721
|
+
//meshs
|
|
722
|
+
let meshs = []
|
|
723
|
+
await pmSeries(items, async(v) => {
|
|
724
|
+
let mesh = await addStl(ev, v.url, {
|
|
725
|
+
color: get(v, 'color', ''),
|
|
726
|
+
opacity: get(v, 'opacity', 1),
|
|
727
|
+
})
|
|
728
|
+
mesh.name = v.name
|
|
729
|
+
meshs.push(mesh)
|
|
730
|
+
})
|
|
731
|
+
console.log('meshs', meshs)
|
|
732
|
+
|
|
733
|
+
//getMeshsInfor
|
|
734
|
+
let getMeshsInfor = () => {
|
|
735
|
+
let rs = map(meshs, (v) => {
|
|
736
|
+
let r1 = get(v, 'material.color.r', 0)
|
|
737
|
+
let g1 = get(v, 'material.color.g', 0)
|
|
738
|
+
let b1 = get(v, 'material.color.b', 0)
|
|
739
|
+
let c = { r: r1 * 255, g: g1 * 255, b: b1 * 255 }
|
|
740
|
+
let color = oc.toRgbString(c)
|
|
741
|
+
let opacity = get(v, 'material.opacity', 1)
|
|
742
|
+
return {
|
|
743
|
+
name: v.name,
|
|
744
|
+
visible: v.visible,
|
|
745
|
+
color,
|
|
746
|
+
opacity,
|
|
747
|
+
}
|
|
748
|
+
})
|
|
749
|
+
return rs
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
//setMeshVisible
|
|
753
|
+
let setMeshVisible = (ind, visible) => {
|
|
754
|
+
let mesh = get(meshs, ind)
|
|
755
|
+
if (!iseobj(mesh)) {
|
|
756
|
+
return null
|
|
757
|
+
}
|
|
758
|
+
try {
|
|
759
|
+
meshs[ind].visible = visible
|
|
760
|
+
}
|
|
761
|
+
catch (err) {
|
|
762
|
+
console.log(err)
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
//setMeshColor
|
|
767
|
+
let setMeshColor = (ind, color) => {
|
|
768
|
+
let mesh = get(meshs, ind)
|
|
769
|
+
if (!iseobj(mesh)) {
|
|
770
|
+
return null
|
|
771
|
+
}
|
|
772
|
+
try {
|
|
773
|
+
meshs[ind].material.color.setHex(colorToHex(color))
|
|
774
|
+
}
|
|
775
|
+
catch (err) {
|
|
776
|
+
console.log(err)
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
//group
|
|
781
|
+
let group = new THREE.Group()
|
|
782
|
+
each(meshs, (mesh) => {
|
|
783
|
+
group.add(mesh)
|
|
784
|
+
})
|
|
785
|
+
scene.add(group)
|
|
786
|
+
// console.log('group',group)
|
|
787
|
+
|
|
788
|
+
//延遲等render後才能取得csrd
|
|
789
|
+
setTimeout(() => {
|
|
790
|
+
|
|
791
|
+
//csrd
|
|
792
|
+
let csrd = getCsrdFromMeshs(meshs)
|
|
793
|
+
// console.log('csrd',csrd)
|
|
794
|
+
|
|
795
|
+
//cs, r
|
|
796
|
+
let cs = csrd.cs
|
|
797
|
+
let r = 1
|
|
798
|
+
if (csrd.rd > 0) {
|
|
799
|
+
r = 1 / csrd.rd
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
//translate, scale
|
|
803
|
+
each(meshs, (mesh) => {
|
|
804
|
+
// console.log('mesh',mesh)
|
|
805
|
+
// console.log('mesh.geometry.boundingSphere.center',mesh.geometry.boundingSphere.center)
|
|
806
|
+
|
|
807
|
+
let geometry = mesh.geometry
|
|
808
|
+
geometry.translate(-cs.x, -cs.y, -cs.z)
|
|
809
|
+
// console.log('cs',cs)
|
|
810
|
+
geometry.scale(r, r, r)
|
|
811
|
+
// console.log('cs',cs)
|
|
812
|
+
|
|
813
|
+
//ele
|
|
814
|
+
let ele = document.createElement('div')
|
|
815
|
+
ele.className = 'label'
|
|
816
|
+
ele.textContent = mesh.name
|
|
817
|
+
// ele.style.marginTop = '0px'
|
|
818
|
+
// ele.style.background = 'none'
|
|
819
|
+
ele.style.color = labelColor
|
|
820
|
+
ele.style.fontFamily = labelFontFamily
|
|
821
|
+
ele.style.fontSize = labelFontSize
|
|
822
|
+
|
|
823
|
+
//label
|
|
824
|
+
let label = new CSS2DObject(ele)
|
|
825
|
+
let c = mesh.geometry.boundingSphere.center
|
|
826
|
+
label.position.set(c.x, c.y, c.z)
|
|
827
|
+
// console.log('label',label)
|
|
828
|
+
mesh.add(label)
|
|
829
|
+
|
|
830
|
+
// console.log('mesh[0].getWorldPosition()',mesh[0].getWorldPosition())
|
|
831
|
+
})
|
|
832
|
+
|
|
833
|
+
// console.log('group.getWorldPosition()',group.getWorldPosition())
|
|
834
|
+
}, 1)
|
|
835
|
+
|
|
836
|
+
let render = () => {
|
|
837
|
+
try {
|
|
838
|
+
renderer.render(scene, camera)
|
|
839
|
+
rendererLabels.render(scene, camera)
|
|
840
|
+
}
|
|
841
|
+
catch (err) {
|
|
842
|
+
console.log(err)
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
let resize = () => {
|
|
847
|
+
// console.log('plot3d resize')
|
|
848
|
+
|
|
849
|
+
//rendererWidth, rendererHeight, cameraAspect
|
|
850
|
+
let rwh = gs(domPanel)
|
|
851
|
+
rendererWidth = rwh.w
|
|
852
|
+
rendererHeight = rwh.h
|
|
853
|
+
cameraAspect = gasp(rendererWidth, rendererHeight)
|
|
854
|
+
|
|
855
|
+
//update camera
|
|
856
|
+
camera.aspect = cameraAspect
|
|
857
|
+
camera.updateProjectionMatrix()
|
|
858
|
+
|
|
859
|
+
//update renderer
|
|
860
|
+
renderer.setSize(rendererWidth, rendererHeight)
|
|
861
|
+
rendererLabels.setSize(rendererWidth, rendererHeight)
|
|
862
|
+
|
|
863
|
+
//render
|
|
864
|
+
render()
|
|
865
|
+
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
//render
|
|
869
|
+
render()
|
|
870
|
+
setTimeout(() => {
|
|
871
|
+
render() //須再延遲渲染
|
|
872
|
+
}, 100)
|
|
873
|
+
|
|
874
|
+
//stop
|
|
875
|
+
let stop = false
|
|
876
|
+
let animate = () => {
|
|
877
|
+
if (stop) {
|
|
878
|
+
// console.log('animate stop')
|
|
879
|
+
return
|
|
880
|
+
}
|
|
881
|
+
try {
|
|
882
|
+
|
|
883
|
+
//delta
|
|
884
|
+
let delta = clock.getDelta()
|
|
885
|
+
// console.log('delta',delta)
|
|
886
|
+
|
|
887
|
+
//hasControlsUpdated
|
|
888
|
+
let hasControlsUpdated = controls.update(delta)
|
|
889
|
+
// console.log('hasControlsUpdated',hasControlsUpdated)
|
|
890
|
+
|
|
891
|
+
//useAutoRotate
|
|
892
|
+
if (useAutoRotate) {
|
|
893
|
+
let i = autoRotateDir === 'clockwise' ? 1 : -1
|
|
894
|
+
// console.log('autoRotateDir', autoRotateDir, i)
|
|
895
|
+
let az = i * autoRotateDeg * toRad * delta
|
|
896
|
+
// console.log('az', az)
|
|
897
|
+
controls.azimuthAngle += az
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
//requestAnimationFrame
|
|
901
|
+
requestAnimationFrame(animate)
|
|
902
|
+
|
|
903
|
+
//check
|
|
904
|
+
if (hasControlsUpdated) {
|
|
905
|
+
// console.log('hasControlsUpdated and render')
|
|
906
|
+
render()
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
catch (err) {
|
|
910
|
+
console.log(err)
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
//animate
|
|
915
|
+
animate()
|
|
916
|
+
|
|
917
|
+
let disposeAll = () => {
|
|
918
|
+
|
|
919
|
+
let cleanMaterial = (material) => { //已預先執行多種dispose, 此函數暫時用不到
|
|
920
|
+
// console.log('dispose material')
|
|
921
|
+
material.dispose()
|
|
922
|
+
// dispose textures
|
|
923
|
+
for (let key of Object.keys(material)) {
|
|
924
|
+
let value = material[key]
|
|
925
|
+
if (value && typeof value === 'object' && 'minFilter' in value) {
|
|
926
|
+
// console.log('dispose texture')
|
|
927
|
+
value.dispose()
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
//stop
|
|
933
|
+
stop = true
|
|
934
|
+
|
|
935
|
+
//dispose & free group
|
|
936
|
+
group.traverse(function(obj) {
|
|
937
|
+
if (obj.isMesh) {
|
|
938
|
+
obj.geometry.dispose()
|
|
939
|
+
obj.material.dispose()
|
|
940
|
+
}
|
|
941
|
+
})
|
|
942
|
+
scene.remove(group)
|
|
943
|
+
group = null
|
|
944
|
+
|
|
945
|
+
//dispose & free helperAxes
|
|
946
|
+
if (useHelperAxes) {
|
|
947
|
+
scene.remove(helperAxes)
|
|
948
|
+
helperAxes.dispose()
|
|
949
|
+
helperAxes = null
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
//dispose & free helperGrid
|
|
953
|
+
if (useHelperGrid) {
|
|
954
|
+
scene.remove(helperGrid)
|
|
955
|
+
helperGrid.dispose()
|
|
956
|
+
helperGrid = null
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// //dispose & free lightAmbient
|
|
960
|
+
// scene.remove(lightAmbient)
|
|
961
|
+
// lightAmbient.dispose()
|
|
962
|
+
// lightAmbient = null
|
|
963
|
+
|
|
964
|
+
// //dispose & free lightPoint
|
|
965
|
+
// scene.remove(lightPoint)
|
|
966
|
+
// lightPoint.dispose()
|
|
967
|
+
// lightPoint = null
|
|
968
|
+
|
|
969
|
+
// //dispose & free lightDirection
|
|
970
|
+
// scene.remove(lightDirection)
|
|
971
|
+
// lightDirection.dispose()
|
|
972
|
+
// lightDirection = null
|
|
973
|
+
|
|
974
|
+
// labelDiv=document.querySelector('#labelDiv'); // same beginning
|
|
975
|
+
// allLabelsToDelete=document.querySelectorAll('#labelDiv .label') // takes children of class "label" like in moon-earth example
|
|
976
|
+
// forEach (elem in allLabelsToDelete ) {
|
|
977
|
+
// labelDiv.removeChild(elem)
|
|
978
|
+
// }
|
|
979
|
+
|
|
980
|
+
//dispose obj of scene
|
|
981
|
+
scene.traverse(object => {
|
|
982
|
+
// console.log('object', object)
|
|
983
|
+
if (object.isLight) {
|
|
984
|
+
// console.log('dispose light')
|
|
985
|
+
object.dispose()
|
|
986
|
+
}
|
|
987
|
+
if (object.isMesh) {
|
|
988
|
+
// console.log('dispose geometry')
|
|
989
|
+
object.geometry.dispose()
|
|
990
|
+
if (object.material.isMaterial) {
|
|
991
|
+
cleanMaterial(object.material)
|
|
992
|
+
}
|
|
993
|
+
else {
|
|
994
|
+
// an array of materials
|
|
995
|
+
for (let material of object.material) cleanMaterial(material)
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
})
|
|
1000
|
+
|
|
1001
|
+
//remove
|
|
1002
|
+
// console.log('renderer.domElement',renderer.domElement)
|
|
1003
|
+
// console.log('rendererLabels.domElement',rendererLabels.domElement)
|
|
1004
|
+
// document.body.remove(renderer.domElement)
|
|
1005
|
+
// document.body.remove(rendererLabels.domElement)
|
|
1006
|
+
// renderer.domElement.remove()
|
|
1007
|
+
// rendererLabels.domElement.remove()
|
|
1008
|
+
domRemove(renderer.domElement)
|
|
1009
|
+
domRemove(rendererLabels.domElement)
|
|
1010
|
+
|
|
1011
|
+
//dispose & free renderer
|
|
1012
|
+
renderer.dispose()
|
|
1013
|
+
// rendererLabels.dispose()
|
|
1014
|
+
renderer = null
|
|
1015
|
+
rendererLabels = null
|
|
1016
|
+
|
|
1017
|
+
//free clock
|
|
1018
|
+
// clock.dispose()
|
|
1019
|
+
clock = null
|
|
1020
|
+
|
|
1021
|
+
//free controls
|
|
1022
|
+
// controls.dispose()
|
|
1023
|
+
controls = null
|
|
1024
|
+
|
|
1025
|
+
//free camera
|
|
1026
|
+
// camera.dispose()
|
|
1027
|
+
camera = null
|
|
1028
|
+
|
|
1029
|
+
//free scene
|
|
1030
|
+
// scene.dispose()
|
|
1031
|
+
scene = null
|
|
1032
|
+
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
//save
|
|
1036
|
+
ev.render = render
|
|
1037
|
+
ev.resize = resize
|
|
1038
|
+
ev.dispose = disposeAll
|
|
1039
|
+
ev.setUseAutoRotate = setUseAutoRotate
|
|
1040
|
+
ev.getMeshsInfor = getMeshsInfor
|
|
1041
|
+
ev.setMeshVisible = setMeshVisible
|
|
1042
|
+
ev.setMeshColor = setMeshColor
|
|
1043
|
+
ev.setViewAngle = setViewAngle
|
|
1044
|
+
ev.getViewAngle = getViewAngle
|
|
1045
|
+
|
|
1046
|
+
return ev
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
|
|
1050
|
+
/**
|
|
1051
|
+
* @vue-prop {Object} [options={}] 輸入設定物件,預設{}
|
|
1052
|
+
*/
|
|
1053
|
+
export default {
|
|
1054
|
+
directives: {
|
|
1055
|
+
domresize: domResize(),
|
|
1056
|
+
},
|
|
1057
|
+
components: {
|
|
1058
|
+
},
|
|
1059
|
+
props: {
|
|
1060
|
+
options: {
|
|
1061
|
+
type: Object,
|
|
1062
|
+
default: () => {},
|
|
1063
|
+
},
|
|
1064
|
+
width: {
|
|
1065
|
+
type: Number,
|
|
1066
|
+
default: 400,
|
|
1067
|
+
},
|
|
1068
|
+
height: {
|
|
1069
|
+
type: Number,
|
|
1070
|
+
default: 400,
|
|
1071
|
+
},
|
|
1072
|
+
},
|
|
1073
|
+
data: function() {
|
|
1074
|
+
return {
|
|
1075
|
+
|
|
1076
|
+
ev: null,
|
|
1077
|
+
|
|
1078
|
+
}
|
|
1079
|
+
},
|
|
1080
|
+
beforeDestroy: function() {
|
|
1081
|
+
let vo = this
|
|
1082
|
+
vo.dispose()
|
|
1083
|
+
},
|
|
1084
|
+
computed: {
|
|
1085
|
+
|
|
1086
|
+
changeOptions: function() {
|
|
1087
|
+
// console.log('changeOptions')
|
|
1088
|
+
|
|
1089
|
+
let vo = this
|
|
1090
|
+
|
|
1091
|
+
//plot
|
|
1092
|
+
vo.plot()
|
|
1093
|
+
|
|
1094
|
+
return ''
|
|
1095
|
+
},
|
|
1096
|
+
|
|
1097
|
+
widthInp: function() {
|
|
1098
|
+
//console.log('computed widthInp')
|
|
1099
|
+
|
|
1100
|
+
let vo = this
|
|
1101
|
+
|
|
1102
|
+
//w
|
|
1103
|
+
let w = vo.width
|
|
1104
|
+
let wOpt = get(vo, 'options.width', '')
|
|
1105
|
+
if (isnum(wOpt)) {
|
|
1106
|
+
w = cdbl(wOpt)
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
return w
|
|
1110
|
+
},
|
|
1111
|
+
|
|
1112
|
+
heightInp: function() {
|
|
1113
|
+
//console.log('computed heightInp')
|
|
1114
|
+
|
|
1115
|
+
let vo = this
|
|
1116
|
+
|
|
1117
|
+
//h
|
|
1118
|
+
let h = vo.height
|
|
1119
|
+
let hOpt = get(vo, 'options.height', '')
|
|
1120
|
+
if (isnum(hOpt)) {
|
|
1121
|
+
h = cdbl(hOpt)
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
return h
|
|
1125
|
+
},
|
|
1126
|
+
|
|
1127
|
+
},
|
|
1128
|
+
methods: {
|
|
1129
|
+
|
|
1130
|
+
updatePanel: function(msg) {
|
|
1131
|
+
// console.log('methods updatePanel', msg)
|
|
1132
|
+
|
|
1133
|
+
let vo = this
|
|
1134
|
+
|
|
1135
|
+
//check
|
|
1136
|
+
if (vo.ev === null) {
|
|
1137
|
+
return
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
//resize
|
|
1141
|
+
let fun = get(vo, 'ev.resize')
|
|
1142
|
+
if (isfun(fun)) {
|
|
1143
|
+
|
|
1144
|
+
//resize
|
|
1145
|
+
fun()
|
|
1146
|
+
|
|
1147
|
+
//emit
|
|
1148
|
+
vo.$emit('resize', msg)
|
|
1149
|
+
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
|
|
1153
|
+
},
|
|
1154
|
+
|
|
1155
|
+
plot: function() {
|
|
1156
|
+
// console.log('methods plot')
|
|
1157
|
+
|
|
1158
|
+
let vo = this
|
|
1159
|
+
|
|
1160
|
+
async function core() {
|
|
1161
|
+
|
|
1162
|
+
//dispose
|
|
1163
|
+
vo.dispose()
|
|
1164
|
+
|
|
1165
|
+
//waitFun
|
|
1166
|
+
await waitFun(() => {
|
|
1167
|
+
return isEle(vo.$refs.panel)
|
|
1168
|
+
})
|
|
1169
|
+
// console.log('vo.$refs.panel', vo.$refs.panel)
|
|
1170
|
+
|
|
1171
|
+
//items
|
|
1172
|
+
let items = get(vo, 'options.items', [])
|
|
1173
|
+
// console.log('items', items)
|
|
1174
|
+
|
|
1175
|
+
//plot3d
|
|
1176
|
+
let opt = {
|
|
1177
|
+
...vo.options,
|
|
1178
|
+
domPanel: vo.$refs.panel,
|
|
1179
|
+
}
|
|
1180
|
+
let ev = await plot3d(items, opt)
|
|
1181
|
+
|
|
1182
|
+
//on
|
|
1183
|
+
ev.on('loading', (prog) => {
|
|
1184
|
+
// console.log('loading', prog)
|
|
1185
|
+
vo.$emit('loading', prog)
|
|
1186
|
+
})
|
|
1187
|
+
|
|
1188
|
+
//save
|
|
1189
|
+
vo.ev = ev
|
|
1190
|
+
|
|
1191
|
+
//test
|
|
1192
|
+
setTimeout(() => {
|
|
1193
|
+
console.log('ev.getMeshsInfor()', ev.getMeshsInfor())
|
|
1194
|
+
}, 1000)
|
|
1195
|
+
// setTimeout(() => {
|
|
1196
|
+
// ev.setUseAutoRotate(true)
|
|
1197
|
+
// console.log('ev.setUseAutoRotate(true)')
|
|
1198
|
+
// }, 1500)
|
|
1199
|
+
// setTimeout(() => {
|
|
1200
|
+
// ev.setMeshVisible(0, false)
|
|
1201
|
+
// console.log('ev.setMeshVisible(0, false)')
|
|
1202
|
+
// }, 3000)
|
|
1203
|
+
// setTimeout(() => {
|
|
1204
|
+
// ev.setMeshVisible(0, true)
|
|
1205
|
+
// console.log('ev.setMeshVisible(0, true)')
|
|
1206
|
+
// }, 6000)
|
|
1207
|
+
// setTimeout(() => {
|
|
1208
|
+
// ev.setViewAngle(0, 0) //x-y view
|
|
1209
|
+
// // ev.setViewAngle(0, 90) //x-z view
|
|
1210
|
+
// // ev.setViewAngle(90, 90) //y-z view
|
|
1211
|
+
// console.log('ev.setViewAngle()')
|
|
1212
|
+
// }, 1000)
|
|
1213
|
+
// setInterval(() => {
|
|
1214
|
+
// console.log(`ev.getViewAngle`, ev.getViewAngle())
|
|
1215
|
+
// }, 500)
|
|
1216
|
+
|
|
1217
|
+
// console.log('init')
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
//core
|
|
1221
|
+
core()
|
|
1222
|
+
.catch((err) => {
|
|
1223
|
+
console.log(err)
|
|
1224
|
+
})
|
|
1225
|
+
|
|
1226
|
+
},
|
|
1227
|
+
|
|
1228
|
+
dispose: function() {
|
|
1229
|
+
let vo = this
|
|
1230
|
+
|
|
1231
|
+
//使用setTimeout讓記憶體脫勾, 避免被computed視為連動
|
|
1232
|
+
setTimeout(() => {
|
|
1233
|
+
|
|
1234
|
+
//check
|
|
1235
|
+
if (vo.ev === null) {
|
|
1236
|
+
return
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
//dispose
|
|
1240
|
+
let fun = get(vo, 'ev.dispose')
|
|
1241
|
+
if (isfun(fun)) {
|
|
1242
|
+
vo.ev.dispose()
|
|
1243
|
+
vo.ev = null
|
|
1244
|
+
// console.log('dispose')
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
}, 1)
|
|
1248
|
+
|
|
1249
|
+
},
|
|
1250
|
+
|
|
1251
|
+
},
|
|
1252
|
+
}
|
|
1253
|
+
</script>
|
|
1254
|
+
|
|
1255
|
+
<style scoped>
|
|
1256
|
+
</style>
|