I (a very amateur programmer) am trying to make an environment in A-frame where you point a cursor at different objects and it changes the displayed value on a thermometer: https://fst-retail-safety.glitch.me
The site never loads completely on the first try but reliably loads upon refresh. If I omit the cursor listener from the GLTF used for the environment, it also loads correctly. Any ideas on how to fix this? Perhaps the cursor is trying to fuse with the background object before it loads and it's causing an error? Many thanks for any help.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Food Service Temperature Inspection</title>
<meta name="description" content="Environment test" />
<script src="https://aframe.io/releases/1.1.0/aframe.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/donmccurdy/aframe-extras#v6.1.1/dist/aframe-extras.min.js"></script>
<script>
AFRAME.registerComponent("cursor-listener-box", {
init: function() {
this.el.addEventListener("click", function(evt) {
let target1 = document.querySelector("#IRtext");
target1.setAttribute("value", "100");
});
}
});
</script>
<script>
AFRAME.registerComponent("cursor-listener-background", {
init: function() {
this.el.addEventListener("click", function(evt) {
let target1 = document.querySelector("#IRtext");
target1.setAttribute("value", "65");
});
}
});
</script>
</head>
<body>
<a-scene background="color: #FAFAFA" renderer="colorManagement: true">
<a-assets>
<a-asset-item
id="gltf"
src="https://cdn.glitch.com/13648f22-5ed9-4349-ad71-1e8bd63b6485%2Fpumptest20.glb"
></a-asset-item>
<a-asset-item
id="IRthermo"
src="https://cdn.glitch.me/7344c97b-c709-4f6e-a17b-3a7e1c7278a4%2FIR%20thermometer.glb"
></a-asset-item>
<a-asset-itm
id="navmesh"
src="https://cdn.glitch.com/13648f22-5ed9-4349-ad71-1e8bd63b6485%2Fpumpnavmesh7.glb"
></a-asset-itm>
<img
id="concrete"
src="https://cdn.glitch.me/13648f22-5ed9-4349-ad71-1e8bd63b6485%2Fconcrete.jpg"
/>
<img
id="background"
src="https://cdn.glitch.me/13648f22-5ed9-4349-ad71-1e8bd63b6485%2Findustrial_1k.jpg"
/>
<img
id="watertank"
src="https://cdn.glitch.me/13648f22-5ed9-4349-ad71-1e8bd63b6485%2Fwatertank.jpg"
/>
</a-assets>
<a-entity
gltf-model="#gltf"
scale="0.15 0.15 0.15"
position="0 1.5 -2"
cursor-listener-background
></a-entity>
<a-light
type="directional"
intensity="0.7"
color="#FAFAFA"
position="0 4 0"
></a-light>
<a-light
type="ambient"
intensity="0.6"
color="#FAFAFA"
position="0 4 0"
></a-light>
<a-box
material="src: #watertank"
scale="5 3.3 5"
position="-6.3 1.93 -1.4"
></a-box>
<a-box
material="src: #watertank"
scale="5 3.3 5"
position="-2 4.5 -11"
></a-box>
<!--test shapes for script-->
<a-entity
geometry="primitive:box"
material="color:green; shader:flat"
position="0 1.6 -1"
scale="0.2 0.2 0.2"
cursor-listener-box
></a-entity>
<a-entity
gltf-model="#navmesh"
scale="0.15 0.15 0.15"
position="0 -.3 -2"
visible="true"
nav-mesh
></a-entity>
<a-entity
geometry="primitive: plane; height: 10; width: 10"
material="src: #concrete; repeat:10 10"
position="0 .3 0"
rotation="-90 0 0"
></a-entity>
<a-sky src="#background"></a-sky>
<!--Player rig-->
<a-entity
id="rig"
movement-controls="speed: 0.08; constrainToNavMesh: true"
>
<a-entity camera position="0 1.6 0" look-controls>
<a-entity
cursor="fuse: true; fuseTimeout: 100"
position="0 0 -0.5"
geometry="primitive: ring; radiusInner: 0.007; radiusOuter: 0.01"
material="color: black; shader: flat"
>
</a-entity>
<a-entity
gltf-model="#IRthermo"
scale="0.05 0.05 0.05"
position="0.15 0 -0.5"
rotation="0 -90 0"
></a-entity>
<a-text
id="IRtext"
value="25"
align="center"
color="black"
position="0.184 0.01 -0.295"
scale="0.1 0.1 0.1"
rotation="-16 0 0"
></a-text>
<a-text
value="TEMPERATURE"
align="center"
color="black"
position="0.184 0.03 -0.295"
scale="0.03 0.03 0.03"
rotation="-16 0 0"
></a-text>
<a-text
value="F"
align="center"
color="black"
position="0.19 -0.014 -0.29"
scale="0.1 0.1 0.1"
rotation="-16 0 0"
></a-text>
<a-entity
geometry="primitive: ring; radiusInner:0.002; radiusOuter:0.003"
material="color: black; shader: flat"
position="0.18 -0.01 -0.29"
rotation="-16 0 0"
></a-entity>
</a-entity>
</a-entity>
</a-scene>
</body>
</html>
I've opened it up, and when something in the scene isn't loaded, there is a nice log in the console:
Uncaught TypeError: Cannot read property 'array' of undefined
at TextGeometry.computeBoundingSphere (index.js:96)
at P.raycast (three.js:8649)
(....)
No need to search for the array of undefined - the rest tells us that there is an issue with raycasting the text elements.
Since you only want to interact with certain things (which aren't text elements), you can specify which items should the cursor interact with:
<!-- let them share a common class -->
<a-box class="interactable></a-box>
<!-- raycaster setup -->
<a-entity
cursor="fuse: true; fuseTimeout: 100"
raycaster="objects: .interactable">
</a-entity>
Like i did in this remix
The problem:
I want to make a ball the user can throw. With my current implementation, physics work but I cannot lift the ball. However, if I delete the "dynamic-body" I can grab the ball exactly as I am supposed to, and move it around. Heck, I tried changing it to "static-body" and it still works. The problem seems to be whenever I mix grabbable and dynamic-body. I know it should be possible in an older version, as I was using this tutorial: https://www.youtube.com/watch?v=SKYfYd3pk4I
However, he is using progressive-controls which are not available in the newest super-hands package, I don't know if that changes anything. Is there anything I am doing wrong here?
Here are my snippits of code that could affect the result:
My A-Frame packages:
<head>
<!-- A-Frame -->
<script src="https://aframe.io/releases/1.0.4/aframe.min.js"></script>
<!-- A-Frame Components -->
<!-- A-Frame Particle System -->
<script src="https://unpkg.com/aframe-particle-system-component#1.0.9/dist/aframe-particle-system-component.min.js"></script>
<script src="https://unpkg.com/aframe-environment-component/dist/aframe-environment-component.min.js"></script>
<!-- A-Frame Event System -->
<script src="https://unpkg.com/aframe-event-set-component#4.2.1/dist/aframe-event-set-component.min.js"></script>
<!-- A-Frame Extras Add-Ons -->
<script src="https://cdn.jsdelivr.net/gh/donmccurdy/aframe-extras#v6.1.1/dist/aframe-extras.min.js"></script>
<!-- A-Frame Physics -->
<script src="https://cdn.jsdelivr.net/gh/n5ro/aframe-physics-system#v4.0.1/dist/aframe-physics-system.min.js"></script>
<!-- A-Frame Physics Extra Add-On -->
<script src="https://unpkg.com/aframe-physics-extras#0.1.2/dist/aframe-physics-extras.min.js"></script>
<!-- A-Frame Super Hands -->
<script src="https://unpkg.com/super-hands#3.0.0/dist/super-hands.min.js"></script>
</head>
My problematic sphere:
<!-- Ball -->
<a-entity
id="Ball-2"
position="0 0 0">
<a-sphere
id="Ball-2-collider"
grabbable
dynamic-body="mass: 0.2; linearDamping: 0.05; angularDamping: 0.3; shape: sphere;
sphereRadius: 0.125;"
class="interactable ball"
radius="5"
position="0 0.6 3.8"
scale="0.02 0.02 0.02">
<a-entity
id="ball-2-mesh"
position="0 -6 0"
rotation="0 0 0"
scale="600 600 600"
gltf-model="#Ball-glb"
color="#FFFFFF">
</a-entity>
</a-sphere>
</a-entity>
My controller-setup:
<a-entity id="camera-rig" position="0 -1.20 4" rotation="0 150 0">
<a-camera
user-height="1.6"
active="true">
<a-entity
cursor="fuse: true; fuseTimeout: 1000"
raycaster="objects: .interactable"
animation__fusing="property: scale; startEvents: fusing; easing: linear; dur: 1000; from: 1 1 1; to: 3 3 3"
animation__leave="property: scale; startEvents: mouseleave; easing: linear; dur: 1; from: 1 1 1; to: 1 1 1"
animation__click="property: scale; startEvents: click; easing: linear; dur: 150; from: 3 3 3; to: 1 1 1"
position="0 0 -1"
geometry="primitive: sphere; radius: 0.005"
material="color: #FF00FF; shader: flat; opacity: 0.5">
</a-entity>
</a-camera>
<a-entity sphere-collider="objects: .interactable" handModelStyle: lowPoly; super-hands hand-controls="hand: left"></a-entity>
<a-entity sphere-collider="objects: .interactable" handModelStyle: lowPoly; super-hands hand-controls="hand: right"></a-entity>
</a-entity>
And finally, the a-scene defining the gravity:
<a-scene embedded antialias="false" physics="gravity: -9.8; debug: true">
Thanks to this: https://github.com/bryik/aframe-ball-throw/blob/master/index.html
I found the culprit.
I needed to add the static-body to my hand-entities, so that collision could be detected. No idea why collision was detected without them before though.
Modified code:
<a-entity static-body="shape: sphere; sphereRadius: 0.02;" sphere-collider="objects: .interactable" handModelStyle: lowPoly; super-hands hand-controls="hand: left"></a-entity>
<a-entity static-body="shape: sphere; sphereRadius: 0.02;" sphere-collider="objects: .interactable" handModelStyle: lowPoly; super-hands hand-controls="hand: right"></a-entity>
I'm trying to create a web page that contains an A-Frame box that rotates 90 degrees when it's clicked. I've tried various things including using the aframe-event-set-component library. I can't quite seem to get it to work. I suspect I have a syntax problem but I cannot figure out my mistake.
Any help you can provide would be greatly appreciated.
The following is my code using the aframe-event-set-component.
Thanks in advance for your help.
Tim
<html>
<head>
<title>Cursor</title>
<meta name="description" content="Changing properties in response to cursor component events"></meta>
<meta property="og:image" content="https://raw.githubusercontent.com/ngokevin/kframe/master/components/event-set/examples/basic/preview.gif"></meta>
<script src="node_modules\aframe-event-set-component\examples\build.js">
</script>
</head>
<body>
<a-scene>
<a-entity geometry="primitive: box" material="color: #FCB241"
event-set__1="_event: click; material.color:red
attribute="rotation dur='5000' repeat='0' to='0 90 0'""
event-set__2="_event: mouseenter; material.color: #5A67A6"
event-set__3="_event: mouseleave; material.color: #FCB241"
position="-1 0 -2">
</a-entity>
<a-sky color="#D68D08"></a-sky>
<a-entity camera look-controls>
<a-entity cursor
geometry="primitive: ring; radiusInner: 0.01; radiusOuter:
0.016"
material="color: #EEE"
position="0 0 -1"></a-entity>
</a-entity>
</a-scene>
<!--githubcorner-->
<a href="https://github.com/ngokevin/kframe/tree/master/components/event-set/examples/basic/" class="github-corner">
<svg width="80" height="80" viewBox="0 0 250 250" style="fill: #111; color: #EFEFEF; position: fixed; bottom: 0; border: 0; left: 0; transform: rotate(180deg); opacity: 0.8">
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path>
</svg>
</a>
<style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}#keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}#media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}
</style>
<!--endgithubcorner-->
</body>
</html>
`
Timothy,
If You wanna just rotate it, add the rotation attribute to the event:
event-set__1="_event: click; material.color:#ff0000;rotation:0 90 0"
On the other hand, i presume you want to have an animation, so You will have to either:
use the <a-animation> component, or use kevin's ngo animation-component: https://github.com/ngokevin/kframe/tree/master/components/animation
You'd need to declare an animation to 0 90 0, make a startEvent, and make the click emit that event:
<a-entity geometry="primitive: box" material="color: #FCB241"
event-set__1="_event: click; material.color:#ff0000;"
event-set__2="_event: mouseenter; material.color: #0000ff"
event-set__3="_event: mouseleave; material.color: #FCB241"
position="-1 0 -2"
animation__rotate="property: rotation; dir: forward; dur: 1000;
easing: easeInSine; loop: false; to: 0 90 0;
startEvents:click">
</a-entity>
The following plunk shows how to make it rotate on click with the animation component:
https://plnkr.co/edit/k9Jc5qEG0ckEovquEZi4?p=preview
If You don't want the animation, just replace Your event-set__1 with mine.
PERSONALLY i'd rather register my own component # AFRAME.registerComponent (name, definition), because I like to handle events by on own.
I'm trying to figure out why my console isn't recording my log statements in my click event handlers. Any help would be greatly appreciated.
Here's my JS Fiddle. https://jsfiddle.net/tznezkqo/
I'm using A-Frame version 5.0
Here's my HTML
<!-- Player -->
<a-entity camera universal-controls="movementControls: checkpoint" checkpoint-controls="mode: animate"
position="0 1.764 0">
<a-entity cursor="fuse: true; fuseTimeout: 500" position="0 0 -1"
geometry="primitive: ring; radiusInner: 0.02; radiusOuter: 0.03;" material="color: #CCC; shader: flat;">
</a-entity>
</a-entity>
<a-entity id="box" cursor-listener geometry="primitive: box" material="color: blue" position="-2 2.2 -1.5"></a-entity>
and my JS
$(document).ready(function() {
AFRAME.registerComponent('cursor-listener', {
init: function () {
this.el.addEventListener('click', function (evt) {
console.log('I was clicked at: ', evt.detail.intersection.point);
});
}
});
AFRAME.registerComponent('collider-check', {
dependencies: ['raycaster'],
init: function () {
this.el.addEventListener('raycaster-intersected', function () {
console.log('Player hit something!');
});
}
});
});
I believe you'll have to make sure the component is registered before the elements are used.
here's a modified version of your example: https://jsfiddle.net/pj3m4obt/2/
<script>
AFRAME.registerComponent('cursor-listener', {
init: function () {
this.el.addEventListener('click', function (evt) {
console.log('I was clicked at: ', evt.detail.intersection.point);
});
}
});
</script>
<body>
...
<a-entity id="box" cursor-listener geometry="primitive: box" material="color: blue" position="-2 2.2 -1.5"></a-entity>
Click events aren't triggering on entities that have cursor-listener set. Here is my source code.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Panorama</title>
<meta name="description" content="Panorama — A-Frame">
<script src="https://cdnjs.cloudflare.com/ajax/libs/aframe/0.4.0/aframe.min.js"></script>
<script type="javascript" >
AFRAME.registerComponent('cursor-listener', {
init: function () {
var COLORS = ['red', 'green', 'blue'];
this.el.addEventListener('click', function (evt) {
var randomIndex = Math.floor(Math.random() * COLORS.length);
this.setAttribute('material', 'color', COLORS[randomIndex]);
console.log('I was clicked at: ', evt.detail.intersection.point);
});
}
});
</script>
</head>
<body>
<a-scene>
<a-sky src="image.jpg" rotation="0 0 0"></a-sky>
<a-camera fov=60 >
<a-entity cursor="fuse: false; fuseTimeout: 500;"
position="0 0 -1"
geometry="primitive: ring; radiusOuter: 0.05; radiusInner: 0.02"
material="color: white; shader: flat" >
</a-entity>
</a-camera>
<a-box color="#aa77dd" cursor-listener width="50" height="10" depth="20" position="-7.45 40.00 -141.77" id="Play">
</a-box>
</a-scene>
</body>
</html>
I tried doing this on a phone and a desktop browser and neither work.
The cursor component works on desktop with mouse dragging the camera to look at the entity. On mobile, it's using fuse or Cardboard button. On VR, it's also gaze-based.
Doesn't work with just clicking the mouse or tapping the phone. Look at https://github.com/mayognaise/aframe-mouse-cursor-component