mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
101.87k stars 35.32k forks source link

bubbling / propagation of events throughout the display list #8365

Open endel opened 8 years ago

endel commented 8 years ago

Hi there!

What do you guys think about having bubble/propagation of events throughout the display list? It could work exactly the way it works for DOM events: https://dom.spec.whatwg.org/#dom-event-bubbles

I'm developing a GUI in which a deep node triggers a mouse event, and I'd like to have the listener on a parent node to deal with that, as follows the representation:

Scene
    > Object3D ~> listens to "click" event
        > Object3D
            > Object3D
            > Object3D ~> triggers the "click" event

The implementation could be something similar to this:

THREE.Object3D.prototype.dispatchEvent = function (event) {
  THREE.EventDispatcher.prototype.dispatchEvent.apply(this, arguments);
  if (event.bubbles && this.parent) {
    this.parent.dispatchEvent(event)
  }
}

Note that bubbling is false by default when instantiating DOM events. In case we implement this feature in three.js this wouldn't be an overhead.

Looking forward to know your thoughts about this. Cheers!

mrdoob commented 8 years ago

Sounds good to me! 😊

jasonChen1982 commented 6 years ago

maybe~~ three.interaction.js can deal with this problem

import { Scene, PerspectiveCamera, WebGLRenderer, Mesh, BoxGeometry, MeshBasicMaterial } from 'three';
import { Interaction } from 'three.interaction';

const renderer = new WebGLRenderer({ canvas: canvasElement });
const scene = new Scene();
const camera = new PerspectiveCamera(60, width / height, 0.1, 100);

// new a interaction, then you can add interaction-event with your free style
const interaction = new Interaction(renderer, scene, camera);

const cube = new Mesh(
  new BoxGeometry(1, 1, 1),
  new MeshBasicMaterial({ color: 0xffffff }),
);
scene.add(cube);
cube.cursor = 'pointer';
cube.on('click', function(ev) {});
cube.on('touchstart', function(ev) {});
cube.on('touchcancel', function(ev) {});
cube.on('touchmove', function(ev) {});
cube.on('touchend', function(ev) {});
cube.on('mousedown', function(ev) {});
cube.on('mouseout', function(ev) {});
cube.on('mouseover', function(ev) {});
cube.on('mousemove', function(ev) {});
cube.on('mouseup', function(ev) {});
// and so on ...

/**
 * you can also listen on parent-node or any display-tree node,
 * source event will bubble up along with display-tree.
 * you can stop the bubble-up by invoke ev.stopPropagation function.
 */
scene.on('touchstart', ev => {
  console.log(ev);
})
scene.on('touchmove', ev => {
  console.log(ev);
})

ping @mrdoob @endel 😊😊😊