286 lines
9.5 KiB
JavaScript
286 lines
9.5 KiB
JavaScript
|
||
import * as THREE from 'three';
|
||
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
||
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
|
||
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
|
||
import { RGBELoader } from 'three/addons/loaders/RGBELoader.js';
|
||
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
|
||
import { FontLoader } from 'three/addons/loaders/FontLoader.js';
|
||
export default class ParkingAreaMap3d {
|
||
|
||
constructor(_element) {
|
||
this._initScene(_element);
|
||
this.shapes = [];
|
||
}
|
||
|
||
|
||
/**
|
||
* 初始化场景
|
||
*/
|
||
initScene() {
|
||
this.scene = new THREE.Scene();
|
||
}
|
||
/**
|
||
* 初始化相机
|
||
*/
|
||
initCamera() {
|
||
this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
|
||
// position and point the camera to the center of the scene
|
||
this.camera.position.z = 5;
|
||
//this.camera.lookAt(this.scene.position);
|
||
}
|
||
|
||
/**
|
||
* 初始化渲染器
|
||
*/
|
||
initRenderer(_element) {
|
||
// create a render and set the size
|
||
this.renderer = new THREE.WebGLRenderer();
|
||
this.renderer.setClearColor(new THREE.Color(0xFFFFFF));
|
||
this.renderer.setSize(window.innerWidth, window.innerHeight);
|
||
this.renderer.antialias = true;
|
||
|
||
this.renderer.alpha = true;
|
||
|
||
this.renderer.precision = 'mediump'
|
||
// add the output of the renderer to the html element
|
||
this.container = document.getElementById(_element);
|
||
this.container.appendChild(this.renderer.domElement);
|
||
}
|
||
|
||
initControls() {
|
||
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
|
||
// 设置控制器阻尼,让控制器更有真是效果,必须在动画循环里调用update()
|
||
//this.controls.enableDamping = true;
|
||
// 禁用旋转功能
|
||
this.controls.enableRotate = false;
|
||
this.controls.minPolarAngle = 0;
|
||
this.controls.maxPolarAngle = 90 / 180 * Math.PI;
|
||
|
||
}
|
||
|
||
/**
|
||
* 初始化灯光
|
||
*/
|
||
initLight() {
|
||
this.light = new THREE.SpotLight(0xffffff);
|
||
this.light.position.set(-300, 600, -400);
|
||
this.light.castShadow = true;
|
||
this.scene.add(this.light);
|
||
this.scene.add(new THREE.AmbientLight(0x404040));
|
||
}
|
||
|
||
update() {
|
||
this.controls.update();
|
||
|
||
this.upDownShap();
|
||
}
|
||
|
||
_initScene(_element) {
|
||
|
||
this.initScene();
|
||
this.initCamera();
|
||
this.initRenderer(_element);
|
||
this.initLight();
|
||
this.initControls();
|
||
|
||
let _that = this;
|
||
function animate() {
|
||
requestAnimationFrame(animate);
|
||
_that.renderer.render(_that.scene, _that.camera);
|
||
_that.update(_that);
|
||
}
|
||
animate();
|
||
|
||
// addEventListener('click', function (event) {
|
||
// _that.onMouseDblclick(event, _that)
|
||
// }, false);
|
||
// window.addEventListener('mousemove', function (event) {
|
||
// _that.onMouseMove(event, _that)
|
||
// }, false);
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
getObjectByName(_objName) {
|
||
return this.scene.getObjectByName(_objName);
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
getObjectPosition(targetObject) {
|
||
let targetCenter = new THREE.Vector3();
|
||
// targetObject.updateMatrixWorld(true); // 确保目标物体的世界矩阵是最新的
|
||
// targetObject.getWorldPosition(targetCenter); // 将目标物体的世界位置存储到 targetCenter 中
|
||
// // 将源物体的位置设置为目标物体的中心位置
|
||
// console.log(targetCenter);
|
||
let box = new THREE.Box3().setFromObject(targetObject);
|
||
targetCenter.x = (box.max.x + box.min.x) / 2;
|
||
targetCenter.y = box.min.y;
|
||
targetCenter.z = (box.max.z + box.min.z) / 2;
|
||
|
||
return { x: targetCenter.x, y: targetCenter.y, z: targetCenter.z };
|
||
}
|
||
|
||
getObjectHeight(targetObject) {
|
||
let box = new THREE.Box3().setFromObject(targetObject);
|
||
// 获取包围盒的高度
|
||
let height = box.max.y - box.min.y;
|
||
return height;
|
||
}
|
||
|
||
upDownShap() {
|
||
if (!this.shapes || this.shapes.length < 1) {
|
||
return;
|
||
}
|
||
// 设置移动的速度和幅度
|
||
let speed = 1.5; // 移动速度
|
||
let amplitude = 5; // 移动幅度
|
||
this.shapes.forEach(shape => {
|
||
let newYPosition = shape.y + amplitude * Math.sin(speed * Date.now() / 1000);
|
||
shape.object.position.y = newYPosition;
|
||
|
||
})
|
||
}
|
||
|
||
lookAtObject(_object) {
|
||
// 将相机移动到物体位置并面对物体
|
||
let _pos = this.getObjectPosition(_object);
|
||
this.camera.position.set(_pos.x, _pos.y, _pos.z);
|
||
this.camera.lookAt(_object.position);
|
||
}
|
||
|
||
clearThree(obj) {
|
||
while (obj.children.length > 0) {
|
||
this.clearThree(obj.children[0])
|
||
obj.remove(obj.children[0]);
|
||
}
|
||
if (obj.geometry) obj.geometry.dispose()
|
||
|
||
if (obj.material) {
|
||
//in case of map, bumpMap, normalMap, envMap ...
|
||
Object.keys(obj.material).forEach(prop => {
|
||
if (!obj.material[prop])
|
||
return
|
||
if (typeof obj.material[prop].dispose === 'function')
|
||
obj.material[prop].dispose()
|
||
})
|
||
obj.material.dispose()
|
||
}
|
||
}
|
||
|
||
resetScene() {
|
||
this.clearThree(this.scene);
|
||
}
|
||
|
||
addText(_objName, _text, _position) {
|
||
let _that = this;
|
||
const loader = new FontLoader();
|
||
loader.load('/js/three/examples/fonts/helvetiker_regular.typeface.json', function (font) {
|
||
const geometry = new TextGeometry(_text, {
|
||
font: font,
|
||
size: 0.15,
|
||
height: 0.05
|
||
});
|
||
|
||
let material = new THREE.MeshBasicMaterial({ color: 0xffffff , transparent: true, opacity: 1 }); // 创建材质
|
||
let mesh = new THREE.Mesh(geometry, material); // 创建网格并添加到场景中
|
||
mesh.name = _objName;
|
||
//mesh.scale.set(10, 10, 10)
|
||
mesh.position.set(_position.x, _position.y+0.6, _position.z);
|
||
//mesh.rotateX(270 / 180 * Math.PI)
|
||
_that.scene.add(mesh); // 将锥形对象添加到场景中
|
||
});
|
||
}
|
||
|
||
createParkingSpace(x, y, z, parkingSpaceSize) {
|
||
console.log(parkingSpaceSize)
|
||
const parkingSpaceDepth = 0.1; // 车位的厚度
|
||
let _color = 0x00FF00;
|
||
if(parkingSpaceSize.color){
|
||
_color = parkingSpaceSize.color;
|
||
}
|
||
const parkingSpaceMaterial = new THREE.MeshBasicMaterial({ color: _color }); // 灰色材质
|
||
const geometry = new THREE.BoxGeometry(parkingSpaceSize.width, parkingSpaceSize.height, parkingSpaceDepth);
|
||
const mesh = new THREE.Mesh(geometry, parkingSpaceMaterial);
|
||
mesh.position.set(x, y, z); // 设置车位位置
|
||
this.scene.add(mesh); // 将车位添加到场景中
|
||
return mesh; // 返回车位对象以便后续管理
|
||
}
|
||
|
||
/**
|
||
* 初始化车位
|
||
* @param {车位列表} pSpaces
|
||
*/
|
||
initParkingSpace(pSpaces) {
|
||
this.resetScene();
|
||
|
||
let sWidth = 0.5;
|
||
let sHeight = 1;
|
||
let lineSpaceLenght = 50;
|
||
let roadHeight = 1;
|
||
// 创建多个车位
|
||
const spaceBetween = 0.1; // 车位之间的间隔
|
||
|
||
//如果车位数没有超过lineSpaceLenght 那么lineSpaceLenght 修改为车位数
|
||
if(pSpaces.length < lineSpaceLenght && pSpaces.length > 20){
|
||
lineSpaceLenght = 20;
|
||
}else if(pSpaces.length < lineSpaceLenght){
|
||
lineSpaceLenght = pSpaces.length;
|
||
}
|
||
|
||
|
||
|
||
|
||
let pWidth = sWidth * lineSpaceLenght + lineSpaceLenght * spaceBetween + roadHeight *2;
|
||
let totalLines = Math.ceil(pSpaces.length / (2 * lineSpaceLenght));
|
||
let pHeight = sHeight * 2 * totalLines + roadHeight * (totalLines + 1);
|
||
|
||
//todo 添加一个车位平面
|
||
// 创建一个停车场平面
|
||
const planeGeometry = new THREE.PlaneGeometry(pWidth, pHeight); // 10x10的平面
|
||
const planeMaterial = new THREE.MeshBasicMaterial({ color: 0x808080 }); // 灰色材质
|
||
const parkingLotPlane = new THREE.Mesh(planeGeometry, planeMaterial);
|
||
|
||
|
||
// 将停车场平面添加到场景中
|
||
this.scene.add(parkingLotPlane);
|
||
|
||
let _x = 0;
|
||
let _y = pHeight / 2 - sHeight / 2 - sHeight;
|
||
let _textX = 0;
|
||
let _textY = _y + sHeight/4 - spaceBetween *2 ;
|
||
for (let i = 0; i < pSpaces.length; i++) {
|
||
_x = -pWidth / 2 + (i%lineSpaceLenght) * (sWidth + spaceBetween) + sWidth/2 + roadHeight;
|
||
_textX = _x;
|
||
if (i%lineSpaceLenght == 0 && i != 0 ) {
|
||
_y -= (sHeight+spaceBetween);
|
||
_textY = _y - sHeight/4 - sHeight - spaceBetween *2 ;
|
||
}
|
||
if(i% (2*lineSpaceLenght) == 0 && i != 0){
|
||
_y -= roadHeight;
|
||
_textY = _y + sHeight/4 - spaceBetween *2 ;
|
||
}
|
||
|
||
console.log(pWidth, pHeight, _x, _y);
|
||
this.createParkingSpace(_x, _y, 0, {
|
||
width: sWidth,
|
||
height: sHeight,
|
||
color:pSpaces[i].psColor
|
||
}); // 创建车位并设置位置
|
||
if(pSpaces[i].num.length>1 ){
|
||
_textX = _x -sWidth/2
|
||
}
|
||
this.addText(pSpaces[i].num,pSpaces[i].num+"",{
|
||
x:_textX,
|
||
y:_textY,
|
||
z:0
|
||
})
|
||
}
|
||
|
||
}
|
||
} |