Doodle3D-Core/src/d3/EventScene.js

82 lines
2.6 KiB
JavaScript

import * as THREE from 'three';
import { Utils } from '@doodle3d/cal';
import createListener from '@doodle3d/touch-events';
import bowser from 'bowser';
import { convertEvent, isMouseEvent } from '../utils/pointerUtils.js';
import normalizeWheel from 'normalize-wheel';
const events = ['wheel', 'tap', 'dragstart', 'drag', 'dragend', 'seconddragstart', 'seconddrag',
'seconddragend', 'multitouchstart', 'multitouch', 'multitouchend'];
export class EventScene extends THREE.Scene {
constructor(domElement) {
super();
if (domElement) this.setCanvas(domElement);
}
_addEventsListeners() {
for (let i = 0; i < events.length; i ++) {
const eventType = events[i];
this._eventDispatcher.addEventListener(eventType, this.convertEvent);
}
this._domElement.addEventListener('contextmenu', this.contextMenu);
}
_removeEventListeners() {
for (let i = 0; i < events.length; i ++) {
const eventType = events[i];
this._eventDispatcher.removeEventListener(eventType, this.convertEvent);
}
this._domElement.removeEventListener('contextmenu', this.contextMenu);
}
contextMenu(event) {
event.preventDefault();
}
convertEvent = (event) => {
// Prevent delayed click events bubbling through closing menus on iOS #1026
if (bowser.ios && isMouseEvent(event)) return;
const gestureEvent = { type: event.type };
const _convertEvent = convertEvent.bind(null, this._domElement);
if (event.event) gestureEvent.position = _convertEvent(event.event);
if (event.events) gestureEvent.positions = event.events.map(_convertEvent);
if (event.preEvents) gestureEvent.preDrags = event.preEvents.map(_convertEvent);
if (event.event && event.event.deltaY !== undefined) {
gestureEvent.wheelDelta = normalizeWheel(event.event).pixelY;
}
this.onEvent(gestureEvent);
};
onEvent(event) {
const objects = Utils.cloneArray(this.children);
for (let i = objects.length - 1; i >= 0; i --) {
const object = objects[i];
if (object.onEvent && object.onEvent(event, this)) break;
}
}
setCanvas(domElement) {
if (this._eventDispatcher) this._removeEventListeners();
this._domElement = domElement;
if (domElement) {
this._eventDispatcher = createListener(domElement);
this._addEventsListeners();
}
return this;
}
}
export class EventObject3D extends THREE.Object3D {
onEvent(event) {
const objects = Utils.cloneArray(this.children);
for (let i = objects.length - 1; i >= 0; i --) {
const object = objects[i];
if (object.onEvent && object.onEvent(event, this)) break;
}
}
}