feat(All):Initial
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
import * as THREE from "three";
|
||||
import {MapControls} from "three/examples/jsm/controls/MapControls.js";
|
||||
|
||||
interface IMiniMapOptions {
|
||||
domElement?: HTMLElement;
|
||||
}
|
||||
|
||||
let onPointerDownFn;
|
||||
|
||||
|
||||
export class MiniMap {
|
||||
private viewport;
|
||||
private mapControl: MapControls;
|
||||
private domElement: HTMLElement;
|
||||
private miniMapRenderer: THREE.WebGLRenderer;
|
||||
private miniMapCamera: THREE.PerspectiveCamera;
|
||||
|
||||
raycaster = new THREE.Raycaster()
|
||||
|
||||
constructor(viewport,options:IMiniMapOptions = {}) {
|
||||
this.viewport = viewport;
|
||||
|
||||
this.domElement = options.domElement || this.createDomElement();
|
||||
viewport.container.appendChild(this.domElement);
|
||||
|
||||
const {renderer, camera} = this.init();
|
||||
this.miniMapRenderer = renderer;
|
||||
this.miniMapCamera = camera;
|
||||
|
||||
this.mapControl = this.initControls();
|
||||
|
||||
this.initEvent();
|
||||
|
||||
this.miniMapRenderer.setAnimationLoop(this.miniMapAnimation.bind(this));
|
||||
}
|
||||
|
||||
createDomElement(){
|
||||
const domElement = document.createElement("div");
|
||||
domElement.setAttribute("id", "es-3d-mini-map");
|
||||
domElement.style.position = "absolute";
|
||||
domElement.style.top = "10px";
|
||||
domElement.style.right = "10px";
|
||||
domElement.style.width = "250px";
|
||||
domElement.style.height = "250px";
|
||||
domElement.style.boxShadow = "0px 0px 5px #000";
|
||||
|
||||
return domElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为小地图准备专门的 渲染器 + 摄像机
|
||||
*/
|
||||
init(){
|
||||
const miniMapRenderer = new THREE.WebGLRenderer({antialias:true});
|
||||
miniMapRenderer.setSize(this.domElement.clientWidth, this.domElement.clientHeight);
|
||||
this.domElement.appendChild(miniMapRenderer.domElement);
|
||||
miniMapRenderer.setClearColor(0xffffff);
|
||||
|
||||
const miniMapCamera = new THREE.PerspectiveCamera(
|
||||
45,
|
||||
this.domElement.clientWidth / this.domElement.clientHeight,
|
||||
0.1,
|
||||
1000
|
||||
)
|
||||
miniMapCamera.position.set(0, 50, 0)
|
||||
miniMapCamera.lookAt(0,0,0);
|
||||
|
||||
return {
|
||||
renderer: miniMapRenderer,
|
||||
camera: miniMapCamera
|
||||
}
|
||||
}
|
||||
|
||||
initControls() {
|
||||
const controls = new MapControls(this.miniMapCamera, this.miniMapRenderer.domElement);
|
||||
controls.enableDamping = true;
|
||||
controls.dampingFactor = 0.05;
|
||||
controls.enableZoom = false;
|
||||
|
||||
return controls;
|
||||
}
|
||||
|
||||
initEvent(){
|
||||
onPointerDownFn = this.onPointerDown.bind(this);
|
||||
this.domElement.addEventListener("pointerdown", onPointerDownFn);
|
||||
}
|
||||
|
||||
onPointerDown(e: PointerEvent){
|
||||
const mousePosition = new THREE.Vector2()
|
||||
|
||||
let x = e.offsetX
|
||||
let y = e.offsetY
|
||||
mousePosition.x = ((x / this.domElement.clientWidth) * 2) - 1;
|
||||
mousePosition.y = -((y / this.domElement.clientHeight) * 2) + 1;
|
||||
|
||||
this.raycaster.setFromCamera(mousePosition, this.miniMapCamera);
|
||||
let intersections = this.raycaster.intersectObject(this.viewport.scene, true);
|
||||
|
||||
if(intersections[0]){
|
||||
const point = intersections[0].point;
|
||||
|
||||
// this.miniMapCamera.position.set(point.x, 8, point.z);
|
||||
this.viewport.modules.controls.target.set(point.x, 0, point.z);
|
||||
}
|
||||
}
|
||||
|
||||
miniMapAnimation(){
|
||||
this.miniMapRenderer.render(this.viewport.scene, this.miniMapCamera)
|
||||
}
|
||||
|
||||
update(){
|
||||
this.mapControl.update();
|
||||
}
|
||||
|
||||
dispose(){
|
||||
this.mapControl.dispose();
|
||||
this.miniMapRenderer.dispose();
|
||||
this.domElement.removeChild(this.miniMapRenderer.domElement);
|
||||
|
||||
this.domElement.removeEventListener("pointerdown", onPointerDownFn);
|
||||
onPointerDownFn = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user