实现类似dom操作中的事件注册
addEventListener,removeEventListener
目标class内
以事件管理器和点击事件为例
import { EventDispatcher, Raycaster, Vector2 } from "three";
export class EventManage {
mouse = new Vector2()
raycaster = new Raycaster()
dom
camera
scene
last = null
listener = []
/**
*
* @param {HTMLElement} dom
* @param {Camera} camera
* @param {Scene} scene
*/
constructor(
dom, camera, scene
) {
// super()
this.dom = dom
this.camera = camera
this.scene = scene
const mouse = this.mouse
const raycaster = this.raycaster
let last = null
dom.addEventListener('mousemove', (e) => {
mouse.x = e.offsetX / dom.offsetWidth * 2 - 1
mouse.y = -e.offsetY * 2 / dom.offsetHeight + 1
raycaster.setFromCamera(mouse, camera);
const intersection = raycaster.intersectObjects(this.scene.children)
if (intersection.length > 0) {
// console.log(intersection[0]);
let object = intersection[0].object
object.dispatchEvent({
type: 'mousemove',
point: intersection[0].point
})
if (last && last.uuid == object.uuid) {
} else {
if (last)
last.dispatchEvent({
type: 'mouseout',
point: intersection[0].point
})
object.dispatchEvent({
type: 'mousein',
point: intersection[0].point
})
}
last = object
}
})
dom.addEventListener('click', (e) => {
raycaster.setFromCamera(mouse, camera);
const intersection = raycaster.intersectObjects(this.scene.children)
if (intersection.length > 0) {
// console.log(intersection[0]);
intersection[0].object.dispatchEvent({
type: 'click',
point: intersection[0].point
})
}
let callbacks = this.listener.filter(item => item.name == 'click')
if (callbacks.length > 0) {
callbacks.forEach(({ callback }) => callback(
{
object: intersection[0],
}
))
}
})
}
//注册与删除事件
addEventListener = (name, callback) => {
this.listener.push({ name, callback })
}
removeListener = (name_, callback_) => {
// 寻找对应事件绑定,=== 确定callback_
for (let i = 0; i < this.listener.length; i++) {
let { name, callback } = this.listener[i]
if (
name === name_ && callback === callback_
) {
this.listener.splice(i, 1)
}
}
}
}
代码内使用
在初始化threejs场景的 class内使用
this.eventManage = new EventManage($dom, this.camera, this.scene)
this.eventManage.addEventListener('click', (info) => console.log(info))
this.metrologyUnit = new MetrologyUnit(this)//测试用其他组件
测试组件
export default class MetrologyUnit {
constructor({ eventManage }) {
let handler = (info) => {
console.log("in Metro", info)
}
eventManage.addEventListener('click',
handler
)
setTimeout(() => {
eventManage.removeListener('click',
handler
)
}, 3000)
}
}
效果展示
页面中点击触发
{object: undefined}
index.js:7 in Metro
{object: undefined}
index.js:45
{object: {…}}
index.js:7 in Metro
{object: {…}}
index.js:45
{object: {…}}
index.js:7 in Metro
{object: {…}}
index.js:45
//三秒后 (3000ms)
{object: {…}}
index.js:45
{object: {…}}
index.js:45
{object: {…}}
index.js:45
{object: undefined}