Custom Events
Learn more about custom events and their properties in this lesson.
We'll cover the following
Events help us communicate with different entities by sending signals that other pieces of code can pick up and respond to. There can be requirements for which we need to achieve a customized behavior against a specific type of event. To accomplish this, A-frame offers custom events.
Emitting events
Using the emit(eventName, eventDetail, bubbles)
function, we can emit from any entity element. For example, we can use the emit()
function to define a changescale
named event and pass target scale values to the event listener using the eventDetail
argument:
entityEl.emit('changescale', { x: 2.0, y: 2.0, z: 2.0 }, false);
In the code above, the data is passed as a dictionary containing the scale values along the three axes. When we want to access the x value passed into this event, we can access it using the event.detail.x
property.
When an event is emitted, any listeners that are registered to handle this event will be notified. Additionally, we can control whether the event propagates up through the DOM hierarchy using the bubbles
argument. If this argument is set to true
, the event will "bubble up" and be emitted by the parent entities as well. In the above example provided, this argument is set to false
, meaning the event does not bubble up and is confined to the entity that emitted it.
Adding an event listener
We can register an event listener using the addEventListener(eventName, function)
method. When the event is emitted, function
will be called to handle it. For example, continuing from the previous example with the changescale
event, we can define a listener as follows:
entityEl.addEventListener('changescale', (evt) => {console.log('I received the event notification');//set the scale of the current entityentityEl.setAttribute('scale', {x: evt.detail.x,y: evt.detail.y,z: evt.detail.z,});});
When an entity receives the notification that the changescale
event has been emitted by another entity in the scene, the event-handling function will be called with the evt
event object. In the event object, we have the event detail, which contains data from the emitting event. In this example, we use the 3D vector data to change the scale
property of the listening entity using the setAttribute()
function.
Removing an event listener
To remove an event listener, we can use the .removeEventListener(eventName, function)
method. We need to pass the same event name and function with which the listener was registered. For example, continuing from the previous example with the changescale
event, we can remove a listener as follows:
sceneEl.removeEventListener('changescale');
It’s a good practice to remove event listeners, as shown in the following example (lines 52 and 69), because if the component that listened to the event malfunctions, the event listener would still be there, causing bugs.
Example
The following example sums up the concepts learned in creating a custom event.
We have two boxes in the scene. The red box has a scale-box-controller
component attached to it. This component listens to a click
event on the box. Upon clicking the red box, the listener attached to the yellow box is notified, and accordingly, the yellow box increases twofold in size. Here, the init()
function in A-Frame represents the initialization function of a custom component. It’s where we set up initial configurations and register event listeners when the component is first attached to an entity. In contrast, the remove()
function is used to remove a specific event listener from an entity. It’s the recommended practice when we no longer want an entity to respond to a particular event.
We create another listener
named component, in which we listen for the changescale
event. Because both boxes are on the same level of the hierarchy, the listener on the yellow box can’t directly receive that event’s notification. The red box itself can listen to the event, and anything higher in the hierarchy can also listen to it. That’s why we add the event listener to the scene, accessing it via the this.el.sceneEl
property. By attaching the component to the yellow box entity, we can access and modify its scale attributes in the event listener.
Conclusion
We now have a basic understanding of how to utilize custom events in our XR application to make them more interactive and engaging.