UNPKG

aframe-babia-components

Version:

A data visualization set of components for A-Frame.

468 lines (405 loc) 18 kB
<html> <head> <meta charset="utf-8" /> <title>Simple Example — Networked-Aframe in BabiaXr</title> <meta name="description" content="Simple Example — Networked-Aframe in BabiaXr" /> <script src="https://aframe.io/releases/1.5.0/aframe.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.slim.js"></script> <script src="./easyrtc.js"></script> <script src="https://unpkg.com/networked-aframe@^0.8.0/dist/networked-aframe.js"></script> <script src="https://unpkg.com/aframe-environment-component@1.3.3/dist/aframe-environment-component.min.js"></script> <script src="../../dist/aframe-babia-components.js"></script> <script src="https://cdn.jsdelivr.net/gh/donmccurdy/aframe-extras@v7.2.0/dist/aframe-extras.min.js"></script> </head> <body> <a-scene id="AframeScene" networked-scene=" room: room_demo; adapter: easyrtc; debug: true; audio: false; serverURL: empty_server; "> <!-- serverURL:http://10.1.130.131:8080/; --> <a-assets> <!-- Dummy asset to make the scene sync (WIP)--> <img src="https://wallpapercave.com/wp/wp2345390.jpg?dummy=8484744"> <!-- Templates --> <!-- Box --> <template id="box-template"> <a-box class="box"></a-box> </template> <!-- Box Button --> <template id="box-button-template"> <a-plane class="box_button"></a-plane> </template> <!-- Box Label--> <template id="box-label-template"> <a-text class="box_label"></a-text> </template> <!-- Cyls --> <template id="cyls-template"> <a-entity class="cyls"></a-entity> </template> <!-- Interface --> <template id="interface-template"> <a-entity class="interface"></a-entity> </template> <!-- Avatar --> <template id="rig-template"> <a-entity class="rig"></a-entity> </template> <template id="camera-template"> <a-entity class="camera"></a-entity> </template> <template id="avatar-template"> <a-sphere class="avatar" networked-audio-source></a-sphere> </template> <template id="username-tag-template"> <a-text class="username-tag"></a-text> </template> </a-assets> <a-entity environment="preset: yavapai; skyType: color; skyColor: #358DF8 "></a-entity> <a-entity light="color: #95E0FF; intensity: 1; type: ambient;" visible="true"></a-entity> <a-entity id="rig" position="0 2.5 3" networked="template:#rig-template; attachTemplateToLocal:false"> <a-entity id="camera" camera look-controls wasd-controls="fly: false" networked="template:#camera-template;attachTemplateToLocal:false;"> <a-sphere id="avatar" color="#D3FFE4" scale="0.25 0.25 0.25" networked="template:#avatar-template;attachTemplateToLocal:false;"> <a-text id="username-tag" networked="template:#username-tag-template; attachTemplateToLocal:false" position="-0.5 1.5 0" width="5" color="black" value="username"></a-text> </a-sphere> </a-entity> <!-- Hand Controls --> <a-entity id="leftHand" laser-controls="hand: left"></a-entity> <a-entity id="rightHand" laser-controls="hand: right"></a-entity> <a-entity id="cursor" cursor="rayOrigin:mouse"></a-entity> </a-entity> <a-box id="box" color="#22B8F6" networked="template:#box-template; networkId:box; persistent: true; owner: scene" position="-7 1 -5" rotation="0 -45 0"></a-box> <a-plane id="box_button" networked="template:#box-button-template; networkId:box_button; persistent: true; owner: scene" position="-7 3 -5" rotation="0 0 0" height="1" width="2" color="#F8F6F2"> <a-text id="box_label" networked="template:#box-label-template; networkId:box_label; persistent: true; owner: scene" value="Start" color="#0582B5" width="10" position="-0.5 0 0" rotation="0 0 0"></a-text> </a-plane> <a-entity id="cyls" babia-queryjson="url: ./data.json;" babia-cyls='x_axis:city; height: population; radius: size; legend: true; palette: flat; radiusMax: 2; heightMax: 45; animation: true;' position="0 0.5 -10" scale="0.25 0.25 0.25" networked="template:#cyls-template; networkId:cyls; persistent: true; owner: scene"></a-entity> <a-entity id="interface" babia-ui="target: cyls" networked="template:#interface-template; networkId:interface; persistent: true; owner: scene" position="7 1 -5" rotation="0 -45 0" scale="0.5 0.5 0.5"></a-entity> <a-plane id="cyls_palette_button" position="7 6 -5" rotation="0 -45 0" height="1" width="4" color="#F8F6F2"> <a-text id="cyls_palette_label" value="Change palette" color="#0582B5" width="10" position="-1.5 0 0" rotation="0 0 0"></a-text> </a-plane> <a-plane id="cyls_scale_button" position="7 4 -5" rotation="0 -45 0" height="1" width="2" color="#F8F6F2"> <a-text id="cyls_scale_label" value="Resize" color="#0582B5" width="10" position="-0.75 0 0" rotation="0 0 0"></a-text> </a-plane> <a-plane id="audio_button" position="-2.5 1 -5" rotation="0 45 0" height="1" width="2" color="#E44B00"> <a-text id="audio_label" value="Stop Audio" color="#0582B5" width="6" position="-0.75 0 0" rotation="0 0 0"> </a-text> </a-plane> </a-scene> <script> /* GET DOM ELEMENTS */ let scene = document.getElementById('AframeScene') let avatar = document.getElementById('avatar') let usernameTag = document.getElementById('username-tag') let hand_right = document.getElementById('rightHand') let box = document.getElementById('box') let boxButton = document.getElementById("box_button") let boxLabel = document.getElementById("box_label") let cyls = document.getElementById('cyls') let cylsScaleButton = document.getElementById('cyls_scale_button') let cylsPaletteButton = document.getElementById('cyls_palette_button') let interface = document.getElementById('interface') let audioButton = document.getElementById('audio_button') let audioLabel = document.getElementById('audio_label') /* SET SERVER URL FROM QUERY STRING */ let serverURL = getValueFromQueryString('serverURL'); console.log("Empty server URL, networked-scene: ", scene.getAttribute('networked-scene')); if (serverURL) { scene.setAttribute('networked-scene', 'serverURL', serverURL); scene.setAttribute('networked-scene', 'audio', 'true') } /* SET USERNAME AND AVATAR COLOR FROM QUERY STRING*/ let username = getValueFromQueryString('username'); let color = "#" + getValueFromQueryString('color'); if (username) { usernameTag.setAttribute('value', username) } if (color != "#") { avatar.setAttribute('color', color) } /* STORE CLIENTS AND USERNAMES */ let users = []; // UI Event Listeners document.addEventListener('controllerconnected', (event) => { document.querySelector('#rig').setAttribute('position', { x: 0, y: 1.6, z: 0 }) }); boxButton.addEventListener('click', function (event) { NAF.utils.takeOwnership(boxButton) NAF.utils.takeOwnership(boxLabel) NAF.utils.takeOwnership(box) if (boxLabel.getAttribute('value') === 'Stop') { stopBox(); } else { moveBox(); } }); cylsScaleButton.addEventListener('click', function (event) { NAF.utils.takeOwnership(cyls) changeCylsScale(); }); cylsPaletteButton.addEventListener('click', function (event) { NAF.utils.takeOwnership(cyls) changeCylsColor(); }); interface.addEventListener('click', function (event) { NAF.utils.takeOwnership(cyls) NAF.utils.takeOwnership(interface) }); function addSayHelloEventListener(clientId) { let sayHelloButton = document.getElementById('sayHello') sayHelloButton.addEventListener('click', function (event) { let username = ""; users.forEach(user => { if (user.clientId === clientId) { username = user.username } }) sendMessage(clientId, 'hello_message', `Hello, ${username}`) scene.removeChild(sayHelloButton) }); } audioButton.addEventListener('click', function (event) { if (audioLabel.getAttribute('value') === 'Stop Audio') { stopAudio(); } else { turnOnAudio(); } }); // NAF Subscriptions NAF.connection.subscribeToDataChannel('hello_message', function (senderId, dataType, data, targetId) { console.log('senderId: ', senderId) console.log('dataType: ', dataType) console.log('data: ', data) console.log('targetId: ', targetId) showMessage(data) }) // NAF Event Listeners document.body.addEventListener('connected', function (event) { console.log('connected event. clientId =', event.detail.clientId); console.log("Filled serverURL, networked-scene: ", scene.getAttribute('networked-scene')) }); document.body.addEventListener('clientConnected', function (event) { let clientId = event.detail.clientId; console.log('clientConnected event. clientId =', clientId); let sayHelloButton = document.getElementById("sayHello") if (sayHelloButton) { scene.removeChild(sayHelloButton) } sayHelloButton = document.createElement('a-plane'); sayHelloButton.setAttribute('id', 'sayHello') sayHelloButton.setAttribute('position', { x: -3, y: 2, z: -2 }); sayHelloButton.setAttribute('rotation', { x: 0, y: 0, z: 0 }); sayHelloButton.setAttribute('height', '1'); sayHelloButton.setAttribute('width', 3); sayHelloButton.setAttribute('color', 'white'); let username = clientId; users.forEach(user => { if (user.clientId === clientId) { username = user.username } }) sayHelloButton.setAttribute('text', { 'value': `${username} is now connected. Click here to say HELLO.`, 'align': 'center', 'width': 3, 'color': 'black' }); scene.appendChild(sayHelloButton) addSayHelloEventListener(clientId) }); document.body.addEventListener('clientDisconnected', function (event) { let clientId = event.detail.clientId; console.log('clientDisconnected event. clientId =', clientId); let sayHelloButton = document.getElementById("sayHello") if (sayHelloButton) { scene.removeChild(sayHelloButton) } users = users.filter(user => user.clientId != clientId) console.log(users) }); document.body.addEventListener('entityCreated', function (event) { console.log(event.detail.el) if (event.detail.el.getAttribute('class') === "username-tag") { let user = { clientId: event.detail.el.components.networked.data.owner, username: event.detail.el.getAttribute('value') }; users.push(user); console.log(users); if (document.getElementById('sayHello')) { document.getElementById('sayHello').setAttribute('text', { 'value': `${event.detail.el.getAttribute('value')} is now connected. Click here to say HELLO.`, }); } }; }); // NAF senders function sendMessage(client, dataType, data) { NAF.connection.sendDataGuaranteed(client, dataType, data) console.log(`message sent to ${client}`) }; // Other methods function getValueFromQueryString(string) { string = string.replace(/[\[\]]/g, '\\$&'); var regex = new RegExp('[?&]' + string + '(=([^&#]*)|&|#|$)'), results = regex.exec(window.location.href); if (!results) return null; if (!results[2]) return ''; return decodeURIComponent(results[2].replace(/\+/g, ' ')); } function moveBox() { box.setAttribute('animation', { 'property': 'position', 'from': '-7 1 -5', 'to': '-2 3 -5', 'dur': '2000', 'easing': 'linear', 'loop': 'true' }) boxButton.setAttribute('color', '#E44B00') boxLabel.setAttribute('value', 'Stop') } function stopBox() { let x = box.getAttribute('position').x; let y = box.getAttribute('position').y; let z = box.getAttribute('position').z; let pos = `${x} ${y} ${z}` box.setAttribute('animation', { 'property': 'position', 'from': pos, 'to': pos, 'loop': 'false' }) boxButton.setAttribute('color', '#F8F6F2') boxLabel.setAttribute('value', 'Start') } function turnOnAudio() { NAF.connection.adapter.enableMicrophone(true) audioButton.setAttribute('color', '#E44B00') audioLabel.setAttribute('value', 'Stop Audio') } function stopAudio() { NAF.connection.adapter.enableMicrophone(false) audioButton.setAttribute('color', '#F8F6F2') audioLabel.setAttribute('value', 'Turn on Audio') } function changeCylsScale() { if (cyls.getAttribute('scale').x === 0.25) { cyls.setAttribute('scale', '0.15 0.15 0.15') } else { cyls.setAttribute('scale', '0.25 0.25 0.25') } } function changeCylsColor() { if (cyls.getAttribute('babia-cyls').palette === 'flat') { cyls.setAttribute('babia-cyls', 'palette', 'bussiness') } else { cyls.setAttribute('babia-cyls', 'palette', 'flat') } } async function showMessage(data) { let showMessage = document.createElement('a-plane'); showMessage.setAttribute('position', { x: 3, y: 2, z: -2 }); showMessage.setAttribute('rotation', { x: 0, y: 0, z: 0 }); showMessage.setAttribute('height', '1'); showMessage.setAttribute('width', 5); showMessage.setAttribute('color', 'white'); showMessage.setAttribute('text', { 'value': data, 'align': 'center', 'width': 6, 'color': 'black' }); scene.appendChild(showMessage) await delay(); scene.removeChild(showMessage) } function delay() { return new Promise(resolve => setTimeout(resolve, 3000)); } </script> <script> // Schemas with components and attributes for syncronization NAF.schemas.add({ template: '#box-template', components: [ 'position', 'rotation', 'color', 'animation' ] }); NAF.schemas.add({ template: '#box-button-template', components: [ 'position', 'rotation', 'height', 'width', 'color' ] }); NAF.schemas.add({ template: '#box-label-template', components: [ 'value', 'color', 'width', 'position', 'rotation' ] }); NAF.schemas.add({ template: '#cyls-template', components: [ 'babia-queryjson', 'position', 'rotation', 'scale', 'babia-cyls' ] }); NAF.schemas.add({ template: '#interface-template', components: [ 'babia-ui', ] }); NAF.schemas.add({ template: '#rig-template', components: [ 'position', 'rotation' ] }); NAF.schemas.add({ template: '#camera-template', components: [ 'position', 'rotation' ] }); NAF.schemas.add({ template: '#avatar-template', components: [ 'position', 'rotation', 'color', 'scale' ] }); NAF.schemas.add({ template: '#username-tag-template', components: [ 'value', 'color', 'width', 'position', 'rotation' ] }); </script> </body> </html>