I'm trying to build an A-Frame scene where a car drives by the user, and I need the sound of the car to start playing as the car starts moving. For example:
<a-collada-model id="car" src="#car-dae" position="-0.7 0 -100" rotation="0 90 0">
<a-animation attribute="position"
dur="7000"
begin="model-loaded"
fill="forwards"
to="-0.7 0 20"
repeat="0"
></a-animation>
</a-collada-model>
Can I put a sound component on the animation? If not, how should I go about having the sound play at the same time as the animation? I tried putting the sound component on the collada model and gave it a on:model-loaded (same event as the animation), but this never played the sound. In fact, the only way I seem to be able to get the sound to play is using autoplay. Any ideas?
If it helps, all of my code is in this git repo under carChase.html
https://github.com/zeekw/aFrameTests
Did you try putting the sound component on the model, or as a child of it?
<a-collada-model src="#car-dae" sound="on: model-loaded; src: #car-sound">
Related
A question about a-frame? Does aframe offer button objects (like a-button)? If yes, why are there no information about them in the documentation?
Are they planned to be added?
And if it isnt, is there a way to create objects in a-frame that behave like button that can be used on a touchscreen?
You can turn pretty much any a-frame object into a button.
make your cursors rayOrigin to your mouse. (You can add the cursor attribute to your camera)
<a-camera cursor="rayOrigin: mouse"></a-camera>
For example lets take an a-box primitive and turn it into a button by adding the standard onclick event to the element
<a-box onclick="doSomething"></a-box>
And initiate the function you want.
This should work for touch too.
If you want an overlay UI, I'd always go with HTML elements. They're easier to manage, as you can position them on the screen easily.
If you want the UI to track an object (like a marker in arjs), you can use my tracked-ui component as follows:
<!-- The HTML UI -->
<div id="ui"></div>
<a-scene arjs>
<a-marker tracked-ui="element: #ui; offset: 0 200">
<a-box></a-box>
</a-marker>
</a-scene>
When I set logarithmicDepthBuffer: true; in the AFrame renderer component, all instances of the text component no longer render at all.
To troubleshoot this, I removed all other entities from the scene, the text still did not render. I also tried using the wrapped <a-text> component, I tried alphaTest: 0.5 , setting depthTest: true and setting sortObjects: false just to see if I could get any kind of result, but found nothing that would produce any results.
<a-scene renderer="logarithmicDepthBuffer: true;">
<a-text value="The quick Brown Fox Jumps over the Lazy Dog"></a-text>
</a-scene>
The text does not appear at all. There are no rendering artifacts, or errors in the console.
You should make an issue for this on AFrame github. I saw this problem come up for someone else before..
As a workaround, I don't know the specifics of aframe, but can you use the .polygonOffset on the material for the text to avoid the zfighting you were trying to counteract with logarithmicDepthBuffer?
logarithmicDepthBuffer is a cool technique, but when enabled, all shaders that interact with depth have to be aware of it, and some of them aren't written with it in mind.
But if you're trying to fix z-fighting, polygonOffset is one of the more classical solutions.
Try using [] around renderer
<a-scene [renderer]="logarithmicDepthBuffer: true;">
<a-text value="The quick Brown Fox Jumps over the Lazy Dog"></a-text>
</a-scene>
I have two overlapping a-sky elements. Second one is positioned at z=-1000 (not visible to camera). In this setup if I set opacity of first a-sky element to 0.5, I should see second a-sky element.
Following code does not work. (Need to make this work.)
skyEl.getObject3D("mesh").material= new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load("image url"),
transparent: true,
opacity: 0.5
});
But this method works.
skyEl.setAttribute('src','image url');
skyEl.getObject3D("mesh").material.transparent = true;
skyEl.getObject3D("mesh").material.opacity= 0.5;
In my project I can't set src attribute because textures are already loaded and I can only create material from preloaded texture. I need to know what's wrong with first method and how to fix it. Is there some other parameter I need to set
Also tried using a-sphere instead of a-sky but same result.
DEMO: https://codesandbox.io/s/qx6zj247l6 (Covers both cases and please ignore all react & tween stuff.)
PS: Creating a crossfade + zoom scene transition effect.
Getting the correct render order for transparency to work as intended is difficult. From the material component documentation page:
Transparency Issues
Transparency and alpha channels are tricky in 3D graphics. If you are having issues where transparent materials in the foreground do not composite correctly over materials in the background, the issues are probably due to underlying design of the OpenGL compositor (which WebGL is an API for).
In an ideal scenario, transparency in A-Frame would “just work”, regardless of where the developer places an entity in 3D space, or in which order they define the elements in markup. We can often run into scenarios where foreground entities occlude background entities. This creates confusion and unwanted visual defects.
To work around this issue, try changing the order of the entities in the HTML.
To resolve your case, simply place #sky1 after #sky2 in the HTML:
render() {
return (
<Scene>
<Entity id="sky2-wrapper" rotation="0 90 0">
<Entity id="sky2" primitive="a-sky" position="0 0 -1000" />
</Entity>
<Entity id="sky1" primitive="a-sky" opacity="1" />
<Entity
camera={{
far: 10000,
fov: 80,
near: 0.05,
active: true
}}
id="cam"
rotation="0 90 0"
mouse-cursor
look-controls="reverseMouseDrag:true"
/>
</Scene>
);
}
I have a 360° rotation animation in aframe (ar.js) and I would like to pause and continue it, whereas all that I can do it's pause but restart from the begining.
<a-entity>
<a-entity
gltf-model="#tree-gltf">
</a-entity>
<a-animation
begin="rotation-begin"
end="rotation-end"
attribute="rotation"
to="0 360 0"
direction="alternate"
dur="10000"
repeat="indefinite">
</a-animation>
</a-entity>
Animation documentation give access to "begin" and "end" events, but "begin" restart from the begining and not from the current value when paused.
Entity documentation give access to pause() and play(), which are the same. Play() doesn't work at all if "begin" attribute exist, so you have to choose between events or functions.
But play() also restart animation from the begining and not from where the animation was paused.
I also tried an ugly trick by setting attribute "dur" to one hour to slow down animation so it looks like paused, but setting back "dur" to 10 sec doesn't restart it.
Any idea which can help ?
Using Kevin Ngo's animation-component helps as it properly supports pause/resume.
Besides including the component, your code will look like this:
<a-entity
animation="property:rotation; startEvents:rotation-begin; pauseEvents: rotation-pause; resumeEvents: rotation-resume; to:0 360 0; dir:alternate; dur:10000; repeat:indefinite"
gltf-model="#tree-gltf">
</a-entity>
This will give you three events: rotation-begin, rotation-pause and rotation-resume that you can trigger.
See a demo here
I have code which, when you look at an element, it moves. I achieve this using a-cursor with fuse="true". I want to make the fuseTimeout 100 milliseconds and I tried adding the following to the <a-cursor> element:
cursor="fuseTimeout: 100"
timeout="100"
fuseTimeout="100"
Here is the full code: https://jsfiddle.net/be1pgjyv/7/
Try fuse-timeout="100". The docs are off, will fix.