Reputation: 6087
I have a 'target-circle' component which is a simple circle with a ring outside it. I'm trying to get mouseenter and mouseleave events for the entire component, but the event listeners attached to the parent element fire for the child entities and only when the raycaster hits something.
I've attempted various ways to put invisible hit-testing circles/rings to try and alleviate the problem, but they all have the core issue that multiple enter/leave events are fired for child entities.
Is it feasible/what is the best way to only get events for entering/leaving the entire parent entity?
Demo: https://output.jsbin.com/tucuxas/quiet
<!DOCTYPE html>
<html>
<head>
<script src="https://aframe.io/releases/0.6.0/aframe.min.js"></script>
<script>
AFRAME.registerComponent('target-circle', {
schema: {
position: {type: 'vec3', default: {x: 0, y: 0, z: 0}}
},
init: function() {
var el = this.el;
el.setAttribute('position', this.data.position);
el.object3D.lookAt(new THREE.Vector3(0, 0, 0));
var outerRing = document.createElement('a-entity');
outerRing.setAttribute('class', 'outerRing');
outerRing.setAttribute('material', {
color: 'black'
});
outerRing.setAttribute('geometry', {
primitive: 'ring',
radiusInner: '1.2',
radiusOuter: '1.4'
});
var innerCircle = document.createElement('a-entity');
innerCircle.setAttribute('class', 'innerCircle');
innerCircle.setAttribute('material', {
color: 'black'
});
innerCircle.setAttribute('geometry', {
primitive: 'circle',
radius: '0.3'
});
el.appendChild(outerRing);
el.appendChild(innerCircle);
el.addEventListener('mouseenter', function() {
console.log('mouseenter');
});
el.addEventListener('mouseleave', function() {
console.log('mouseleave');
});
}
});
</script>
</head>
<body>
<a-scene>
<a-entity target-circle='position: 0 3 -10'></a-entity>
<a-entity camera look-controls>
<a-entity id="cursor" cursor="fuse: false;" material="color: black; shader: flat;"
position="0 0 -1"
geometry="primitive: ring; radiusInner: 0.001; radiusOuter: .005; "></a-entity>
</a-entity>
</a-scene>
</body>
</html>
Upvotes: 0
Views: 1218
Reputation: 37
An updated solution for A-Frame 0.8.0:
a-circle
as the parenta-ring
as a child of the a-circle
raycaster="objects: a-circle (and comma-separated selectors of any other elements you need the cursor to interact with in the scene); recursive: false"
to the cursor entity in your sceneThe raycaster
component settings here will prevent your cursor from intersecting with elements in the scene other than the ones whose selectors match what's listed in the objects
property, as well as limiting the intersections to the top-level element that matches, ignoring all descendents.
More on the raycaster
component: https://github.com/aframevr/aframe/blob/master/docs/components/raycaster.md
Upvotes: 0
Reputation: 14645
Although SamB's anwser is correct in this case, I'm not sure if blocking the pointer-events in css will work on all raycasters ( even though it should ), here is my idea of wrapping the children in a container entity, just for the raycast:
Because Your entire entity consists of a ring, and a small circle inside, the parent entity is just an empty holder for the child entities.
The mouseleave event fires when you leave the ring, because between the ring, and the circle, there is literally nothing. If You want to fill in the space ( in 2D ), You need to either:
opacity = 0
, not visible = false
( for the visible attribute is responsible for the rendering, not visibility ), and place it in front of the other children.If You want to fill it in 3D space, instead of a circle, create an invisible cylinder, paper thin, just so it could block the raycasts from all sides.
Working fiddle here.
Upvotes: 1
Reputation: 151
In your CSS classes for innerCircle and outerCircle add following property
pointer-events: none;
Upvotes: 1