Hey George,
Thank you in advance for your help here!
Here is a link to a screen recording. In the recording, I alternate between clicking the two buttons. When I click the “Start Video Button”, the experience works as intended. However, when I click the “Video 1 Button”, the audio of the corresponding video starts playing, but the video itself is not visible. Additionally, the “Start Video” pauses and remains visible. My ultimate goal here is to have 6 buttons allowing the user to cycle seamlessly through 6 different videos.
Below is the code:
app.js
// Import components and primitives
import { myNamedImageTargetComponent, namedImageTargetPrimitive } from './my-named-target';
// Register component
AFRAME.registerComponent('my-xrextras-named-imagetarget', myNamedImageTargetComponent);
AFRAME.registerPrimitive('my-xrextras-named-image-target', namedImageTargetPrimitive);
// Component to handle video playback on button click
AFRAME.registerComponent('play-video', {
schema: { videoId: { type: 'string' } }, // ID of the video to play
init: function () {
this.el.addEventListener('click', () => {
const videoId = this.data.videoId; // Get the video ID from schema
const videoPlayer = document.querySelector('#video-player'); // Get the video player element
const videoElement = document.querySelector(videoId); // Get the actual video element by ID
if (!videoElement) {
console.error(`Video with ID ${videoId} not found.`);
return;
}
// Pause and reset the currently playing video if any
const currentVideoId = videoPlayer.getAttribute('video');
if (currentVideoId) {
const currentVideoElement = document.querySelector(currentVideoId);
if (currentVideoElement) {
currentVideoElement.pause();
currentVideoElement.currentTime = 0; // Reset to the beginning
}
}
// Update the video source in xrextras-target-video-sound component
videoPlayer.setAttribute('src', videoElement.getAttribute('src'));
// Trigger the new video to play directly
videoElement.play();
// Manually trigger xrextras-target-video-sound component to reload the video source
videoPlayer.components['xrextras-target-video-sound'].play();
});
},
});
console.log('App.js loaded and initialized.');
body.html
<a-scene
device-orientation
xrextras-gesture-detector
landing-page
xrextras-loading="
loadBackgroundColor: #63ACA8;
cameraBackgroundColor: #63ACA8;
loadImage: #logo-icon;
loadAnimation: pulse"
xrextras-runtime-error
renderer="colorManagement:true"
xrweb="disableWorldTracking: true">
<!-- Assets -->
<a-assets>
<img id="start-thumb" src="assets/start-thumbnail.jpg">
<img id="logo-icon" src="./assets/logo-icon.png">
<!-- Video Assets for the Gallery -->
<video id="start-video" crossorigin="anonymous" loop="false" src="assets/start-video.mp4"></video>
<video id="video-1" crossorigin="anonymous" loop="false" src="assets/video-1.mp4"></video>
</a-assets>
<!-- Camera and Lights -->
<a-camera position="0 0 0" raycaster="objects: .cantap" cursor="fuse: false; rayOrigin: mouse;"></a-camera>
<a-light type="directional" intensity="0.5" position="1 1 1"></a-light>
<a-light type="ambient" intensity="0.7"></a-light>
<!-- Image Target with Video -->
<my-xrextras-named-image-target name="start-target">
<xrextras-target-video-sound
video="#start-video"
thumb="#start-thumb"
height="1"
width="1.1"
id="video-player">
</xrextras-target-video-sound>
<!-- Buttons as part of the tracked entity -->
<a-entity position="0 -1 0" id="button-container" visible="true">
<a-plane
position="-0.5 0 0"
width="0.5"
height="0.2"
color="#63ACA8"
class="cantap"
text="value: Start Video; color: #F3EBCE; align: center; width: 4;"
play-video="videoId: #start-video">
</a-plane>
<a-plane
position="0.5 0 0"
width="0.5"
height="0.2"
color="#63ACA8"
class="cantap"
text="value: Video 1; color: #F3EBCE; align: center; width: 4;"
play-video="videoId: #video-1">
</a-plane>
</a-entity>
</my-xrextras-named-image-target>
</my-xrextras-named-image-target>
</a-scene>
my-named-target.js
const myNamedImageTargetComponent = {
schema: {
name: { type: 'string' },
},
init() {
const { object3D } = this.el;
const { name } = this.data;
const geometry = {};
const onready = () => {
this.el.sceneEl.removeEventListener('realityready', onready);
object3D.visible = false;
};
this.el.sceneEl.addEventListener('realityready', onready);
const checkGeometry = (newGeometry) => {
let needsUpdate = false;
const fields = [
'type',
'height',
'radiusTop',
'radiusBottom',
'arcLengthRadians',
'arcStartRadians',
'scaledWidth',
'scaledHeight',
];
fields.forEach((f) => {
if (geometry[f] !== newGeometry[f]) {
geometry[f] = newGeometry[f];
needsUpdate = true;
}
});
if (needsUpdate) {
this.el.emit('xrextrasimagegeometry', geometry, false);
}
};
const imageScanning = ({ detail }) => {
detail.imageTargets.forEach((t) => {
if (name !== t.name) return;
checkGeometry({ type: t.type, ...t.geometry });
});
};
const updateImage = ({ detail }) => {
if (name !== detail.name) return;
object3D.position.copy(detail.position);
object3D.quaternion.copy(detail.rotation);
object3D.scale.set(detail.scale, detail.scale, detail.scale);
object3D.visible = true;
};
const showImage = ({ detail }) => {
if (name !== detail.name) return;
checkGeometry(detail);
updateImage({ detail });
this.el.emit('xrextrasfound', {}, false);
};
const hideImage = ({ detail }) => {
if (name !== detail.name) return;
this.el.emit('xrextraslost', {}, false);
object3D.visible = false;
};
this.el.sceneEl.addEventListener('xrimagescanning', imageScanning);
this.el.sceneEl.addEventListener('xrimagefound', showImage);
this.el.sceneEl.addEventListener('xrimageupdated', updateImage);
this.el.sceneEl.addEventListener('xrimagelost', hideImage);
},
};
const namedImageTargetPrimitive = {
defaultComponents: {
'my-xrextras-named-imagetarget': {},
},
mappings: {
name: 'my-xrextras-named-imagetarget.name',
},
};
export { myNamedImageTargetComponent, namedImageTargetPrimitive };