A tutorial demonstrates how to create a 3D football commentary scoreboard with running commentary using React VR to give sports lovers a unique way to experience the games.
Over the years, with the advancement of technology, different breakthroughs have been made in our interaction with computers. The experience that was limited to viewing 2D objects on a screen has evolved to the stage that we have augmented reality and virtual reality, in which we can have an immersive experience in our applications with the help of headsets connected to our machines. We will explore building an application using React VR.
This opens up endless possibilities. It allows users to experience computers and the world like they have never done before. From Virtual Tours of Tourist Centres to magnificent virtual reality games with Oculus and Vives.
In this article, we are going to be looking at how to build a scoreboard with running commentary to give sports lovers a different way to experience games.
To get started, you would need the following:
When you have the requirements listed above, let’s continue with the article.
First, we need to install the React VR CLI tool. We will need this to initialize new ReactVR projects. To install the tool, run this command on your terminal:
npm install -g react-vr-cli
Once this is done, we create our simple ReactVR project. To create a ReactVR application run the following command:
react-vr init scoreboard-vr
To start the development server, run this command on your terminal:
1cd scoreboard-vr 2npm start
Now that we have set up the base application, you can view the app here: http://localhost:8081/vr/. This will launch something similar to this:
When you create the project using the init
function, some basic files are created by default. Since we are making a scoreboard application, we want to set the scenery. In the index.vr.js
replace the contents of the render function with this:
1[...] 2render() { 3return ( 4<View style={{ 5flex: 1, flexDirection: 'column', width: 2, alignItems: 'stretch' 6}}> 7<Pano source={asset('lille-pitch.jpg')}/> 8</View> 9[...]
We set the source to the image in our static_assets
directory . When you visit the app, we have:
If you wish to change the background, you can do so by placing the image you want in the static_assets
folder and then supplying the relative path to the image in the Pano
component of your index.vr.js
:
1[...] 2<Pano source={asset('relative/file/path')} /> 3[...]
For this application, we have one basic component, the commentary component. This component, as the name suggests, is responsible for displaying commentary as the game goes on. Ideally, we can get comments using an API or a service, but in this case, we are going to use some stock JSON data obtained from Goal.com.
We create a component that displays the teams, we make a components directory and then create Teams.js
in it:
1mkdir components 2touch Teams.js
Our Team component looks like this:
1import React, {Component} from 'react'; 2import { 3View, 4Text, 5} from 'react-vr'; 6 7export default ({teamA, teamB}) => { 8return ( 9<View> 10<Text 11style={{ 12backgroundColor: '#777879', 13fontSize: 0.8, 14layoutOrigin: [0.5, 1], 15paddingLeft: 0.1, 16paddingRight: 0.1, 17textAlign: 'center', 18textAlignVertical: 'center', 19transform: [{ translate: [0, 0, -4],}], 20width: '50' 21}} 22>{teamA} vs {teamB} !</Text> 23</View> 24); 25}
In our index.vr.js
we use the component:
1[...] 2import Teams from './components/Teams'; 3[...] 4export class scoreboard_vr extends React.Component { 5render(){ 6[...] 7<Teams teamA={"Losc Lille"} teamB={"Moncao"} /> 8[...] 9); 10}
Now when we go back to our app, we have this:
Our comment component is also a text component, but here, we display the time and what occurred at that time. We make the file by running the following in our components
directory:
touch Commentary.js
Our Commentary.js
looks like this:
1import React, { Component } from 'react'; 2import { 3View, 4Text, 5} from 'react-vr'; 6 7export default ({ time, comment }) => { 8return ( 9<View> 10<Text 11style={{ 12backgroundColor: '#ffffff', 13color : '#333333', 14fontSize: 0.8, 15layoutOrigin: [0.5, 0], 16paddingLeft: 0.2, 17paddingRight: 0.2, 18textAlign: 'center', 19textAlignVertical: 'center', 20transform: [{ 21translate: [0, 0, -7] 22}], 23}} 24>{time} - {comment}</Text> 25</View> 26); 27}
In our comment model, we have our comments stored in an array as shown in the file below. We create a model directory in the root of our application and then create the comment.js
file that is shown below:
1mkdir models 2touch comments.js
Add this code to comment.js
file:
1export class Comments { 2comments = 3[ 4{ 5"time": "1", 6"comment": "Attempt blocked. Falcao (Monaco) right footed shot from the left side of the box is blocked. Assisted by Stevan Jovetic." 7}, 8{ 9"time": "3", 10"comment": "Foul by Falcao (Monaco)." 11}, 12{ 13"time": "3", 14"comment": "Ibrahim Amadou (Lille) wins a free kick in the attacking half." 15}, { 16"time": "5", 17"comment": "João Moutinho (Monaco) wins a free kick in the defensive half." 18}, { 19"time": "5", 20"comment": "Foul by Thiago Maia (Lille)" 21}, { 22"time": "5", 23"comment": "Offside, Lille. Yves Bissouma tries a through ball, but Anwar El Ghazi is caught offside." 24}, { 25"time": "24", 26"comment": "Goal! Lille 0, Monaco 1. Stevan Jovetic (Monaco) right footed shot from outside the box to the bottom right corner." 27}, { 28"time": "90", 29"comment": "Match ends, Lille 0, Monaco 4." 30} 31]; 32}
In our index.vr.js
we fetch the comments and then display them via a loop in the view. Instead of displaying all our comments at once, what we can do is to display the comments in particular chunks. In this case we are going to display them four at a time:
1[...] 2import Commentary from './components/Commentary'; 3import { Comments } from './models/comments'; 4[...] 5export class scoreboard_vr extends React.Component { 6constructor(props) { 7super(props); 8this.state = { 9comment_index: 0, 10}; 11} 12 13componentDidMount(){ 14let comments = new Comments().comments.length; 15setInterval(() => { 16this.setState({ 17comment_index : (this.state.comment_index > comments.length) ? comments.length-4 : this.state.comment_index+3 18}) 19}, 5000); 20}; 21 22render() { 23let comment_list = new Comments().comments; 24let comment_length = comment_list.length; 25let comments = (this.state.comment_index < comment_length ) ? 26comment_list.slice(this.state.comment_index, this.state.comment_index+3) : 27comment_list.slice(comment_length-1, comment_length); 28return ( 29[...] 30{comments.map(function (comment) { 31return <Commentary time={comment.time} comment={comment.comment} /> 32})} 33[...] 34); 35} 36};
We first set the comment index to zero and then the final view is updated periodically using the ComponentDidMount
method. So if you were fetching your data from an external API, you could keep fetching data and updating by placing the logic to fetch the data in the method.
To adjust how close the comment view is to the user, we revisit the commentary component. Instead of making the comments appear so close to the user, we adjust the distance from the user in the styling by changing the Commentary.js
component style to :
1[...] 2export default ({ time, comment }) => { 3return ( 4[...] 5<Text 6style={{ 7backgroundColor: '#ffffff', 8color : '#333333', 9fontSize: 0.8, 10layoutOrigin: [0.5, 0], 11paddingLeft: 0.2, 12paddingRight: 0.2, 13textAlign: 'left', 14textAlignVertical: 'center', 15transform: [{ 16translate: [1, 1, -15] 17}], 18width : 15 19}} 20> 21[...] 22</Text> 23[...] 24); 25}
In the above, we set :
transfrom: [{ translate: [1,1, -15]}]
This moves the commentary text to about 15m
away from the user and this can be adjusted to fit your preference.
In this article, we have successfully seen one of the many implementations of React VR and how to use it. Here’s a link to the GitHub repository if interested.