xy-map 1.0.60 → 1.1.1
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/demo.html +1 -0
- package/{src/image/marker.png → img/marker.42b5782a.png} +0 -0
- package/package.json +11 -47
- package/xy-map.common.js +67645 -0
- package/xy-map.css +1 -0
- package/xy-map.umd.js +67664 -0
- package/xy-map.umd.min.js +20 -0
- package/.browserslistrc +0 -3
- package/.eslintignore +0 -1
- package/.eslintrc.js +0 -29
- package/README.md +0 -36
- package/babel.config.js +0 -3
- package/jsconfig.json +0 -12
- package/lint-staged.config.js +0 -3
- package/public/draco/README.md +0 -32
- package/public/draco/draco_decoder.js +0 -52
- package/public/draco/draco_decoder.wasm +0 -0
- package/public/draco/draco_encoder.js +0 -33
- package/public/draco/draco_wasm_wrapper.js +0 -104
- package/public/draco/gltf/draco_decoder.js +0 -48
- package/public/draco/gltf/draco_decoder.wasm +0 -0
- package/public/draco/gltf/draco_encoder.js +0 -33
- package/public/draco/gltf/draco_wasm_wrapper.js +0 -104
- package/public/favicon.ico +0 -0
- package/public/img/MM.png +0 -0
- package/public/img/MM_D.png +0 -0
- package/public/img/MM_W.png +0 -0
- package/public/img/loading.gif +0 -0
- package/public/img/waternormals.jpg +0 -0
- package/public/index.html +0 -29
- package/src/App.vue +0 -13
- package/src/image/arrow_white.png +0 -0
- package/src/image/map_end.png +0 -0
- package/src/image/map_start.png +0 -0
- package/src/index.js +0 -154
- package/src/layers/Line.js +0 -203
- package/src/layers/Point.js +0 -384
- package/src/layers/Polygon.js +0 -119
- package/src/layers/Text.js +0 -53
- package/src/layers/circle.js +0 -148
- package/src/layers/circleAnimate.js +0 -147
- package/src/layers/index.js +0 -128
- package/src/layers/model copy.js +0 -314
- package/src/layers/model.js +0 -341
- package/src/layers/scene.js +0 -314
- package/src/layers/water.js +0 -239
- package/src/map.js +0 -486
- package/src/package/draw/index.vue +0 -239
- package/src/package/draw/line.vue +0 -172
- package/src/package/draw/point.vue +0 -152
- package/src/package/draw/polygon.vue +0 -172
- package/src/package/draw/shpFile.vue +0 -49
- package/src/package/draw/styles.js +0 -162
- package/src/package/mapFullScreen.vue +0 -105
- package/src/package/mapLoad.vue +0 -120
- package/src/package/mapMarker.vue +0 -50
- package/src/package/mapModel.vue +0 -69
- package/src/package/mapRain.vue +0 -110
- package/src/style/hoverHtml.css +0 -29
- package/src/style/main.scss +0 -186
- package/src/style/map.css +0 -7
- package/src/util/gaodeApi.js +0 -67
- package/src/util/mapEvent.js +0 -111
- package/src/util/mapHoverHtml.js +0 -59
- package/src/util/mapTools.js +0 -169
- package/src/util/measure-area.js +0 -215
- package/src/util/measure-distance.js +0 -600
- package/vue.config.js +0 -32
package/src/layers/model.js
DELETED
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
import mapSdk from '../map'
|
|
2
|
-
import * as THREE from 'three'
|
|
3
|
-
import * as dat from 'dat.gui'
|
|
4
|
-
import {
|
|
5
|
-
GLTFLoader
|
|
6
|
-
} from 'three/examples/jsm/loaders/GLTFLoader'
|
|
7
|
-
import {
|
|
8
|
-
EffectComposer
|
|
9
|
-
} from 'three/examples/jsm/postprocessing/EffectComposer'
|
|
10
|
-
import {
|
|
11
|
-
RenderPass
|
|
12
|
-
} from 'three/examples/jsm/postprocessing/RenderPass'
|
|
13
|
-
import {
|
|
14
|
-
DRACOLoader
|
|
15
|
-
} from 'three/examples/jsm/loaders/DRACOLoader'
|
|
16
|
-
import { // 环境贴图
|
|
17
|
-
RGBELoader
|
|
18
|
-
} from 'three/examples/jsm/loaders/RGBELoader'
|
|
19
|
-
import {
|
|
20
|
-
Water
|
|
21
|
-
} from 'three/examples/jsm/objects/Water'
|
|
22
|
-
import {
|
|
23
|
-
FXAAShader
|
|
24
|
-
} from 'three/examples/jsm/shaders/FXAAShader'
|
|
25
|
-
import {
|
|
26
|
-
ShaderPass
|
|
27
|
-
} from 'three/examples/jsm/postprocessing/ShaderPass'
|
|
28
|
-
import {
|
|
29
|
-
OutlinePass
|
|
30
|
-
} from 'three/examples/jsm/postprocessing/OutlinePass'
|
|
31
|
-
import {
|
|
32
|
-
CSS2DRenderer
|
|
33
|
-
} from 'three/examples/jsm/renderers/CSS2DRenderer'
|
|
34
|
-
|
|
35
|
-
import mapBoxGl from 'mapbox-gl'
|
|
36
|
-
|
|
37
|
-
import {
|
|
38
|
-
hasLayer,
|
|
39
|
-
removeLayer
|
|
40
|
-
} from './index'
|
|
41
|
-
|
|
42
|
-
const defaultOptions = {
|
|
43
|
-
id: '3dModel',
|
|
44
|
-
path: '',
|
|
45
|
-
position: [103.353557, 23.362395], // 位置
|
|
46
|
-
height: 0, // 海拔高度
|
|
47
|
-
directionalLight: [{
|
|
48
|
-
color: 0xfffcce,
|
|
49
|
-
intensity: 1,
|
|
50
|
-
position: [-4100, 3000, -1800],
|
|
51
|
-
shadow: {},
|
|
52
|
-
}],
|
|
53
|
-
ambientLight: {
|
|
54
|
-
color: 0xFFFFFF,
|
|
55
|
-
intensity: 0.2,
|
|
56
|
-
},
|
|
57
|
-
shadow: false,
|
|
58
|
-
edit: false,
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* 添加模型
|
|
63
|
-
*/
|
|
64
|
-
export const addLayerModel = (option, layerId = '') => {
|
|
65
|
-
return new Promise((resolve) => {
|
|
66
|
-
let {
|
|
67
|
-
map
|
|
68
|
-
} = mapSdk
|
|
69
|
-
|
|
70
|
-
let opt = Object.assign({}, defaultOptions, option)
|
|
71
|
-
let id = opt.id
|
|
72
|
-
|
|
73
|
-
let camera = ''
|
|
74
|
-
let scene = ''
|
|
75
|
-
let renderer = ''
|
|
76
|
-
let customLayer = ''
|
|
77
|
-
let labelRenderer = ''
|
|
78
|
-
let composer = ''
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (hasLayer(id)) {
|
|
82
|
-
removeLayer(id)
|
|
83
|
-
}
|
|
84
|
-
addModel(id)
|
|
85
|
-
map.addLayer(customLayer, layerId)
|
|
86
|
-
|
|
87
|
-
resolve(scene)
|
|
88
|
-
|
|
89
|
-
function addModel() {
|
|
90
|
-
const modelOrigin = opt.position // 中心点
|
|
91
|
-
const modelAltitude = opt.height // 高度
|
|
92
|
-
const modelRotate = [Math.PI / 2, 0, 0]
|
|
93
|
-
|
|
94
|
-
const modelAsMercatorCoordinate = mapBoxGl.MercatorCoordinate.fromLngLat(
|
|
95
|
-
modelOrigin,
|
|
96
|
-
modelAltitude
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
const modelTransform = {
|
|
100
|
-
translateX: modelAsMercatorCoordinate.x,
|
|
101
|
-
translateY: modelAsMercatorCoordinate.y,
|
|
102
|
-
translateZ: modelAsMercatorCoordinate.z,
|
|
103
|
-
rotateX: modelRotate[0],
|
|
104
|
-
rotateY: modelRotate[1],
|
|
105
|
-
rotateZ: modelRotate[2],
|
|
106
|
-
scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// 根据CustomLayerInterface为三维模型配置自定义层
|
|
110
|
-
customLayer = {
|
|
111
|
-
id: opt.id,
|
|
112
|
-
type: 'custom',
|
|
113
|
-
renderingMode: '3d',
|
|
114
|
-
onAdd: (map, gl) => {
|
|
115
|
-
const gui = opt.edit ? new dat.GUI() : null
|
|
116
|
-
const container = map.getCanvas()
|
|
117
|
-
|
|
118
|
-
// 摄像机
|
|
119
|
-
camera = new THREE.PerspectiveCamera(50, container.clientWidth / container.clientHeight, 0.01, 50000000)
|
|
120
|
-
// camera = new THREE.Camera()
|
|
121
|
-
// 场景
|
|
122
|
-
scene = new THREE.Scene()
|
|
123
|
-
// scene.background = new THREE.Color('rgba(255,255,255, 0)')
|
|
124
|
-
|
|
125
|
-
// 辅助坐标轴
|
|
126
|
-
// if (gui) {
|
|
127
|
-
// let AxesHelper = new THREE.AxesHelper(100)
|
|
128
|
-
// AxesHelper.position.y = opt.translate[1]
|
|
129
|
-
// scene.add(AxesHelper)
|
|
130
|
-
// }
|
|
131
|
-
|
|
132
|
-
// 创建灯光
|
|
133
|
-
if (opt.directionalLight && opt.directionalLight.length > 0) {
|
|
134
|
-
opt.directionalLight.forEach((item, index) => {
|
|
135
|
-
let position = {
|
|
136
|
-
x: item.position[0],
|
|
137
|
-
y: item.position[1],
|
|
138
|
-
z: item.position[2],
|
|
139
|
-
}
|
|
140
|
-
const directionalLight = new THREE.DirectionalLight(item.color, item.intensity)
|
|
141
|
-
directionalLight.position.set(position.x, position.y, position.z)
|
|
142
|
-
directionalLight.width = 1
|
|
143
|
-
directionalLight.height = 1
|
|
144
|
-
// directionalLight.distance = 0
|
|
145
|
-
// directionalLight.decay = 0 // 衰减强度
|
|
146
|
-
// directionalLight.exponent = 0 // 衰减速度
|
|
147
|
-
// directionalLight.angle = 0 // 光源角度
|
|
148
|
-
directionalLight.castShadow = true
|
|
149
|
-
|
|
150
|
-
// 开启编辑模式
|
|
151
|
-
if (gui) {
|
|
152
|
-
const lightGui = gui.addFolder('灯光' + (index + 1))
|
|
153
|
-
lightGui.addColor(item, 'color').name('颜色').onChange(val => directionalLight.color = new THREE.Color(val))
|
|
154
|
-
lightGui.add(item, 'intensity').min(0).step(0.1).name('强度').onChange(val => directionalLight.intensity = val)
|
|
155
|
-
lightGui.add(position, 'x').step(100).name('x').onChange(val => directionalLight.position.x = val)
|
|
156
|
-
lightGui.add(position, 'y').step(100).name('y').onChange(val => directionalLight.position.y = val)
|
|
157
|
-
lightGui.add(position, 'z').step(100).name('z').onChange(val => directionalLight.position.z = val)
|
|
158
|
-
lightGui.open()
|
|
159
|
-
|
|
160
|
-
let pointLightHelper = new THREE.DirectionalLightHelper(directionalLight, 1000)
|
|
161
|
-
scene.add(pointLightHelper)
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// 开启阴影
|
|
165
|
-
let shadow = Object.assign({
|
|
166
|
-
size: 2000,
|
|
167
|
-
near: 1,
|
|
168
|
-
far: 8000,
|
|
169
|
-
clarity: 14, // 阴影清晰度 0-20
|
|
170
|
-
bias: -0.0005
|
|
171
|
-
}, item.shadow)
|
|
172
|
-
if (shadow) {
|
|
173
|
-
directionalLight.castShadow = true
|
|
174
|
-
const d = shadow.size || 1000 //阴影范围
|
|
175
|
-
directionalLight.shadow.camera.left = -d
|
|
176
|
-
directionalLight.shadow.camera.right = d
|
|
177
|
-
directionalLight.shadow.camera.top = d
|
|
178
|
-
directionalLight.shadow.camera.bottom = -d
|
|
179
|
-
directionalLight.shadow.camera.near = shadow.near || 1
|
|
180
|
-
directionalLight.shadow.camera.far = shadow.far || 8000
|
|
181
|
-
directionalLight.shadow.mapSize.width = 2 ** shadow.clarity // 定义阴影贴图的宽度和高度,必须为2的整数此幂
|
|
182
|
-
directionalLight.shadow.mapSize.height = 2 ** shadow.clarity // 较高的值会以计算时间为代价提供更好的阴影质量
|
|
183
|
-
directionalLight.shadow.bias = shadow.bias || -0.05 //解决条纹阴影的出现
|
|
184
|
-
}
|
|
185
|
-
scene.add(directionalLight)
|
|
186
|
-
})
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// 环境光
|
|
190
|
-
if (opt.ambientLight) {
|
|
191
|
-
let item = {
|
|
192
|
-
color: opt.ambientLight.color,
|
|
193
|
-
intensity: opt.ambientLight.intensity
|
|
194
|
-
}
|
|
195
|
-
let ambientLight = new THREE.AmbientLight(item.color, item.intensity)
|
|
196
|
-
if (gui) {
|
|
197
|
-
const lightGui = gui.addFolder('环境光')
|
|
198
|
-
lightGui.addColor(item, 'color').name('颜色').onChange(val => ambientLight.color = new THREE.Color(val))
|
|
199
|
-
lightGui.add(item, 'intensity').min(0).step(0.1).name('强度').onChange(val => ambientLight.intensity = val)
|
|
200
|
-
lightGui.open()
|
|
201
|
-
}
|
|
202
|
-
scene.add(ambientLight)
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// 渲染器
|
|
206
|
-
renderer = new THREE.WebGLRenderer({
|
|
207
|
-
canvas: map.getCanvas(),
|
|
208
|
-
context: gl,
|
|
209
|
-
antialias: true,
|
|
210
|
-
alpha: true,
|
|
211
|
-
// precision: 'lowp',
|
|
212
|
-
// logarithmicDepthBuffer: true
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
// 创建一个EffectComposer(效果组合器)对象,然后在该对象上添加后期处理通道。
|
|
216
|
-
// composer = new EffectComposer(renderer)
|
|
217
|
-
// composer.setSize(container.clientWidth, container.clientHeight)
|
|
218
|
-
|
|
219
|
-
// 去掉锯齿
|
|
220
|
-
// let effectFXAA = new ShaderPass(FXAAShader)
|
|
221
|
-
// effectFXAA.uniforms['resolution'].value.set(1 / container.clientWidth, 1 / container.clientHeight)
|
|
222
|
-
// effectFXAA.renderToScreen = true
|
|
223
|
-
// composer.addPass(effectFXAA)
|
|
224
|
-
|
|
225
|
-
// let renderPass = new RenderPass(scene, camera)
|
|
226
|
-
// composer.addPass(renderPass)
|
|
227
|
-
|
|
228
|
-
// 处理阴影
|
|
229
|
-
if (opt.shadow) {
|
|
230
|
-
renderer.shadowMap.enabled = true
|
|
231
|
-
renderer.shadowMap.type = THREE.PCFSoftShadowMap
|
|
232
|
-
}
|
|
233
|
-
renderer.autoClear = false
|
|
234
|
-
renderer.outputEncoding = THREE.sRGBEncoding
|
|
235
|
-
renderer.setPixelRatio(window.devicePixelRatio)
|
|
236
|
-
renderer.setSize(container.clientWidth, container.clientHeight)
|
|
237
|
-
// renderer.gammaOutput = true
|
|
238
|
-
// renderer.physicallyCorrectLights = true
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
// css2渲染器创建
|
|
242
|
-
labelRenderer = new CSS2DRenderer()
|
|
243
|
-
labelRenderer.setSize(container.clientWidth, container.clientHeight)
|
|
244
|
-
container.appendChild(labelRenderer.domElement)
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
// 缩放比例调整
|
|
248
|
-
window.addEventListener('resize', () => {
|
|
249
|
-
renderer.setSize(container.clientWidth, container.clientHeight)
|
|
250
|
-
camera.aspect = container.clientWidth / container.clientHeight
|
|
251
|
-
camera.updateProjectionMatrix()
|
|
252
|
-
})
|
|
253
|
-
|
|
254
|
-
// loadHDR()
|
|
255
|
-
// getIntersects() // 点击事件
|
|
256
|
-
},
|
|
257
|
-
render: cameraUpdate
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
return customLayer
|
|
261
|
-
|
|
262
|
-
function loadHDR() {
|
|
263
|
-
new RGBELoader().setPath('/model/hdr/').load('hdr1.hdr', (texture) => {
|
|
264
|
-
texture.mapping = THREE.EquirectangularReflectionMapping
|
|
265
|
-
scene.background = texture
|
|
266
|
-
scene.environment = texture
|
|
267
|
-
})
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// 渲染摄像机
|
|
271
|
-
function cameraUpdate(gl, matrix) {
|
|
272
|
-
const rotationX = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), modelTransform.rotateX)
|
|
273
|
-
const rotationY = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), modelTransform.rotateY)
|
|
274
|
-
const rotationZ = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 0, 1), modelTransform.rotateZ)
|
|
275
|
-
|
|
276
|
-
const m = new THREE.Matrix4().fromArray(matrix)
|
|
277
|
-
const l = new THREE.Matrix4().makeTranslation(
|
|
278
|
-
modelTransform.translateX,
|
|
279
|
-
modelTransform.translateY,
|
|
280
|
-
modelTransform.translateZ
|
|
281
|
-
).scale(new THREE.Vector3(
|
|
282
|
-
modelTransform.scale,
|
|
283
|
-
-modelTransform.scale,
|
|
284
|
-
modelTransform.scale
|
|
285
|
-
)).multiply(rotationX)
|
|
286
|
-
.multiply(rotationY)
|
|
287
|
-
.multiply(rotationZ)
|
|
288
|
-
|
|
289
|
-
camera.projectionMatrix.elements = matrix
|
|
290
|
-
camera.projectionMatrix = m.multiply(l)
|
|
291
|
-
|
|
292
|
-
// renderer.toneMapping = THREE.ACESFilmicToneMapping
|
|
293
|
-
// renderer.toneMappingExposure = 1.5
|
|
294
|
-
|
|
295
|
-
renderer.resetState()
|
|
296
|
-
renderer.render(scene, camera)
|
|
297
|
-
// composer.render()
|
|
298
|
-
labelRenderer.render(scene, camera)
|
|
299
|
-
map.triggerRepaint()
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// 点击事件
|
|
303
|
-
function getIntersects() {
|
|
304
|
-
const container = map.getCanvas()
|
|
305
|
-
|
|
306
|
-
container.addEventListener('click', (event) => {
|
|
307
|
-
event.preventDefault()
|
|
308
|
-
|
|
309
|
-
// 声明 raycaster 和 mouse 变量
|
|
310
|
-
let raycaster = new THREE.Raycaster()
|
|
311
|
-
let mouse = new THREE.Vector2()
|
|
312
|
-
|
|
313
|
-
// 通过鼠标点击位置,计算出 raycaster 所需点的位置,以屏幕为中心点,范围 -1 到 1
|
|
314
|
-
mouse.x = (event.layerX / container.clientWidth) * 2 - 1
|
|
315
|
-
mouse.y = -(event.layerY / container.clientHeight) * 2 + 1
|
|
316
|
-
|
|
317
|
-
//通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
|
|
318
|
-
raycaster.setFromCamera(mouse, camera)
|
|
319
|
-
|
|
320
|
-
// 获取与射线相交的对象数组,其中的元素按照距离排序,越近的越靠前
|
|
321
|
-
let meshArr = []
|
|
322
|
-
findMesh(scene.children)
|
|
323
|
-
let intersects = raycaster.intersectObjects(meshArr, true)
|
|
324
|
-
|
|
325
|
-
// 获取所有mesh
|
|
326
|
-
function findMesh(list) {
|
|
327
|
-
list.forEach(item => {
|
|
328
|
-
if (item.children.length > 0) {
|
|
329
|
-
findMesh(item.children)
|
|
330
|
-
} else {
|
|
331
|
-
meshArr.push(item)
|
|
332
|
-
}
|
|
333
|
-
})
|
|
334
|
-
}
|
|
335
|
-
console.log(intersects)
|
|
336
|
-
return intersects
|
|
337
|
-
})
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
})
|
|
341
|
-
}
|
package/src/layers/scene.js
DELETED
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
import mapSdk from '../map'
|
|
2
|
-
import * as THREE from 'three'
|
|
3
|
-
import * as dat from 'dat.gui'
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
EffectComposer
|
|
7
|
-
} from 'three/examples/jsm/postprocessing/EffectComposer'
|
|
8
|
-
import {
|
|
9
|
-
RenderPass
|
|
10
|
-
} from 'three/examples/jsm/postprocessing/RenderPass'
|
|
11
|
-
import {
|
|
12
|
-
Sky
|
|
13
|
-
} from 'three/examples/jsm/objects/Sky'
|
|
14
|
-
// import {
|
|
15
|
-
// RoomEnvironment
|
|
16
|
-
// } from 'three/examples/jsm/environments/RoomEnvironment'
|
|
17
|
-
// import { // 环境贴图
|
|
18
|
-
// RGBELoader
|
|
19
|
-
// } from 'three/examples/jsm/loaders/RGBELoader'
|
|
20
|
-
|
|
21
|
-
import mapBoxGl from 'mapbox-gl'
|
|
22
|
-
|
|
23
|
-
import {
|
|
24
|
-
hasLayer,
|
|
25
|
-
removeLayer
|
|
26
|
-
} from './index'
|
|
27
|
-
|
|
28
|
-
const defaultOptions = {
|
|
29
|
-
id: '3dModel',
|
|
30
|
-
path: '/img/30.gltf',
|
|
31
|
-
position: [103.353557, 23.362395], // 位置
|
|
32
|
-
directionalLight: [{
|
|
33
|
-
color: 0xfffcce,
|
|
34
|
-
intensity: 1,
|
|
35
|
-
position: [-4100, 3000, -1800],
|
|
36
|
-
shadow: {},
|
|
37
|
-
}],
|
|
38
|
-
ambientLight: {
|
|
39
|
-
color: 0xFFFFFF,
|
|
40
|
-
intensity: 0.2,
|
|
41
|
-
},
|
|
42
|
-
sky: {
|
|
43
|
-
size: 1000000,
|
|
44
|
-
box: [1, 1, 0]
|
|
45
|
-
},
|
|
46
|
-
shadow: false,
|
|
47
|
-
edit: false,
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* 添加场景
|
|
52
|
-
*/
|
|
53
|
-
export const addLayerScene = (option, layerId = '') => {
|
|
54
|
-
return new Promise((resolve) => {
|
|
55
|
-
let {
|
|
56
|
-
map
|
|
57
|
-
} = mapSdk
|
|
58
|
-
|
|
59
|
-
let opt = Object.assign({}, defaultOptions, option)
|
|
60
|
-
let id = opt.id
|
|
61
|
-
|
|
62
|
-
let camera = ''
|
|
63
|
-
let scene = ''
|
|
64
|
-
let renderer = ''
|
|
65
|
-
let customLayer = ''
|
|
66
|
-
let sun = opt.sky && opt.sky.box ? new THREE.Vector3(opt.sky.box[0], opt.sky.box[1], opt.sky.box[2]) : new THREE.Vector3(1, 1, 0)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (hasLayer(id)) {
|
|
70
|
-
removeLayer(id)
|
|
71
|
-
}
|
|
72
|
-
addModel(id)
|
|
73
|
-
map.addLayer(customLayer, layerId)
|
|
74
|
-
|
|
75
|
-
resolve({
|
|
76
|
-
scene,
|
|
77
|
-
sun
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
function addModel() {
|
|
81
|
-
const modelOrigin = opt.position // 中心点
|
|
82
|
-
const modelAltitude = 0 // 高度
|
|
83
|
-
const modelRotate = [Math.PI / 2, 0, 0]
|
|
84
|
-
|
|
85
|
-
const modelAsMercatorCoordinate = mapBoxGl.MercatorCoordinate.fromLngLat(
|
|
86
|
-
modelOrigin,
|
|
87
|
-
modelAltitude
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
const modelTransform = {
|
|
91
|
-
translateX: modelAsMercatorCoordinate.x,
|
|
92
|
-
translateY: modelAsMercatorCoordinate.y,
|
|
93
|
-
translateZ: modelAsMercatorCoordinate.z,
|
|
94
|
-
rotateX: modelRotate[0],
|
|
95
|
-
rotateY: modelRotate[1],
|
|
96
|
-
rotateZ: modelRotate[2],
|
|
97
|
-
scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// 根据CustomLayerInterface为三维模型配置自定义层
|
|
101
|
-
customLayer = {
|
|
102
|
-
id: opt.id,
|
|
103
|
-
type: 'custom',
|
|
104
|
-
renderingMode: '3d',
|
|
105
|
-
onAdd: (map, gl) => {
|
|
106
|
-
const gui = opt.edit ? new dat.GUI() : null
|
|
107
|
-
const container = map.getCanvas()
|
|
108
|
-
|
|
109
|
-
// 摄像机
|
|
110
|
-
camera = new THREE.PerspectiveCamera(70, container.clientWidth / container.clientHeight, 1, 5000)
|
|
111
|
-
// camera = new THREE.Camera()
|
|
112
|
-
// 场景
|
|
113
|
-
scene = new THREE.Scene()
|
|
114
|
-
|
|
115
|
-
// 辅助坐标轴
|
|
116
|
-
// if (gui) {
|
|
117
|
-
// let AxesHelper = new THREE.AxesHelper(100)
|
|
118
|
-
// AxesHelper.position.y = opt.translate[1]
|
|
119
|
-
// scene.add(AxesHelper)
|
|
120
|
-
// }
|
|
121
|
-
|
|
122
|
-
// 创建灯光
|
|
123
|
-
if (opt.directionalLight && opt.directionalLight.length > 0) {
|
|
124
|
-
opt.directionalLight.forEach((item, index) => {
|
|
125
|
-
let position = {
|
|
126
|
-
x: item.position[0],
|
|
127
|
-
y: item.position[1],
|
|
128
|
-
z: item.position[2],
|
|
129
|
-
}
|
|
130
|
-
const directionalLight = new THREE.DirectionalLight(item.color, item.intensity)
|
|
131
|
-
directionalLight.position.set(position.x, position.y, position.z)
|
|
132
|
-
directionalLight.width = 1
|
|
133
|
-
directionalLight.height = 1
|
|
134
|
-
// directionalLight.distance = 0
|
|
135
|
-
// directionalLight.decay = 0 // 衰减强度
|
|
136
|
-
// directionalLight.exponent = 0 // 衰减速度
|
|
137
|
-
// directionalLight.angle = 0 // 光源角度
|
|
138
|
-
directionalLight.castShadow = true
|
|
139
|
-
|
|
140
|
-
// 开启编辑模式
|
|
141
|
-
if (gui) {
|
|
142
|
-
const lightGui = gui.addFolder('灯光' + (index + 1))
|
|
143
|
-
lightGui.addColor(item, 'color').name('颜色').onChange(val => directionalLight.color = new THREE.Color(val))
|
|
144
|
-
lightGui.add(item, 'intensity').min(0).step(0.1).name('强度').onChange(val => directionalLight.intensity = val)
|
|
145
|
-
lightGui.add(position, 'x').step(100).name('x').onChange(val => directionalLight.position.x = val)
|
|
146
|
-
lightGui.add(position, 'y').step(100).name('y').onChange(val => directionalLight.position.y = val)
|
|
147
|
-
lightGui.add(position, 'z').step(100).name('z').onChange(val => directionalLight.position.z = val)
|
|
148
|
-
lightGui.open()
|
|
149
|
-
|
|
150
|
-
let pointLightHelper = new THREE.DirectionalLightHelper(directionalLight, 1000)
|
|
151
|
-
scene.add(pointLightHelper)
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// 开启阴影
|
|
155
|
-
let shadow = Object.assign({
|
|
156
|
-
size: 2000,
|
|
157
|
-
near: 1,
|
|
158
|
-
far: 8000,
|
|
159
|
-
clarity: 14, // 阴影清晰度 0-20
|
|
160
|
-
bias: -0.0005
|
|
161
|
-
}, item.shadow)
|
|
162
|
-
if (shadow) {
|
|
163
|
-
directionalLight.castShadow = true
|
|
164
|
-
const d = shadow.size || 1000 //阴影范围
|
|
165
|
-
directionalLight.shadow.camera.left = -d
|
|
166
|
-
directionalLight.shadow.camera.right = d
|
|
167
|
-
directionalLight.shadow.camera.top = d
|
|
168
|
-
directionalLight.shadow.camera.bottom = -d
|
|
169
|
-
directionalLight.shadow.camera.near = shadow.near || 1
|
|
170
|
-
directionalLight.shadow.camera.far = shadow.far || 8000
|
|
171
|
-
directionalLight.shadow.mapSize.width = 2 ** shadow.clarity // 定义阴影贴图的宽度和高度,必须为2的整数此幂
|
|
172
|
-
directionalLight.shadow.mapSize.height = 2 ** shadow.clarity // 较高的值会以计算时间为代价提供更好的阴影质量
|
|
173
|
-
directionalLight.shadow.bias = shadow.bias || -0.05 //解决条纹阴影的出现
|
|
174
|
-
}
|
|
175
|
-
scene.add(directionalLight)
|
|
176
|
-
})
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// 环境光
|
|
180
|
-
if (opt.ambientLight) {
|
|
181
|
-
let item = {
|
|
182
|
-
color: opt.ambientLight.color,
|
|
183
|
-
intensity: opt.ambientLight.intensity
|
|
184
|
-
}
|
|
185
|
-
let ambientLight = new THREE.AmbientLight(item.color, item.intensity)
|
|
186
|
-
if (gui) {
|
|
187
|
-
const lightGui = gui.addFolder('环境光')
|
|
188
|
-
lightGui.addColor(item, 'color').name('颜色').onChange(val => ambientLight.color = new THREE.Color(val))
|
|
189
|
-
lightGui.add(item, 'intensity').min(0).step(0.1).name('强度').onChange(val => ambientLight.intensity = val)
|
|
190
|
-
lightGui.open()
|
|
191
|
-
}
|
|
192
|
-
scene.add(ambientLight)
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// 创建天空
|
|
196
|
-
if (opt.sky) {
|
|
197
|
-
let sky = new Sky()
|
|
198
|
-
sky.scale.setScalar(opt.sky.size || 1000000)
|
|
199
|
-
let uniforms = sky.material.uniforms
|
|
200
|
-
uniforms['sunPosition'].value.copy(sun)
|
|
201
|
-
scene.add(sky)
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// 渲染器
|
|
205
|
-
renderer = new THREE.WebGLRenderer({
|
|
206
|
-
canvas: map.getCanvas(),
|
|
207
|
-
context: gl,
|
|
208
|
-
antialias: true,
|
|
209
|
-
// logarithmicDepthBuffer: true
|
|
210
|
-
})
|
|
211
|
-
|
|
212
|
-
// 创建一个EffectComposer(效果组合器)对象,然后在该对象上添加后期处理通道。
|
|
213
|
-
let composer = new EffectComposer(renderer)
|
|
214
|
-
composer.setSize(container.clientWidth, container.clientHeight)
|
|
215
|
-
|
|
216
|
-
let renderPass = new RenderPass(scene, camera)
|
|
217
|
-
composer.addPass(renderPass)
|
|
218
|
-
|
|
219
|
-
// 处理阴影
|
|
220
|
-
if (opt.shadow) {
|
|
221
|
-
renderer.shadowMap.enabled = true
|
|
222
|
-
renderer.shadowMap.type = THREE.PCFSoftShadowMap
|
|
223
|
-
}
|
|
224
|
-
renderer.autoClear = false
|
|
225
|
-
renderer.outputEncoding = THREE.sRGBEncoding
|
|
226
|
-
renderer.setSize(container.clientWidth, container.clientHeight)
|
|
227
|
-
|
|
228
|
-
// RoomEnvironment
|
|
229
|
-
// const pmremGenerator = new THREE.PMREMGenerator(renderer)
|
|
230
|
-
// scene.environment = pmremGenerator.fromScene(new RoomEnvironment(), 0.001).texture
|
|
231
|
-
|
|
232
|
-
// 缩放比例调整
|
|
233
|
-
// window.addEventListener('resize', () => {
|
|
234
|
-
// renderer.setSize(container.clientWidth, container.clientHeight)
|
|
235
|
-
// camera.aspect = container.clientWidth / container.clientHeight
|
|
236
|
-
// camera.updateProjectionMatrix()
|
|
237
|
-
// })
|
|
238
|
-
|
|
239
|
-
// getIntersects() // 点击事件
|
|
240
|
-
},
|
|
241
|
-
render: cameraUpdate
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
return customLayer
|
|
245
|
-
|
|
246
|
-
// 渲染摄像机
|
|
247
|
-
function cameraUpdate(gl, matrix) {
|
|
248
|
-
const rotationX = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(1, 0, 0), modelTransform.rotateX)
|
|
249
|
-
const rotationY = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 1, 0), modelTransform.rotateY)
|
|
250
|
-
const rotationZ = new THREE.Matrix4().makeRotationAxis(new THREE.Vector3(0, 0, 1), modelTransform.rotateZ)
|
|
251
|
-
|
|
252
|
-
const m = new THREE.Matrix4().fromArray(matrix)
|
|
253
|
-
const l = new THREE.Matrix4().makeTranslation(
|
|
254
|
-
modelTransform.translateX,
|
|
255
|
-
modelTransform.translateY,
|
|
256
|
-
modelTransform.translateZ
|
|
257
|
-
).scale(new THREE.Vector3(
|
|
258
|
-
modelTransform.scale,
|
|
259
|
-
-modelTransform.scale,
|
|
260
|
-
modelTransform.scale
|
|
261
|
-
)).multiply(rotationX)
|
|
262
|
-
.multiply(rotationY)
|
|
263
|
-
.multiply(rotationZ)
|
|
264
|
-
|
|
265
|
-
camera.projectionMatrix.elements = matrix
|
|
266
|
-
camera.projectionMatrix = m.multiply(l)
|
|
267
|
-
|
|
268
|
-
renderer.toneMapping = THREE.ACESFilmicToneMapping
|
|
269
|
-
|
|
270
|
-
renderer.resetState()
|
|
271
|
-
renderer.render(scene, camera)
|
|
272
|
-
map.triggerRepaint()
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// 点击事件
|
|
276
|
-
function getIntersects() {
|
|
277
|
-
const container = map.getCanvas()
|
|
278
|
-
|
|
279
|
-
container.addEventListener('click', (event) => {
|
|
280
|
-
event.preventDefault()
|
|
281
|
-
|
|
282
|
-
// 声明 raycaster 和 mouse 变量
|
|
283
|
-
let raycaster = new THREE.Raycaster()
|
|
284
|
-
let mouse = new THREE.Vector2()
|
|
285
|
-
|
|
286
|
-
// 通过鼠标点击位置,计算出 raycaster 所需点的位置,以屏幕为中心点,范围 -1 到 1
|
|
287
|
-
mouse.x = (event.layerX / container.clientWidth) * 2 - 1
|
|
288
|
-
mouse.y = -(event.layerY / container.clientHeight) * 2 + 1
|
|
289
|
-
|
|
290
|
-
//通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
|
|
291
|
-
raycaster.setFromCamera(mouse, camera)
|
|
292
|
-
|
|
293
|
-
// 获取与射线相交的对象数组,其中的元素按照距离排序,越近的越靠前
|
|
294
|
-
let meshArr = []
|
|
295
|
-
findMesh(scene.children)
|
|
296
|
-
let intersects = raycaster.intersectObjects(meshArr, true)
|
|
297
|
-
|
|
298
|
-
// 获取所有mesh
|
|
299
|
-
function findMesh(list) {
|
|
300
|
-
list.forEach(item => {
|
|
301
|
-
if (item.children.length > 0) {
|
|
302
|
-
findMesh(item.children)
|
|
303
|
-
} else {
|
|
304
|
-
meshArr.push(item)
|
|
305
|
-
}
|
|
306
|
-
})
|
|
307
|
-
}
|
|
308
|
-
console.log(intersects)
|
|
309
|
-
return intersects
|
|
310
|
-
})
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
})
|
|
314
|
-
}
|