I'm using the following code for visual feedback:
<script src="https://aframe.io/releases/0.5.0/aframe.min.js"></script>
<a-scene>
<a-entity cursor="fuse: true; fuseTimeout: 500" position="0 0 -1" geometry="primitive: ring" material="color: black; shader: flat">
<a-animation begin="click" easing="ease-in" attribute="scale" fill="backwards" from="0.1 0.1 0.1" to="1 1 1"></a-animation>
<a-animation begin="cursor-fusing" easing="ease-in" attribute="scale" fill="forwards" from="1 1 1" to="0.1 0.1 0.1"></a-animation>
</a-entity>
</a-scene>
The problem is that this code is applied where the cursor "collide" with every primitive entity in the scene. I want it to be apply only on specific elements. (or alternatively, disable the animations on specific elements). How can I do it?
Thanks
The cursor component depends on the raycaster component. If the raycaster component is not added as an attribute of the DOM element, the cursor component will initialize one with default settings. However when provided, you can alter certain attribute values of the raycaster component to satisfy your needs.
Luckily for you, the raycaster component supports specific entities with a DOM query selector.
<a-entity cursor raycaster="objects: .clickable"></a-entity>
This will make the cursor only emit events to <a-entity>s with the class name of clickable.
Here is a link to all the raycaster component properties: raycaster component properties.
Related
I am trying to include a mouse click functionality to VR scene apart from focus cursor. I am using it as below -
<a-entity camera look-controls mouse-cursor>
<a-entity position="0 0 -3" scale="0.2 0.2 0.2" geometry="primitive: ring; radiusOuter: 0.20;radiusInner: 0.10;" material="color: #990000; shader: flat" cursor=" fuse: true; rayOrigin: mouse">
</a-entity>
</a-entity>
Below is the error while using this code. Please note that i am using Afrmae with Angular2
ERROR TypeError: Cannot read property 'count' of undefined
at Mesh.raycast (aframe-master.js:21938)
at intersectObject (aframe-master.js:45999)
at Raycaster.intersectObjects (aframe-master.js:46072)
at NewComponent.module.exports.Component.registerComponent.tick (aframe-master.js:69697)
at HTMLElement.value (aframe-master.js:76597)
at HTMLElement.value (aframe-master.js:76645)
at bound (aframe-master.js:79931)
at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:425)
at Object.onInvokeTask (core.es5.js:3881)
at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:424)
If you want your mouse to act like a <a-cursor> You need to move the cursor bit to the <a-scene> :
<a-scene cursor="rayOrigin:mouse">
I want to use fernandojsg's teleport controls on my A-Frame project, but the way I want to use them is with shake.js, one shake to make the teleport line appear and another one to actually teleport where you selected.
I've seen the documentations and came across the startEvents and endEvent properties, and I want to map them into the shake event... for me it sounds like I have to create a custom component to do this, but I wanted to seek help first, to see if this is possible without doing it.
So far I've made this (glitch.com/ link) but it doesn't work so far (please note that I've got some other libraries there that make use of shake, mousedown, and similar events... my plan is to activate or deactivate them depending on how the user wants to move)
<a-entity id="player" wasd-controls tap-to-walk>
<a-camera id="eyes" position="-.5 1.5 0" camera="" look-controls="" mouse-cursor="">
<a-entity id="cursor" cursor="fuse: false;"
position="0 0 -1"
geometry="primitive: ring; radiusInner: 0.015; radiusOuter: 0.019"
material="color: white; shader: flat"
raycaster="far: 5; interval: 1000; objects: .clickable">
</a-entity>
<a-entity id="texto" text="value:Hola;align:center" position="0 -.3 -0.5"></a-entity>
<a-plane position="0 .7 -1" material="transparent: true; opacity: 0.5; color: #ffec04; shader:flat;" scale="1 0.2 1"></a-plane>
</a-camera>
<a-entity
teleport-controls="cameraRig: #player; teleport-origins: #eyes; startEvents:['shake','mousedown']"> </a-entity>
<a-entity id="step" sound="src: #step1"></a-entity>
</a-entity>
Thanks...
Yes you will need a some JS or a custom component to get shake.js and teleport controls to work together for two reasons:
shake.js emits its events outside the A-Frame scene on window where teleport-controls is not listening
shake.js only emits one event type, and you need to differentiate for startEvents and endEvents
But it doesn't need to be very complicated:
AFRAME.registerComponent('shake-listener', {
init: function () {
var targetEl = this.el
var count = 0
// you could also initialize the shake instance here
window.addEventListener('shake', function () {
if (++count % 2) {
targetEl.emit('shakestart')
} else {
targetEl.emit('shakeend')
}
})
}
})
Then add shake-listener to the same entity as teleport-controls="startEvents: shakestart; endEvents: shakeend"
I am trying to detect collision of two boxes in A-FRAME v. 0.5.0. I use raycaster example:
https://aframe.io/docs/0.5.0/components/raycaster.html#whitelisting-entities-to-test-for-intersection
but for me it only works with cursor intersecting one of the meshes.
As it is written, raycaster detects when line created from a starting point to a certain direction intersects desired mesh (here marked with a collidable class). It appears that start of this collision-detecting line is somehow set on the camera or on a cursor but not on one of the boxes. How to reassign this starting point?
Before initializing scene I added component:
AFRAME.registerComponent('collider-check', {
dependencies: ['raycaster'],
init: function () {
console.log("we have component");
this.el.addEventListener('raycaster-intersected', function () {
console.log('Player hit something!');
});
},
});
and then A-FRAME entities
<a-entity id="player" collider-check >
<a-entity id="rc"
raycaster="objects: .collidable"
geometry="primitive: box; width: 0.5; height: 4; depth: 0.5"
material="shader: flat; color:gray"
position="0 -0.9 0"
rotation="90 0 0" ></a-entity>
</a-entity>
<a-entity id="inmotion" class="collidable"
geometry="primitive: box; width: 0.5; height: 4; depth: 0.5"
position="1 0 0"
material="shader: flat; color: #00CCDD">
<a-animation id="canim"
attribute="position"
dur="2000"
from ="-2 -1 0"
to="2 0 0.5"
fill="forwards"
direction="alternate"
repeat="indefinite">
</a-animation>
</a-entity>
Here is jsfiddle with the example;
https://jsfiddle.net/Suiseki/9ggs6x4m/2/
Using the raycaster is one way to check for collisions in 3D space, but it's best if one of those shapes is a ray/line. If you have two 3D objects, it's easier to use bounding box or bounding sphere collisions, without a raycaster. Here are example implementations of each:
aabb-collider
sphere-collider
Both will file hit events on the elements when they collide. Example usage, for a slightly different case.
Does anyone know how to create a button in aframe
One way to create a button with A-Frame would be to use the <a-box> primitive combined with a cursor. The following is a simple demo:
<a-scene>
<a-entity position="0 .6 4">
<a-camera>
<a-entity id="mycursor" cursor="fuse: true; fuseTimeout: 500; max-distance: 30;"
position="0 0 -5"
geometry="primitive: ring"
material="color: blue; shader: flat">
</a-entity>
</a-camera>
</a-entity>
<!-- "button" -->
<a-entity id="refresh-button" geometry="primitive: box" material="color: red" position="0 0 -2"></a>
</a-scene>
<script>
document.querySelector('#refresh-button').addEventListener('click', function() {
// Refresh stuff would go here!
});
</script>
When the cursor focuses on the "button", the click event would fire. To add text to the button, you can use this component:
https://github.com/ngokevin/aframe-text-component
Lastly, if you're looking for a more traditional "button", you could simply float a <button> element over the canvas or Iframe if you're embedding.
i like https://www.npmjs.com/package/aframe-event-set-component for the hover event. And i give my cursor an attribute (data clickable) and then i say the raycaster he should just trigger entities with the attribute. If you want to let something just be clickable if you for example enter the vr-mode simply remove the dataclickable attribute. Scene looks like this:
<a-scene cursor="rayOrigin: mouse" raycaster="objects: [data-clickable]">
<a-image id="button" data-clickable visible="true" position="2 1.75 -0.2" height="0.5" width="0.5" rotation="0 90 0" onclick="dosomething()" event-set__enter="_event: mouseenter; width: 0.53; height: 0.53;"
event-set__leave="_event: mouseleave; width: 0.5; height: 0.5;"></a-image>
<a-camera>
<a-cursor id="curseid" raycaster="objects: [data-clickable]"</a-cursor>
</a-camera>
</a-scene>
If you want that a button works just if something happend give him the attribute later:
document.getElementById('button').setAttribute('data-clickable', '');
If you done with the button use:
document.getElementById('button').setAttribute('visible', 'false');
document.getElementById('button').removeAttribute('data-clickable');
If you want that the cursor just triggers button if you for example enter vr-mode, change the raycaster="objects: .notclickable" and then give him later with this line his attribute back:
document.getElementById('curseid').setAttribute('raycaster', 'objects: [data-clickable]');
This is for now my way to do buttons, maybe there is a smarter way. I hope this helped a bit :D
I have an app where the user has to answer a question by clicking the correct area on a collada model - there are 2 options and the user knows that an area is selectable when the cursor turns blue (mouse enters the cylinder, which has visible=false).
The mouse turns blue fine, however where the mouse leaves the cylinder, the cursor color should return to black, but instead it stays blue.
Thanks in advance for your help.
<a-cursor id="myCursor" color="black"></a-cursor>
<a-entity id='questionA' geometry="primitive: cylinder; height: .01; radius: 2.5" material="color:green; opacity: 1" correctAnswer > </a-entity>
var cursorVar = document.getElementById('myCursor');
var questionVar = document.getElementById('questionA');
questionVar.addEventListener('mouseenter', function() {
cursorVar.setAttribute('color', 'blue');
});
questionVar.addEventListener('mouseleave', function() {
cursorVar.setAttribute('color', 'black');
});
The cursor side also emits the event. Try listening to the event from the cursor as a workaround:
cursorEl.addEventListener('mouseleave');
0.3.0 which should be releasing tomorrow or in two days has improvements on the cursor, raycaster, and raycasting against COLLADA models. This includes the ability to limit what the raycaster tests against which would be ideal in the workaround above.
Could be several factors in your bug, I think once 0.3.0 is out, I'd be able to say with more clarity what's happening.
Does this CodePen perform as you expect?
I can't see the problem looking at your code (maybe it's something to do with the cursor primitive). Try replacing the cursor primitive with a manually defined one used in the CodePen link above:
<!-- Camera with gaze cursor -->
<a-entity position="0 1.8 5">
<a-entity camera look-controls wasd-controls>
<a-entity cursor
geometry="primitive: ring; radiusOuter: 0.025;
radiusInner: 0.015; segmentsTheta: 32"
material="color: #283644; shader: flat"
raycaster="far: 30"
position="0 0 -0.75"
id='cursor'>
</a-entity>
</a-entity>
</a-entity>
That said, the raycasting does seem a bit inaccurate (with 0.2.0 at least).