/Users/song/Code/threejs_learn_vanilla_class_singleton/threejs_learn_vanilla_ts_class_singleton/src/threejs_全局事件管理/Base.ts
import { Light, Object3D, Scene, Vector2 } from "three";
import Camera from "./Cameras";
import Helper from "./Helpers";
import Renderer from "./Renderer";
import Size from "./Size";
import Time from "./Time";
import Box from "./World/Box";
import Control from "./Controls";
import Lights from "./Lights";
import EventManger from "./Events";
export default class Base {
public static base: Base;
public canvas: HTMLCanvasElement;
public scene: Scene;
public cameras: Camera;
public size: Size;
public time: Time;
public renderer: Renderer;
public control: Control;
public helper: Helper;
public eventManger: EventManger;
public noTransfromControlObjs: Object3D[] = [];
constructor(canvas: HTMLCanvasElement) {
Base.base = this;
this.canvas = canvas as HTMLCanvasElement;
this.scene = new Scene();
this.size = new Size();
this.cameras = new Camera();
this.time = new Time();
this.renderer = new Renderer();
new Lights();
// helper
const helper = new Helper();
this.helper = helper;
this.noTransfromControlObjs.push(helper.gridHelper, helper.axesHelper);
// control
const control = new Control();
this.control = control;
this.noTransfromControlObjs.push(this.control.transformControl);
// events
this.eventManger = new EventManger();
// 使用EventManager实例注册的事件,就是相当于全局事件,
this.eventManger.addEventListener("click", (e) => {
console.log("点击射线穿过了下面这些物体");
console.log(e);
});
// -----------------------
new Box();
this.time.on("update", () => {
this.update();
});
this.size.on("resize", () => {
this.resize();
});
}
public static getInstance(canvas?: HTMLCanvasElement) {
if (canvas === undefined && Base.base !== undefined) {
return Base.base;
}
Base.base = new Base(canvas as HTMLCanvasElement);
return Base.base;
}
private resize() {
this.cameras.resize();
this.renderer.resize();
}
private update() {
this.control.update();
this.renderer.update();
}
}
/Users/song/Code/threejs_learn_vanilla_class_singleton/threejs_learn_vanilla_ts_class_singleton/src/threejs_全局事件管理/Helpers.ts
import { AxesHelper, GridHelper } from "three";
import Base from "./Base";
export default class {
public axesHelper: AxesHelper;
public gridHelper: GridHelper;
constructor() {
const base = Base.getInstance();
const axesHelper = new AxesHelper(5);
this.axesHelper = axesHelper;
base.scene.add(axesHelper);
const size = 10;
const divisions = 10;
const gridHelper = new GridHelper(size, divisions);
this.gridHelper = gridHelper;
base.scene.add(gridHelper);
}
}
/Users/song/Code/threejs_learn_vanilla_class_singleton/threejs_learn_vanilla_ts_class_singleton/src/threejs_全局事件管理/Lights.ts
import { AmbientLight, DirectionalLight } from "three";
import Base from "./Base";
export default class Environment {
private sunLight: DirectionalLight;
private ambientLight: AmbientLight;
constructor() {
const base = Base.getInstance();
this.sunLight = new DirectionalLight("#ffffff", 2);
this.sunLight.castShadow = true;
this.sunLight.shadow.camera.far = 20;
this.sunLight.shadow.mapSize.set(2048, 2048);
this.sunLight.shadow.normalBias = 0.05;
this.sunLight.position.set(-1.5, 7, 10);
base.scene.add(this.sunLight);
this.ambientLight = new AmbientLight("#ffffff", 0.1);
base.scene.add(this.ambientLight);
}
}
/Users/song/Code/threejs_learn_vanilla_class_singleton/threejs_learn_vanilla_ts_class_singleton/src/threejs_全局事件管理/Cameras.ts
import { PerspectiveCamera, Scene } from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import Base from "./Base";
import type Size from "./Size";
export default class Camera {
private size: Size;
private scene: Scene;
private canvas: HTMLCanvasElement;
public perspectiveCamera: PerspectiveCamera;
// private controls: OrbitControls;
constructor() {
const base = Base.getInstance();
this.size = base.size;
this.scene = base.scene;
this.canvas = base.canvas;
this.perspectiveCamera = this.createPerspectiveCamera();
this.scene.add(this.perspectiveCamera);
}
private createPerspectiveCamera() {
const perspectiveCamera = new PerspectiveCamera(
35,
this.size.aspect,
0.1,
1000
);
perspectiveCamera.position.set(15, 30, 20);
return perspectiveCamera;
}
public resize() {
// Updating Perspective Camera on Resize
this.perspectiveCamera.aspect = this.size.aspect;
this.perspectiveCamera.updateProjectionMatrix();
}
}
/Users/song/Code/threejs_learn_vanilla_class_singleton/threejs_learn_vanilla_ts_class_singleton/src/threejs_全局事件管理/Size.ts
import EventEmitter from "eventemitter2";
export default class Size extends EventEmitter {
public width: number;
public height: number;
public aspect: number;
public pixelRatio: number;
constructor() {
super();
this.width = window.innerWidth;
this.height = window.innerHeight;
this.aspect = this.width / this.height;
this.pixelRatio = Math.min(window.devicePixelRatio, 2);
window.addEventListener("resize", () => {
this.width = window.innerWidth;
this.height = window.innerHeight;
this.aspect = this.width / this.height;
this.pixelRatio = Math.min(window.devicePixelRatio, 2);
this.emit("resize");
});
}
}
/Users/song/Code/threejs_learn_vanilla_class_singleton/threejs_learn_vanilla_ts_class_singleton/src/threejs_全局事件管理/Events.ts
import {
Camera,
EventDispatcher,
Object3D,
Raycaster,
Scene,
Vector2,
} from "three";
import Base from "./Base";
export default class EventManger extends EventDispatcher {
private raycaster: Raycaster = new Raycaster();
private mouse: Vector2 = new Vector2();
private dom: HTMLCanvasElement;
private scene: Scene;
private camera: Camera;
constructor() {
super();
const base = Base.getInstance();
this.dom = base.canvas;
this.scene = base.scene;
this.camera = base.cameras.perspectiveCamera;
const mouse = this.mouse;
const raycaster = this.raycaster;
const dom = this.dom;
let cacheObject: Object3D | null = null;
dom.addEventListener("mousedown", (event) => {
// 选取物体的操作
raycaster.setFromCamera(mouse, this.camera);
const intersection = raycaster.intersectObjects(this.scene.children);
// 这里将事件派发到this上面,相当于注册全局事件,也就是将事件派发到EventManager的实例上面
this.dispatchEvent({
type: "mousedown",
intersection,
});
if (intersection.length) {
const object = intersection[0].object;
// 派发事件到3d物体上面
object.dispatchEvent({
type: "mousedown",
});
}
});
dom.addEventListener("mousemove", (event) => {
mouse.x = (event.offsetX / dom.offsetWidth) * 2 - 1;
mouse.y = (-event.offsetY * 2) / dom.offsetHeight + 1;
// 选取物体的操作
raycaster.setFromCamera(mouse, this.camera);
const intersection = raycaster.intersectObjects(this.scene.children);
// 全局派发事件
this.dispatchEvent({
type: "mousemove",
intersection,
});
if (intersection.length) {
const object = intersection[0].object;
if (object !== cacheObject) {
if (cacheObject) {
cacheObject.dispatchEvent({
type: "mouseleave",
});
}
object.dispatchEvent({
type: "mouseenter",
});
} else if (object === cacheObject) {
object.dispatchEvent({
type: "mousemove",
});
}
cacheObject = object;
} else {
if (cacheObject) {
cacheObject.dispatchEvent({
type: "mouseleave",
});
}
cacheObject = null;
}
});
dom.addEventListener("mouseup", (event) => {
// 选取物体的操作
raycaster.setFromCamera(mouse, this.camera);
const intersection = raycaster.intersectObjects(this.scene.children);
this.dispatchEvent({
type: "mouseup",
intersection,
});
if (intersection.length) {
const object = intersection[0].object;
object.dispatchEvent({
type: "mouseup",
});
}
});
dom.addEventListener("click", (event) => {
// 选取物体的操作
raycaster.setFromCamera(mouse, this.camera);
const intersection = raycaster.intersectObjects(this.scene.children);
this.dispatchEvent({
type: "click",
intersection,
});
if (intersection.length) {
const object = intersection[0].object;
object.dispatchEvent({
type: "click",
});
}
});
}
}
/Users/song/Code/threejs_learn_vanilla_class_singleton/threejs_learn_vanilla_ts_class_singleton/src/threejs_全局事件管理/Renderer.ts
import * as THREE from "three";
import Base from "./Base";
import { Scene, WebGLRenderer } from "three";
import Camera from "./Cameras";
import Size from "./Size";
export default class Renderer {
private size: Size;
private scene: Scene;
private canvas: HTMLCanvasElement;
private camera: Camera;
private renderer: WebGLRenderer;
constructor() {
const base = Base.getInstance();
this.size = base.size;
this.scene = base.scene;
this.canvas = base.canvas;
this.camera = base.cameras;
this.renderer = this.setRenderer();
}
setRenderer() {
const renderer = new WebGLRenderer({
canvas: this.canvas,
antialias: true,
});
renderer.physicallyCorrectLights = true;
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.toneMapping = THREE.CineonToneMapping;
renderer.toneMappingExposure = 1.75;
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setSize(this.size.width, this.size.height);
renderer.setPixelRatio(this.size.pixelRatio);
return renderer;
}
resize() {
this.renderer.setSize(this.size.width, this.size.height);
this.renderer.setPixelRatio(this.size.pixelRatio);
}
update() {
this.renderer.render(this.scene, this.camera.perspectiveCamera);
}
}
/Users/song/Code/threejs_learn_vanilla_class_singleton/threejs_learn_vanilla_ts_class_singleton/src/threejs_全局事件管理/Controls.ts
import {
TransformControls,
TransformControlsGizmo,
TransformControlsPlane,
} from "three/examples/jsm/controls/TransformControls";
import Base from "./Base";
import {
AxesHelper,
GridHelper,
Line,
MOUSE,
Object3D,
PerspectiveCamera,
Raycaster,
Scene,
Vector2,
} from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
export default class Control {
public transformControl: TransformControls;
public orbitControl: OrbitControls;
private base: Base;
private camera: PerspectiveCamera;
private canvas: HTMLCanvasElement;
private scene: Scene;
private transing: boolean;
constructor() {
const base = Base.getInstance();
this.base = base;
this.camera = base.cameras.perspectiveCamera;
this.canvas = base.canvas;
this.scene = base.scene;
// 正在变换的标志位
this.transing = false;
this.transformControl = this.createTransformControl();
this.initTransformControlEvent();
this.scene.add(this.transformControl);
this.orbitControl = this.createOrbitControl();
}
private createTransformControl() {
const transformControls = new TransformControls(this.camera, this.canvas);
return transformControls;
}
private initTransformControlEvent() {
this.transformControl.addEventListener("mouseDown", (e) => {
this.transing = true;
});
}
public update() {
this.orbitControl.update();
}
private createOrbitControl() {
const controls = new OrbitControls(this.camera, this.canvas);
controls.enableDamping = true;
controls.enableZoom = true;
// 取消鼠标控制器的鼠标左键旋转功能
controls.mouseButtons = {
LEFT: null as unknown as MOUSE,
MIDDLE: MOUSE.DOLLY,
RIGHT: MOUSE.PAN,
};
return controls;
}
}
/Users/song/Code/threejs_learn_vanilla_class_singleton/threejs_learn_vanilla_ts_class_singleton/src/threejs_全局事件管理/Time.ts
import EventEmitter from "eventemitter2";
import { Clock } from "three";
export default class Time extends EventEmitter {
public clock: Clock;
constructor() {
super();
this.clock = new Clock();
this.update();
}
update() {
this.emit("update");
window.requestAnimationFrame(() => this.update());
}
}
/Users/song/Code/threejs_learn_vanilla_class_singleton/threejs_learn_vanilla_ts_class_singleton/src/threejs_全局事件管理/World/Box.ts
import {
BoxGeometry,
MeshBasicMaterial,
Mesh,
MeshLambertMaterial,
Color,
} from "three";
import Base from "../Base";
export default class Box {
private cube: Mesh;
private cubeMaterial: MeshBasicMaterial;
constructor() {
const base = Base.getInstance();
this.cubeMaterial = new MeshBasicMaterial({ color: 0x00ff00 });
const cube = this.createCube();
this.cube = cube;
base.scene.add(cube);
const cube2 = new Mesh(
new BoxGeometry(1, 1, 1),
new MeshBasicMaterial({ color: 0x00ff00 })
);
cube2.position.setX(3);
base.scene.add(cube2);
this.initCubeEvent();
}
private createCube() {
const cube = new Mesh(new BoxGeometry(1, 1, 1), this.cubeMaterial);
cube.position.y = 0.5;
return cube;
}
private initCubeEvent() {
this.cube.addEventListener("mouseenter", (e) => {
console.log("鼠标进入");
this.cubeMaterial.color = new Color(0xff0000);
});
this.cube.addEventListener("mousemove", (e) => {
console.log("鼠标正在移动");
});
this.cube.addEventListener("mouseleave", (e) => {
console.log("鼠标离开");
this.cubeMaterial.color = new Color(0x00ff00);
});
this.cube.addEventListener("click", (e) => {
console.log("鼠标点击");
this.cubeMaterial.color = new Color(0x0000ff);
});
}
}
标签:Base,const,private,NOTE,base,new,import
From: https://www.cnblogs.com/zhuoss/p/17107350.html