UNPKG

aframe-hotspots

Version:

A-Frame component for interactive VR hotspots with audio and scene transitions

179 lines (162 loc) 6.43 kB
export const FaceCameraComponent = { // ... face-camera component code ... tick: function () { const camera = document.querySelector("[camera]").object3D; this.el.object3D.lookAt(camera.position); }, }; export const HotspotsComponent = { // ... hotspots component code ... init: function () { this.el.addEventListener("reloadspots", function (evt) { var currspotgroup = document.getElementById(evt.detail.currspots); currspotgroup.setAttribute("visible", "false"); var newspotgroup = document.getElementById(evt.detail.newspots); newspotgroup.setAttribute("visible", "true"); console.log( "Hotspots reloaded from", evt.detail.currspots, "to", evt.detail.newspots ); console.log( "New hotspot group visibility:", evt.detail.newspots, newspotgroup.getAttribute("visible") ); }); }, }; export const SpotComponent = { // ... spot component code ... schema: { linkto: { type: "string", default: "" }, spotgroup: { type: "string", default: "" }, label: { type: "string", default: "" }, audio: { type: "string", default: "" }, labelBackground: { type: "color", default: "#333333" }, // New property labelPadding: { type: "number", default: 0.2 }, lineHeight: { type: "number", default: 0.4 }, }, init: function () { this.el.setAttribute("src", "#hotspot"); this.el.setAttribute("look-at", "#cam"); var data = this.data; var el = this.el; console.log("Initializing hotspot with label:", data.label); if (data.label !== "") { // Create container for label + background const labelContainer = document.createElement("a-entity"); labelContainer.setAttribute("position", "0 -0.6 0"); // Add background panel const background = document.createElement("a-plane"); background.setAttribute("color", data.labelBackground); background.setAttribute("opacity", 0.8); background.setAttribute( "width", data.label.length * 0.15 + data.labelPadding ); // Dynamic width background.setAttribute("height", 0.3); background.setAttribute("position", "0 0 -0.01"); // Behind text // Add text label const textEl = document.createElement("a-text"); textEl.setAttribute("value", data.label); textEl.setAttribute("align", "center"); textEl.setAttribute("color", "#FFFFFF"); // White text by default textEl.setAttribute("position", "0 0 0"); // In front of background // Assemble components labelContainer.appendChild(background); labelContainer.appendChild(textEl); el.appendChild(labelContainer); } if (data.audio !== "") { var audioEl = document.createElement("a-sound"); audioEl.setAttribute("src", data.audio); audioEl.setAttribute("autoplay", "false"); audioEl.setAttribute("loop", "true"); audioEl.setAttribute("volume", "1"); el.appendChild(audioEl); console.log("Audio element added with source:", data.audio); audioEl.addEventListener("sound-loaded", function () { console.log("Sound loaded -force stop playing:", data.label); audioEl.components.sound.stopSound(); button.setAttribute("text", "value: Play; align: center; color: #FFF"); audioReady = true; }); var button = document.createElement("a-plane"); button.setAttribute("color", "#ff0000"); button.setAttribute("width", "0.5"); button.setAttribute("height", "0.3"); button.setAttribute("position", "0 -1 0"); button.setAttribute("text", "value: Play; align: center; color: #FFF"); el.appendChild(button); console.log("Play/Pause button added for hotspot:", data.label); var audioReady = false; audioEl.addEventListener("sound-loaded", function () { console.log("Sound loaded for hotspot:", data.label); audioReady = true; }); var toggleAudio = function () { if (audioEl.components.sound.isPlaying) { audioEl.components.sound.stopSound(); button.setAttribute( "text", "value: Play; align: center; color: #FFF" ); console.log("Audio paused for hotspot:", data.label); } else { audioEl.components.sound.playSound(); button.setAttribute( "text", "value: Pause; align: center; color: #FFF" ); console.log("Audio playing for hotspot:", data.label); } }; button.addEventListener("click", function (evt) { evt.stopPropagation(); console.log("Button clicked for hotspot:", data.label); if (!audioReady) { console.log("Waiting for audio to load..."); var onLoaded = function () { audioEl.removeEventListener("sound-loaded", onLoaded); toggleAudio(); }; audioEl.addEventListener("sound-loaded", onLoaded); return; } toggleAudio(); }); } el.addEventListener("click", function (evt) { var audioChild = el.querySelector("a-sound"); if ( audioChild && audioChild.components && audioChild.components.sound && audioChild.components.sound.isPlaying ) { audioChild.components.sound.stopSound(); var btn = el.querySelector("a-plane"); if (btn) { btn.setAttribute("text", "value: Play; align: center; color: #FFF"); } console.log("Audio reset on hotspot:", data.label); } var sky = document.getElementById("skybox"); sky.setAttribute("src", data.linkto); console.log("Skybox changed to:", data.linkto); var spotcomp = document.getElementById("spots"); var currspots = el.parentElement.getAttribute("id"); spotcomp.emit("reloadspots", { newspots: data.spotgroup, currspots: currspots, }); }); }, }; if (typeof window !== "undefined" && window.AFRAME) { window.AFRAME.registerComponent("face-camera", FaceCameraComponent); window.AFRAME.registerComponent("hotspots", HotspotsComponent); window.AFRAME.registerComponent("spot", SpotComponent); }