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>
Related
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
Why new_position value does not change when moving the camera and clicking again?
<html>
<head>
<meta charset="UTF-8" />
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script src="https://unpkg.com/aframe-event-set-component#3.0.3/dist/aframe-event-set-component.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("go_in_front_camera", {
init: function() {
var el = this.el;
el.addEventListener("click", function() {
console.log(
document.querySelector("a-scene").camera.el.object3D.position.x
);
var new_position_x = document.querySelector("a-scene").camera.el
.object3D.position.x;
var new_position_z = document.querySelector("a-scene").camera.el
.object3D.position.z;
var new_position = {
x: new_position_x - 1,
y: el.object3D.position.y,
z: new_position_z - 1
};
console.log(new_position);
el.setAttribute("animation", {
property: "position",
to: new_position,
dur: 2000,
easing: "linear"
});
});
}
});
</script>
</head>
<body>
<a-scene>
<a-entity
id="camera-rig"
position="0 0 0"
movement-controls="controls: cardboard, gamepad, keyboard, touch; constrainToNavMesh: true; speed: 0.2"
>
<a-entity
id="head"
camera
look-controls="pointerLockEnabled: true"
position="0 1.6 0"
>
<a-entity
cursor="fuse: true;fuseTimeout: 500"
animation__click="property: scale; startEvents: click; easing: easeInCubic; dur: 150; from: 0.1 0.1 0.1; to: 1 1 1"
animation__fusing="property: scale; startEvents: fusing; easing: easeInCubic; dur: 1500; from: 1 1 1; to: 0.1 0.1 0.1"
animation__mouseleave="property: scale; startEvents: mouseleave; easing: easeInCubic; dur: 500; to: 1 1 1"
geometry="primitive: ring; radiusInner: 0.002; radiusOuter: 0.003"
material="shader: flat; color: #f7f7ed;"
position="0 0 -0.1"
></a-entity>
</a-entity>
</a-entity>
<a-plane
id="ground_floor"
color="blue"
repeat="10 10"
rotation="-90 0 0"
width="30"
height="30"
></a-plane>
<a-sky color="#212120"></a-sky>
<a-box
position="0 1 -2"
width="1"
height="1"
color="red"
go_in_front_camera
></a-box>
</a-scene>
</body>
</html>
I edited my code to show a full example.
You're placing the box at "-1 0 -1" regarding the camera. But the camera isn't moving. It's just rotating. So it's world position isn't changing at all.
either:
translate the coordinates to the camera local space of reference
get the camera direction vector, and add it to the camera
Direction option:
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script>
AFRAME.registerComponent('go_in_front_camera', {
init: function() {
var el = this.el;
const dir = new THREE.Vector3();
el.addEventListener('click', function() {
const acamera = document.querySelector('a-scene').camera.el.object3D
acamera.getWorldDirection(dir);
dir.multiplyScalar(-2);
dir.add(acamera.position)
el.setAttribute('animation', {
property: 'position',
to: AFRAME.utils.coordinates.stringify(dir),
dur: 2000,
easing: 'linear'
});
});
}
});
</script>
<a-scene cursor="rayOrigin: mouse" raycaster="objects: a-box">
<a-box position="-1 0.5 -3" color="#4CC3D9" go_in_front_camera></a-box>
<a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
<a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
<a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
<a-sky color="#ECECEC"></a-sky>
<a-entity id="camera-rig" position="0 0 0" movement-controls="controls: cardboard, gamepad, keyboard, touch; constrainToNavMesh: true; speed: 0.2">
<a-entity id="head" camera look-controls="pointerLockEnabled: true" position="0 1.6 0">
<a-entity geometry="primitive: ring; radiusInner: 0.002; radiusOuter: 0.003" material="shader: flat; color: #f7f7ed;" position="0 0 -0.1"></a-entity>
</a-entity>
</a-entity>
</a-scene>
Since it's a rig with camera as child, the position should not be read on the camera object but on the camera parent object.
document.querySelector("a-scene").camera.el.parentNode.object3D.position
I'm trying to render entities based on an array in the state:
[
{ id: 'left', color: 'red', position: '-1 1 -4' },
{ id: 'right', color: 'green', position: '1 1 -4' }
]
The entities are displayed successfully according to
<a-entity bind-for="for: marker; in: markers; key: id"> <!-- ; updateInPlace: true ?? -->
<template>
<a-sphere color="{{marker.color}}" position="{{marker.position}}"></a-sphere>
<!-- <a-sphere bind-item__color="marker.color" bind-item__position="marker.position"></a-sphere> --><!-- state.marker is undefined -->
</template>
</a-entity>
I cannot get the entities to update when I alter the array (adding or removing elements) or manually setting the __dirty flag.
handlers: {
setMarkers: function (state, data) {
state.markers.length = 0;
state.markers.push(...data.markers);
},
updateMarkers: function (state, data) {
state.markers.__dirty = true;
}
}
Neither replacing the array elements nor setting the dirty flag works.
el.addEventListener('click', function () {
markers[0].color = markers[0].color === 'red' ? 'blue' : 'red';
//el.sceneEl.emit('setMarkers', {markers});
el.sceneEl.emit('updateMarkers', {});
});
Questions:
how can I make the state component update the entities when an array (or its items) has been updated?
when should I use updateInPlace?
why cannot I use bind-item__color="marker.color", as specified in the documentation? -- I get state.marker is undefined.
Glitch link: https://glitch.com/~aframe-state-bind-for-help
<html>
<head>
<title>Score</title>
<meta name="description" content="Incrementing and decrementing score"></meta>
<meta property="og:image" content="https://raw.githubusercontent.com/supermedium/superframe/master/components/state/examples/score/preview.gif"></meta>
<script src="https://aframe.io/releases/0.9.0/aframe.min.js"></script>
<script src="https://unpkg.com/aframe-state-component#6.7.0/dist/aframe-state-component.min.js"></script>
<script>
AFRAME.registerState({
initialState: {
markers: []
},
handlers: {
setMarkers: function (state, data) {
state.markers.length = 0;
state.markers.push(...data.markers);
},
updateMarkers: function (state, data) {
state.markers.__dirty = true;
}
}
});
let markers = [
{ id: 'left', color: 'red', position: '-1 1 -4' },
{ id: 'right', color: 'green', position: '1 1 -4' }
];
AFRAME.registerComponent('decrease-action', {
init: function () {
var el = this.el;
el.addEventListener('click', function () {
markers[0].color = markers[0].color === 'red' ? 'blue' : 'red';
//el.sceneEl.emit('setMarkers', {markers});
el.sceneEl.emit('updateMarkers', {});
});
el.sceneEl.addEventListener('stateupdate', function (e) {
console.log(JSON.stringify(e.detail.state.markers, null, 2));
});
el.sceneEl.emit('setMarkers', {markers});
}
});
AFRAME.registerComponent('increase-action', {
init: function () {
var el = this.el;
el.addEventListener('click', function () {
markers[1].color = markers[1].color === 'green' ? 'blue' : 'green';
//el.sceneEl.emit('setMarkers', {markers});
el.sceneEl.emit('updateMarkers', {});
});
}
});
</script>
</head>
<body>
<a-scene>
<a-entity text="value: Change left color; align: center; width: 2" geometry="primitive: plane" material="color: black" position="-1 1 -3" decrease-action></a-entity>
<a-entity text="value: Change right color; align: center; width: 2" geometry="primitive: plane" material="color: black" position="1 1 -3" increase-action></a-entity>
<a-entity bind-for="for: marker; in: markers; key: id"> <!-- ; updateInPlace: true ?? -->
<template>
<a-sphere color="{{marker.color}}" position="{{marker.position}}"></a-sphere>
<!-- <a-sphere bind-item__color="marker.color" bind-item__position="marker.position"></a-sphere> --><!-- state.marker is undefined -->
</template>
</a-entity>
<a-sky color="#24CAFF"></a-sky>
<a-camera>
<a-cursor color="#FAFAFA"></a-cursor>
</a-camera>
</a-scene>
</body>
</html>
Thank you.
I used the example code from the Github and plugged it into a boilerplate page:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello, World! • A-Frame</title>
<meta name="description" content="Hello, World! • A-Frame">
<script src="https://cdnjs.cloudflare.com/ajax/libs/aframe/0.7.0/aframe-master.js"></script>
<script>
AFRAME.registerComponent('cursor-listener', {
init: function () {
var lastIndex = -1;
var COLORS = ['red', 'green', 'blue'];
this.el.addEventListener('click', function (evt) {
lastIndex = (lastIndex + 1) % COLORS.length;
this.setAttribute('material', 'color', COLORS[lastIndex]);
console.log('I was clicked at: ', evt.detail.intersection.point);
});
}
});
</script>
</head>
<body>
<a-scene>
<a-entity camera>
<a-entity cursor="fuse: true; fuseTimeout: 500"
position="0 0 -1"
geometry="primitive: ring; radiusInner: 0.02; radiusOuter: 0.03"
material="color: black; shader: flat">
</a-entity>
</a-entity>
<a-entity id="box" cursor-listener geometry="primitive: box" material="color: blue" position="0, 0, -4"></a-entity>
</a-scene>
</body>
</html>
In this code snippet, I am using the cdn for aframe 0.7.0 but have also attempted 0.7.1 and master.
The cursor appears to "click" the cube once, changing its color. The view is unable to be moved in both desktop and VR mode. For example, in VR mode, when moving my head, the rectangle stays in the direct center of view.
Here is a live codepen.
How do I fix the code to allow me to be able to move the camera?
You'll want to add the look-controls component to your camera:
<a-entity camera look-controls>
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