AFRAME I cant display informations on pictures on click - javascript

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>

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>

SVG access to path when instantiated with a use (shadowDOM) (vanilla javascript)

I'd like to manipulate the internal path of a SVG which is in a separate file and instantiated with a "use"
here is my code
<!DOCTYPE html><meta charset="utf8"/>
<script src="https://ipfs.blockringtm.ml/ipfs/QmZU12UqysToVJjNmWo3E31i4tmmMbWyxZ82Vyse9CQp49/path-data-polyfill.js"></script>
<svg data="logo.svg" type="image/svg+xml" id="logo"
width="120px"
preserveAspectRatio="xMidYMin slice" viewBox="0 0 512 512"
>
<!-- https://stackoverflow.com/questions/65526455/trying-to-access-svg-elements-generated-with-use-with-javascript -->
<!--
SVG use elements are like shadow DOM elements in HTML. Only the attributes
of the USE element itself is exposed via the SVG DOM - you cannot alter
any properties on a single USE element instance that are being cloned
from the original symbol. It's not like a macro.
-->
<use id="logo1" xlink:href="logo.svg#logo"></use>
</svg>
<script>
var svg = document.querySelector('#logo');
var use = svg.querySelector('#logo1');
console.log('use:',use);
var paths = use.querySelectorAll('path'); // FAILED HERE : empty NodeList: []
console.log('paths:',paths);
for (let path of paths) {
var pathdata = path.getPathData();
console.log(pathdata);
}
</script>
The svg file is :
<svg id="logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 196.1 236.8">
<defs>
<linearGradient id="a">
<stop offset="0" stop-color="#606"/>
<stop offset="1"/>
</linearGradient>
</defs>
<path id="pin" fill="#01a49b" d="M30.3 168a94.8 94.8 0 0063.2 27.2 95 95 0 0065.6-21.8c.8-.8 17.6-16 1.2.6l-28 28.2L98 236.8l-68.1-68c-6.5-6.5-12.6-15.5-12.6-15.5a88.1 88.1 0 0013 14.7z"/>
<path if="wrench" fill="#660266" d="M13.5 47.8C36.2 8.5 97-15.8 145 11.9c41.1 23.7 69.1 81.4 37.6 135-17.6 30-49.3 44-65 46.7-4 .7-18.3 1.9-22.5 1.9-1.3-.1-1.8-1.2-1-2.6l17.5-30.8c14.7-4.5 32-11.3 44.2-32.4a66.7 66.7 0 00-26.5-90.8C93.8 18.7 55 37.9 40 63.7A64.5 64.5 0 0051 144l8.2-14.5c2.2-3.8 2.4-4.5-.2-9A46.6 46.6 0 0158 73.3a44.8 44.8 0 0134.5-21.7c5.4-.3 4.8 1 3.7 2.7L80 82.3l9.4 16.3c1.7 3 5 6 8.5 5.9l22-2 15.3-26c1.3-1.9 2.2 0 3 2.2.7 2.2 10.4 16.9-2.5 39.3a45.3 45.3 0 01-37.9 23.4c-4.8-.3-6.1 2.5-8.7 7L65 190A99.7 99.7 0 012.7 121c-6.4-25.7-.8-53.3 10.8-73.3z"/>
</svg>
if I use an <object> tag instead of the <use> I can access the internal path with a path.pathSegList
however it doesn't work with path.getPathData pollyfill as the path is a plain object and not a SVGPathElement.
Questions :
how to I get a SVGPathElement from a path within an Object tag ?
i.e. how to I cast a DOMobject into a SVGPathElement ?
alternatively is there a way to I get and "open" shadow-root with the use tag, do I need to create the tag within the script to keep it open ?
The code (that works) with the object tag instance is :
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, initial-scale=1.0" charset="utf8">
<script src="http://ipfs.blockringtm.ml/ipfs/QmU3jKAewrHV8Wryx2WzT5v72PsgT7wt8FgnL8mqmWk259/path-data-polyfill.js"></script>
<style>
body { border:0; margin:0; padding: 0; height: 100vh; top: 0; }
svg { border: 1px dashed #555 }
</style>
<object id="sotest1" style="width:100px" data="logo.svg" type="image/svg+xml"></object>
<script>
let obj = document.querySelector('#sotest1');
obj.addEventListener("load",function(){
console.log('obj.loaded !');
var svgDoc = obj.contentDocument;
console.log('svgDoc:',svgDoc);
let path1 = svgDoc.querySelector("#pin");
console.log('typeof:',typeof(path1))
console.log('#path.d:',path1.getAttribute('d'));
let paths = svgDoc.getElementsByTagName('path');
for (let p of paths) {
let d = p.getAttribute('d'); // does work but can get p.getPathData() to work
console.log('p.d:',d);
}
},false);
</script>
if you want to get the file I have prepared a gist for it :
https://gist.github.com/DrI-T/145db3eed5905f83333d8127cbf2c6b8

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

Enter VR in Aframe via eye-gazing button

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.

Categories

Resources