A-frame add enable/disable component on function - javascript

I have created a scene using A-frame (https://aframe.io) and I currently have some rain in my scene and a button. What I would like to do is when the button is clicked, a function occurs, I'm wondering how I can make this function remove the rain component from the scene. Code:
<head>
<script src="https://cdn.rawgit.com/aframevr/aframe/v0.4.0/dist/aframe-master.min.js"></script>
<script src="https://rawgit.com/takahirox/aframe-rain/master/build/aframe-rain.min.js"></script>
</head>
<body>
<button onclick="toggleRain()">
Toggle rain
</button>
<a-scene rain>
<a-entity position="0 0 10">
<a-camera></a-camera>
</a-entity>
<a-entity geometry="primitive:sphere"></a-entity>
<a-sky color="#222"></a-sky>
<a-entity light="type:directional;color:#666" position="-10 -10 -10"></a-entity>
</a-scene>
</body>
What I would like to happen is when the toggleRain() function is triggered, the
<a-scene rain> part of the code will change and remove the rain part so there is just
<a-scene>
This should stop the rain from falling when the button is clicked. Just to clarify, when the function is triggered, it should rain property from the <a-scene rain> leaving just
<a-scene>
How can this be done? Link to fiddle containing code: https://jsfiddle.net/AidanYoung/z7qstgua/2/

You could just use removeAttribute() to remove the rain
function toggleRain() {
let a = document.getElementById('a');
if (a.hasAttribute('rain')) {
a.removeAttribute('rain');
} else {
a.setAttribute('rain', '1');
}
console.log ("ok");
}
<head>
<script src="https://cdn.rawgit.com/aframevr/aframe/v0.4.0/dist/aframe-master.min.js"></script>
<script src="https://rawgit.com/takahirox/aframe-rain/master/build/aframe-rain.min.js"></script>
</head>
<body>
<button onclick="toggleRain()">
Toggle rain
</button>
<a-scene id="a" rain>
<a-entity position="0 0 10">
<a-camera></a-camera>
</a-entity>
<a-entity geometry="primitive:sphere"></a-entity>
<a-sky color="#222"></a-sky>
<a-entity light="type:directional;color:#666" position="-10 -10 -10"></a-entity>
</a-scene>
</body>

Related

A-frame set websubsurface source to a variable

I am using the websurface A-frame component () and I'm wondering how I can make it so when a button is clicked, the url of the websurface will change to the value of a variable I've defined called source. What should happen is for example, if the variable source is set to "https://google.ca" and you click the button, the websurface url will change to https://google.ca. Current code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Example 1</title>
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script src="https://unpkg.com/aframe-websurfaces#1.4.0/dist/aframe-websurfaces.umd.js"></script>
<script>
function updateSource() {
let source = "https://google.ca";
}
</script>
</head>
<body>
<button style="position: fixed; z-index: 100000;" onclick="updateSource()">
update src
</button>
<a-scene>
<!--Camera-->
<a-entity
wasd-controls="acceleration: 20;"
camera="active: true"
look-controls="pointerLockEnabled: false"
position="0 1.6 0"
>
<a-cursor position="0 0 -.05" scale=".04 .04 1"></a-cursor>
</a-entity>
<!--Environment-->
<a-sky color="#aff"></a-sky>
<a-plane
rotation="-90 0 0"
width="20"
height="20"
color="#3fa841"
></a-plane>
<!--Websurface-->
<a-entity
websurface="url:https://aframe.io/; width:4; height:2;"
position="2.25 1.5 -4"
></a-entity>
</a-scene>
</body>
</html>
Fiddle with code: https://jsfiddle.net/AidanYoung/7vye3osa/2/
The component is using an i-frame accessible with the reference:
element.websurface_iframe
You can use it like any other i-frame - like changing the src property:
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script src="https://unpkg.com/aframe-websurfaces#1.4.0/dist/aframe-websurfaces.umd.js"></script>
<script>
function updateSource() {
let source = "https://threejs.org";
const websurfaceEl = document.querySelector("[websurface]")
websurfaceEl.websurface_iframe.src = source
}
</script>
<button style="position: fixed; z-index: 100000;" onclick="updateSource()">
update src
</button>
<a-scene>
<a-entity websurface="url:https://aframe.io/; width:4; height:2;"
position="0 1.6 -2"></a-entity>
</a-scene>
Keep in mind - the originating server may not welcome requests from other origins - like https://google.ca which explicitly tells you, that only websites from the same origin may display it in a frame (check the logs in the snippet below):
X-Frame-Options' to 'sameorigin'
<div>
<iframe src="https://google.ca" width="500" height="250">
</div>

A-Frame: change "visible" with set.Attribute

I have several entities in my a-scene and I want to hide them, if I click on a button.
That my JS for changing the attribute "visible":
<script>
document.querySelector('#button-right').addEventListener('mouseclick',myEventHandler);
myEventHandler: function (evt) {
let myEl = document.querySelector("#links");
myEl.setAttribute('visible',"false");
}
</script>
The script should be executed if "button_right" is clicked:
<!-- left and right button: button-left = reset background // button-right = hide links -->
<a-entity id="buttons" layout="type: line; margin: 2.5" position="-1.75 -2.5 -4">
<a-entity id="button-left" template="src: #button_reset" data-src="#default"></a-entity>
<a-entity id="button-right" template="src: #button_hide"></a-entity>
</a-entity>
If I click the right button I get this error:
Uncaught DOMException: Failed to execute 'setAttribute' on 'Element':
'0' is not a valid attribute name.
at HTMLElement.setAttribute (http://127.0.0.1:5500/assets/js/aframe-master.js:77507:51)
at HTMLElement.setAttribute (http://127.0.0.1:5500/assets/js/aframe-master.js:76931:40)
at NewComponent.module.exports.setComponentProperty (http://127.0.0.1:5500/assets/js/aframe-master.js:83857:6)
at HTMLElement.s (https://unpkg.com/aframe-event-set-component#5.0.0/dist/aframe-event-set-component.min.js:1:1990)
at HTMLElement.emit (http://127.0.0.1:5500/assets/js/aframe-master.js:77546:16)
at NewComponent.twoWayEmit (http://127.0.0.1:5500/assets/js/aframe-master.js:68002:19)
at NewComponent.onCursorUp (http://127.0.0.1:5500/assets/js/aframe-master.js:67858:12)
at HTMLCanvasElement.bound (http://127.0.0.1:5500/assets/js/aframe-master.js:83391:17)
Here is the full code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>360° Image</title>
<meta name="description" content="360° Image - A-Frame">
<script src="assets/js/aframe-master.js"></script>
<script src="assets/js/play-all-model-animations.js"></script>
<script src="https://unpkg.com/aframe-template-component#3.x.x/dist/aframe-template-component.min.js"></script>
<script src="https://unpkg.com/aframe-layout-component#4.3.1/dist/aframe-layout-component.min.js"></script>
<script src="https://unpkg.com/aframe-event-set-component#5.0.0/dist/aframe-event-set-component.min.js"></script>
</head>
<body>
<a-scene>
<a-assets>
<!-- background images -->
<img id="oberkirch" src="assets/image/oberkirch.jpg" alt="360 Degree view of the City Oberkirch">
<img id="schauenburg" src="assets/image/schauenburg.JPG" alt="360 Degree view of the Schauenburg">
<img id="city" src="assets/image/360_background.jpg" alt="360 Degree view of a city">
<img id="default" crossorigin="anonymous" src="https://cdn.aframe.io/360-image-gallery-boilerplate/img/city.jpg">
<img id="city-thumb" crossorigin="anonymous"
src="https://cdn.aframe.io/360-image-gallery-boilerplate/img/thumb-city.jpg">
<!-- Template for links -->
<script id="circle" type="text/html">
<a-entity class="link"
geometry="primitive: circle; height: 1; width: 1"
material="color: blue"
visible="true"
event-set__mouseenter="material.color: red"
event-set__mouseleave="material.color: blue"
event-set__click="_target: #image-360; _delay: 300; material.src: ${src}"
proxy-event="event: click; to: #image-360; as: image"
></a-entity>
</script>
<!-- Template for button_reset -->
<script id="button_reset" type="text/html">
<a-entity class="button"
geometry="primitive: plane; height: 0,5; width: 1s"
material="color: blue"
event-set__mouseenter="material.color: red"
event-set__mouseleave="material.color: blue"
event-set__click="_target: #image-360; _delay: 300; material.src: ${src}"
proxy-event="event: click; to: #image-360; as: image"
></a-entity>
</script>
<!-- Template for button_hide -->
<script id="button_hide" type="text/html">
<a-entity class="button"
geometry="primitive: plane; height: 0,5; width: 1s"
material="color: blue"
event-set__mouseenter="material.color: red"
event-set__mouseleave="material.color: blue"
event-set__click="_target: #link; link.setA"
></a-entity>
</script>
<!-- Script for hiding the links -->
<script>
document.querySelector('#button-right').addEventListener('mouseclick', myEventHandler);
myEventHandler: function (evt) {
let myEl = document.querySelector("#links");
myEl.setAttribute('visible', "false");
}
</script>
</a-assets>
<!-- Change the background of the scene -->
<a-sky id="image-360" radius="10" src="#default"></a-sky>
<!-- Creates a cursor -->
<a-camera>
<a-cursor id="cursor"
animation__click="property: scale; startEvents: click; from: 0.1 0.1 0.1; to: 1 1 1; dur: 150">
</a-cursor>
</a-camera>
<!-- Links for changing the background -->
<a-entity id="links" visible="true" layout="type: line; margin: 2.5" position="-3 -1 -4">
<a-entity template="src: #circle" data-src="#oberkirch"></a-entity>
<a-entity template="src: #circle" data-src="#schauenburg"></a-entity>
<a-entity template="src: #circle" data-src="#city"></a-entity>
</a-entity>
<!-- left and right button: button-left = reset background // button-right = hide links -->
<a-entity id="buttons" layout="type: line; margin: 2.5" position="-1.75 -2.5 -4">
<a-entity id="button-left" template="src: #button_reset" data-src="#default"></a-entity>
<a-entity id="button-right" template="src: #button_hide"></a-entity>
</a-entity>
</a-scene>
</body>
</html>
Thank you!
myEl.setAttribute('visible',false);
Here true and false is a boolean value so you don't need to add as a "false" in string.
Use single quotes ('#links')
And maybe try not to use numbers for id

Objects are Losing/Changing shape when used with Ar.js

I am just starting with Ar.js. I have a problem where the objects appearing on screen have lost their shapes a bit. First I have this simple A-Frame example which shows a sphere which is perfectly round:
<!DOCTYPE>
<html>
<head>
<script src="https://aframe.io/releases/1.0.4/aframe.min.js"></script>
</head>
<body>
<a-scene>
<a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"> </a-sphere>
</a-scene>
</body>
</html>
But when I use this following code of Ar.js, the same sphere looks like a oval now:
<!doctype html>
<html>
<head>
<link rel="canonical" href="https://inspiredlabs.github.io/ar.js/markerless.html" />
<!-- location based aframe v0.9.2 -->
<script src="https://aframe.io/releases/1.0.4/aframe.min.js"></script>
<script src="https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar-nft.js"></script><!-- debug -->
<script>
const log = console.log;
window.onload = () => {
let scene = document.querySelector('a-scene'); /* Apply to whole scene */
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function (position) {
let gps = document.createAttribute('gps-entity-place'),
arjs = document.createAttribute('arjs'),
arjs.value = 'sourceType: webcam; sourceWidth: 640; sourceHeight: 480; trackingMethod: best; debugUIEnabled: false;';
gps.value = `latitude: ${position.coords.latitude}; longitude: ${position.coords.longitude}`;
log(gps.value);
scene.setAttributeNode(gps); /* Apply to whole scene */
scene.setAttributeNode(arjs);
});
}
};
</script>
</head>
<a-scene device-orientation-permission-ui="enabled: true" vr-mode-ui="enabled: false">
<a-entity id="wrapper" position="0 -4 -5 " look-at="[camera]">
<a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E" shadow></a-sphere>
</a-entity><!-- /wrapper -->
<a-camera camera="fov: 60;" gps-camera rotation-reader></a-camera>
</a-scene>
</body>
</html>
I am having trouble figuring it out. Can anyone help me out here please?
Your sphere is perfectly fine. Shapes get distorted when they're close to the screen edges due to the perspective of the camera but that's absolutely normal. If you retry your first example, get further from the sphere and move it somewhere in a corner you'll see the same distortion you see in the second example. It will seem more natural with a background sky cause the whole view will get distorted in the corners. Nothing to worry about anyway!

In Aframe AR.js Show A Preloading Screen Till All The Assets Loads And Renders

I Want To Show A Preloading Screen Till All Assets Loads And Renders.
I Tried Using Assets Event loaded but its not working . When We Augment 3d Model , Image and video , So These Assets Are Almost 50-60mb . So it takes time to load the assets and augment . The video when we augment for 4-8 seconds the black screen comes and plays,if the network is slow (In inspect Network Tab Select 3G Slow We Test).
Please Edit My Code in Glitch
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello!</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script type="text/javascript" src="https://aframe.io/releases/0.8.2/aframe.min.js"></script>
<script type="text/javascript" src="https://cdn.rawgit.com/jeromeetienne/AR.js/1.7.2/aframe/build/aframe-ar.min.js"></script>
<script type="text/javascript" src="https://cdn.rawgit.com/donmccurdy/aframe-extras/v6.0.0/dist/aframe-extras.min.js"></script>
<script src="https://unpkg.com/aframe-animation-component#5.1.2/dist/aframe-animation-component.min.js"></script>
<script>
AFRAME.registerComponent("vidhandler", {
init: function () {
// Set up initial state and variables.
this.toggle = false;
this.vid = document.querySelector("#vid");
this.vid.pause();
console.log('************* Vid Paused');
},
tick: function () {
if (this.el.object3D.visible == true) {
if (!this.toggle) {
this.toggle = true;
this.vid.play();
console.log('************* Vid Play');
}
} else {
this.toggle = false;
this.vid.pause();
//console.log('************* Vid Paused');
}
}
});
</script>
</head>
<body>
<a-scene vr-mode-ui="enabled: false" artoolkit='sourceType: webcam; detectionMode: mono; maxDetectionRate: 90;' arjs='debugUIEnabled: false;detectionMode: mono_and_matrix; matrixCodeType: 3x3;'>
<!-- ALL ASSETS -->
<a-assets>
<!-- 3D MODEL -->
<a-entity id="model" src="https://cdn.glitch.com/c3106e6c-98cb-40e4-b0c1-85257680d25a%2Fygark.glb?v=1564472468760" crossorigin="anonymous" rotation="-90 0 -90">
</a-entity>
<!-- VIDEO -->
<video preload="auto" id="vid" response-type="arraybuffer" loop="false" crossorigin webkit-playsinline playsinline controls>
<source src="https://cdn.glitch.com/c3106e6c-98cb-40e4-b0c1-85257680d25a%2Fvid.mp4?v=1564472320471" type="video/mp4">
</video>
<!-- IMAGE -->
<img id="img" src="https://cdn.glitch.com/c3106e6c-98cb-40e4-b0c1-85257680d25a%2Fsun.png?v=1564472507237">
</a-assets>
<!-- ALL ASSETS -->
<a-marker type="pattern" preset="hiro" vidhandler>
<a-entity position="0 0 0">
<a-video width="2" height="2" rotation="-90 0 0" material='transparent:true;shader:flat;side:double;src:#vid'></a-video>
</a-entity>
<a-image width="2" height="2" material='transparent:true;shader:flat;side:double;src:#img' position="2 0 0" rotation="-90 0 0"></a-image>
<a-entity position="-1.5 0 0" gltf-model="#model" material='transparent:true;shader:flat;side:double;metelness:2' rotation="0 0 0" scale="0.5 0.5 0.5" shadow="receive: false" >
</a-entity>
</a-marker>
<a-entity camera>
<a-entity cursor="rayOrigin: mouse;fuse: false;"></a-entity>
</a-entity>
</a-scene>
</body>
</html>
Asset loaded event is not working . Please Edit My Code in Glitch
Thanks In Advance
There are a couple different options.
Aframe has a built in loading screen that is enabled within the <a-scene> declaration
<a-scene loading-screen="dotsColor: red; backgroundColor: black"></a-scene>
Another option is to follow the steps in the response from Noam Almosnino
Use a component like, Aframe Preloader
Note: I am not associated with this component and have not tested it. Please see the demo page for some examples
Update
Based on your comment (below) I would recommend #2 (above)
create a listener for the scene's loaded event
document.addEventListener('DOMContentLoaded', function() {
var scene = document.querySelector('a-scene');
scene.addEventListener('loaded', function (e) {
// hide splash screen
});
});

Reset orientation does not work in phone

I want reset head orientation. I did but that works in PC but not in phone. There is a button called reset. If I click that it should reset the head orientation. It does on PC but not on phone. Here is my code:
<!DOCTYPE html>
<html>
<head>
<title>Hello, WebVR! - A-Frame</title>
<meta name="description" content="Hello, WebVR! - A-Frame">
<script src="https://aframe.io/releases/0.8.0/aframe.min.js"></script>
<script src="https://rawgit.com/rdub80/aframe-gui/master/dist/aframe-gui.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<a-scene>
<a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9" shadow></a-box>
<a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E" shadow></a-sphere>
<a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D" shadow></a-cylinder>
<a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4" shadow></a-plane>
<a-gui-button resetorientation
id="reset"
class="clickable"
position="-0.038 -1.611 -3.011"
rotation="-25 0 0"
width="2.5" height="0.75"
key-code="80"
value="Reset"
font-family="Helvetica"
background-color="#A04000"
>
</a-gui-button>
<a-sky color="#ECECEC"></a-sky>
<a-camera position="0 2 0">
<a-cursor raycaster="objects: .clickable" ></a-cursor>
</a-camera>
</a-scene>
</body>
</html>
Here is my script:
AFRAME.registerComponent('resetorientation', {
init: function () {
this.el.addEventListener('click', function () {
document.querySelector('#reset').emit(reset());
});
}
});
function reset(){
var x = document.querySelector('[camera]').getAttribute('rotation').x;
var y = document.querySelector('[camera]').getAttribute('rotation').y;
console.log(x);
console.log(y);
document.querySelector('[camera]').setAttribute('rotation', {x: 0 * x});
document.querySelector('[camera]').setAttribute('rotation', {y: 0 * y});
var a = document.querySelector('[camera]').getAttribute('rotation').x;
var b = document.querySelector('[camera]').getAttribute('rotation').y;
console.log(a);
console.log(b);
}
You would need to get into the look-controls and manually add an offset to the x-y-z rotations it gets from the gyroscope.
A workaround making sense with only the yaw (y) value, would be wrapping the camera in an entity, and when you click reset, you rotate the wrappers yaw.
Live fiddle here.

Categories