Enter VR in Aframe via eye-gazing button - javascript

I enabled the vr-mode-ui and I would like to have a button inside my aframe scene which enters vr mode by click. My problem is my js gives me a TypeError: document.getElementById(...) is null and I don`t know why!
<script>
AFRAME.registerComponent('enter', {
init: function () {
}
});
document.getElementById('startbutton').addEventListener("click", (e)=>{
scene.enterVR(true);
});
</script>
<a-scene id="scene" antialias="true"; cursor="rayOrigin: mouse" vr-mode-ui="enabled: true">
<a-assets>
<img id="startscreen" src="start_overlay.png">
</a-assets>
<!-- Environment -->
<a-sky id="environment" radius="9" rotation="0 -90 0"; material="shader: flat; src: #xxx"></a-sky>
<!-- Camera + cursor + Startscreen + Interaction-->
<a-entity look-controls>
<a-entity id="start">
<a-plane id="startbutton" class="link"; height="0.5"; width="5"; position="0 -0.7 -2" rotation="0 0 0" color="#ffbff0">
<a-text align="center" value="START" width="10" color="#e143a1"></a-text>
</a-plane>
</a-entity>
<a-entity id="cam" camera rotation="0 0 0" mouse-cursor>
<a-cursor id="cursor" color="red"
animation__click="property: scale; startEvents: click; from: 0.1 0.1 0.1; to: 1 1 1; dur: 150"
animation__fusing="property: fusing; startEvents: fusing; from: 1 1 1; to: 0.1 0.1 0.1; dur: 1500"
event-set__1="_event: mouseenter; color: white"
event-set__2="_event: mouseleave; color: red"
fuse="true"
raycaster="objects: .link"></a-cursor>
</a-entity>
</a-entity>
</a-scene>
I dont know why my button isnt recognized by the js-script!
Could someone help, please! Cheers, Can

The button may not be present in the DOM by the time the code is executed. Either :
1) throw the code into a AFRAME component,
2) place the code after the HTML body, or
3) place it in a window.onload callback:
window.onload = function() {
doSomething();
};
Also, as you can see in the docs, the proper method is to call enterVR(), or exitVR() on the scene element. Make sure the scene reference you use actually holds the scene element.

Related

Why aren't my A-Frame animations looping properly?

I am trying to get these animations to loop, but they only run once each then stop. My code is as follows
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<a-scene>
<a-box height=0.1 width=3 depth=7 position="0 3.5 0" color="#964800" rotation="45 0 0"
animation__first="property:rotation; from:45 0 0; to:-45 0 0; dur:300 startEvents:loaded, animationcomplete__second;"
animation__second="property:rotation; from:-45 0 0; to:45 0 0; delay:500; startEvents:animationcomplete__first;">
<a-cone radius-bottom=1.5 radius-top=1.5 height=1.5 position="0 .75 2" color="#964800"></a-cone>
</a-box>
</a-scene>
I've tried changing the first and second to 1 and 2 with no change and I tried changing the order of loaded and animationcomplete which, once again, changed nothing.
You're missing a semicolon in the first animation (so i guess the startEvents aren't properly parsed at all, and the first animation starts on loaded by default. With the semicolon it works properly:
<script src="https://aframe.io/releases/1.4.0/aframe.min.js"></script>
<a-scene>
<a-box height=0.1 width=3 depth=7 position="0 3.5 -5" color="#964800" rotation="45 0 0"
animation__first="property:rotation; from:45 0 0; to:-45 0 0;
dur:300; startEvents:loaded, animationcomplete__second;"
animation__second="property:rotation; from:-45 0 0; to:45 0 0;
delay:500; startEvents: animationcomplete__first;">
<a-cone radius-bottom=1.5 radius-top=1.5 height=1.5 position="0 .75 2" color="#964800"></a-cone>
</a-box>
</a-scene>

AFRAME I cant display informations on pictures on click

I am starting aframe and I cant display some informations (a small text) on pictures.
If you could help me it would be very nice.
I put the script of my pictures in the head of my html page.
<script id="panInfor" type="text/html">
<a-entity class="panInfor"
geometry="primitive: plane; height: 1; width: 1"
material="shader: flat; src: ${thumb}"
sound="on: click; src: #click-sound"
event-set__mouseenter="scale: 1.2 1.2 1"
event-set__mouseleave="scale: 1 1 1"
event-set__click="_target: #text-informations;_delay: 300; material.src: ${src}"
proxy-event="event: click; to: #text-informations; as: switch">
</a-entity>
</script>
In the asset I put this code concerning the text of my picture
<a-text position="1 2 -4" rotation="0 -90 0" id="text-messi" value="Greatest Of All Times" align="center">
</a-text>
And out of the asset, in the ascene, i put this code :
<a-text id="text-informations" src="#text-messi" visible="false"
animation__click="property: visible; dur: 0; to: true; startEvents: switch" color="yellow">
</a-text>
The aim of my code is just to display informations when I click on the pictures.
I wanted to display informations on pictures, retrieving the code of the tutorial of aframe "360 image gallery" but it doesnt work...
Thank you
Afaik you can't place one a-text node in the assets and refer to it from another a-text node - the assets are rather used to load resources like images, models, videos, sound etc.
If you add the text via the value attribute to the animated a-text entity, it's working:
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script src="https://unpkg.com/aframe-proxy-event-component/dist/aframe-proxy-event-component.min.js"></script>
<script src="https://unpkg.com/aframe-event-set-component#5.0.0/dist/aframe-event-set-component.min.js"></script>
<a-scene cursor="rayOrigin: mouse" raycaster="objects: a-entity">
<a-entity position="0 1.6 -2"
geometry="primitive: plane; height: 1; width: 1"
material="shader: flat; color: green"
event-set__mouseenter="scale: 1.2 1.2 1"
event-set__mouseleave="scale: 1 1 1"
proxy-event="event: click; to: #text-informations; as: switch">
<a-text id="text-informations" value="Greatest Of All Times" align="center" visible="false"
animation__click="property: visible; dur: 0; to: true; startEvents: switch" color="yellow">
</a-text>
</a-entity>
</a-scene>
I'd strongly recommend trying to create a custom component, which would handle the hide-show logic:
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script src="https://unpkg.com/aframe-event-set-component#5.0.0/dist/aframe-event-set-component.min.js"></script>
<script>
// the component has to be defined before the <a-scene>
AFRAME.registerComponent("show-text", {
// a schema, so we can provide different <a-text>s
schema: {
txt: {type: "selector"}
},
// called upon initialisation
init: function() {
// on each click - toggle the visibility
this.el.addEventListener("click", evt => {
// if the text is invalid - lets get outta here
if (!this.data.txt) return;
// get the current visibility
const visible = this.data.txt.getAttribute("visible")
// set the visibility to its opposite
this.data.txt.setAttribute("visible", !visible)
})
}
})
</script>
<a-scene cursor="rayOrigin: mouse" raycaster="objects: a-entity">
<a-entity position="-1 1.6 -2"
geometry="primitive: plane; height: 1; width: 1"
material="shader: flat; color: green"
event-set__mouseenter="scale: 1.2 1.2 1"
event-set__mouseleave="scale: 1 1 1"
show-text="txt: #text-informations">
<a-text id="text-informations" value="Greatest Of All Times" align="center" visible="false"
animation__click="property: visible; dur: 0; to: true; startEvents: switch" color="yellow">
</a-text>
</a-entity>
<a-entity position="1 1.6 -2"
geometry="primitive: plane; height: 1; width: 1"
material="shader: flat; color: green"
event-set__mouseenter="scale: 1.2 1.2 1"
event-set__mouseleave="scale: 1 1 1"
show-text="txt: #text-informations2">
<a-text id="text-informations2" value="Something Else" align="center" visible="false"
animation__click="property: visible; dur: 0; to: true; startEvents: switch" color="yellow">
</a-text>
</a-entity>
</a-scene>

How do I trigger an animation in A-frame 1.0.4?

After reading through the a-frame animation documentation, I was working around with some code in JSFiddle to get an idea of how it actually works. Seemed pretty simple... Until I tried to apply it to my own project. What was working in JSFiddle, doesn't work in my project. The console returns the error: "document.querySelector(...).emit is not a function". In the fiddle I was working on, a-frame was set to its 0.3.0 version. I need to use the most recent version - 1.0.4. Is there an alternative to "emit"?
Here's the JSFiddle, and a code snippet. Both are working with the 0.3.0 version of A-Frame.If you change the script src from "https://aframe.io/releases/0.3.0/aframe.min.js" to "https://aframe.io/releases/1.0.4/aframe.min.js" though, you will observe that it no longer works.
https://jsfiddle.net/6y5qbr4z/
function lookAway() {
document.getElementById("myCam").innerHTML = '<a-animation id="away" begin="move-away" attribute="rotation" dur="2000" to="20 20 0"></a-animation>';
setTimeout(function(){document.querySelector('#away').emit('move-away');}, 1)
}
.sceneWrapper {
position: relative;
padding-top: 20px;
height: 100vh;
}
<script src="https://aframe.io/releases/0.3.0/aframe.min.js"></script>
<button id="btn01" type="button" name="button" onclick="lookAway();">Look Away</button>
<div class="sceneWrapper">
<a-scene embedded>
<a-camera id="myCam" wasd-controls-enabled="false" look-controls="reverseMouseDrag:true">
</a-camera>
<a-sky src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Equirectangular_projection_SW.jpg/1920px-Equirectangular_projection_SW.jpg"></a-sky>
<a-sphere id="ball" material="color: red" position="0 1.5 -5"></a-sphere>
</a-scene>
</div>
I tried running your examples both the JS fiddle and the code snipet provided. on my local machine i.e through create a html page, add script, css and test,both are working without any errors.
I got this error when I block the aframe.io libraty from loading in the network tab.Can you please confirm that this is not the case.
Are you triggering the lookAway() function before aframe.io library has loaded ?
Is your library loading properly ?
If the above reasons are not one of the reasons for your error.please can you provide more info.
I also checked the checked the documentation for an alernative of .emit function
emit : emits a custom DOM event on the entity. For example, we can emit an event to trigger an animation
So we can trigger custom DOM evennts using javascript as well. please refer snippet for example.
function moveAway() {
document.getElementById("myCam").innerHTML = '<a-animation id="away" begin="move-away" attribute="rotation" dur="2000" to="20 20 0"></a-animation>';
// setTimeout(function(){
// document.querySelector('#away').emit('move-away');},
// 1)
setTimeout(() => document.querySelector('#away').dispatchEvent(new CustomEvent("move-away", {
bubbles: true
})));
}
.sceneWrapper {
position: relative;
padding-top: 20px;
height: 100vh;
}
<script src="https://aframe.io/releases/0.3.0/aframe.min.js"></script>
<button id="btn01" type="button" name="button" onclick="moveAway();">Move Away</button>
<div class="sceneWrapper">
<a-scene embedded>
<a-camera id="myCam" wasd-controls-enabled="false" look-controls="reverseMouseDrag:true">
</a-camera>
<a-sky src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Equirectangular_projection_SW.jpg/1920px-Equirectangular_projection_SW.jpg"></a-sky>
<a-sphere id="ball" material="color: red" position="0 1.5 -5"></a-sphere>
</a-scene>
</div>
I get your point now, sorry I didnt notice the version above
The <a-animation> element was deprecated in a-frame 0.9.0 in favor of the animation component.
It should look a little bit like this:
<a-camera id="myCam" wasd-controls-enabled="false" rotation="0 0 0" look-controls="reverseMouseDrag:true" animation="property: rotation; to: 0 360 0; loop: false; dur: 10000; startEvents: move-away">
please refer example implementation example
function moveAway() {
// document.getElementById("myCam").setAttribute("animation", "property: rotation; to: 0 360 0; loop: false; dur: 10000; startEvents: move-away")
// document.getElementById("myCam").innerHTML = '<a-animation id="away" begin="move-away" attribute="rotation" dur="2000" to="20 20 0"></a-animation>';
setTimeout(function(){
document.querySelector('#myCam').emit('move-away');},
1)
}
.sceneWrapper {
position: relative;
padding-top: 20px;
height: 100vh;
}
<script src="https://aframe.io/releases/1.0.4/aframe.min.js"></script>
<button id="btn01" type="button" name="button" onclick="moveAway();">Move Away</button>
<div class="sceneWrapper">
<a-scene embedded>
<a-camera id="myCam" wasd-controls-enabled="false" rotation="0 0 0" look-controls="reverseMouseDrag:true" animation="property: rotation; to: 0 360 0; loop: false; dur: 10000; startEvents: move-away">
</a-camera>
<a-sky src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Equirectangular_projection_SW.jpg/1920px-Equirectangular_projection_SW.jpg"></a-sky>
<a-sphere id="ball" material="color: red" position="0 1.5 -5"></a-sphere>
</a-scene>
</div>
Please do let me know if anything else is needed.
Thank you

Changing <a-mixin> material texture with a javascript ID on a button press

So I have the following code:
function pictureChange()
{
document.getElementById("theImage").src="img02.png";
}
<a-mixin id="voxel"
geometry="primitive: box; height: 0.6; width: 0.6; depth: 0.6"
material="id: theImage; src: Box.jpg; color: #696969; roughness: 1; metalness: 0"
snap="offset: 0.4 0.4 0.4; snap: 0.6 0.6 0.6"
></a-mixin>
And I wanted to use the ID "theImage" to change the image url to somthing else, but CSS3 in Aframe doesn't work the same so I can't get it to run properly. If anybody has any ideas that might help me, it would be very appreciated. Thanks.
PS: to clarify, I want some way to change the url by the press of a button.
The id refers to an entity or asset, not a material. Try setting the image on the mixin:
var mixinEl = document.getElementById('voxel');
mixinEl.setAttribute('material','src: #super');
Example: https://glitch.com/edit/#!/swamp-sparrow?path=index.html:1:0

AngularJS - Fire a function on ng-init=true

Hi I have the following code:
html:
<div class="portlet-titlebar"
ng-click="toggleCollapsed(portlet, $event)"
ng-class="{current: hover}"
ng-init="hover = false"
ng-mouseenter="hover = hoverIn()"
ng-mouseleave="hover = false">
<span class="arrow">
<svg height="20" viewBox="0 0 32 32" width="20"><path d="M16.7 11.3c-0.4-0.4-1-0.4-1.4 0l-9 9c-0.4 0.4-0.4 1 0 1.4 0.4 0.4 1 0.4 1.4 0L16 13.4l8.3 8.3c0.4 0.4 1 0.4 1.4 0 0.4-0.4 0.4-1 0-1.4L16.7 11.3z" fill="#121313"/></svg>
</span>
<span class="titlebar-text" title="{{portlet.title}}">{{portlet.title}}</span>
</div>
inside the angularJS directive:
scope.hoverIn = function(){
if(event.ctrlKey){
return true;
}
return false;
}
I'm using less for the styling, so inside my less file I have:
.current{
border: 1px solid red;
}
Now what I'm trying to do is: on mouseover + crtl key pressed, I want to change the span class="arrow" icon to another icon and then on click on the icon (while ctrl is still pressed) fire another function. Anybody know what is the best approach to this, as I tried to handle the hover like so, but it didn't work:
document.element.getElementsByClassName('portlet-titlebar').hover(function () {
$(this).toggleClass('current');
});
$(document).keypress(function (e) {
if (e.which == 17) {
$('.current').remove();
}
});
but for some reason it doesn't work..
you have javascript event .onmouseover, i think it will do the job

Categories

Resources