Split Screen App With React

Split Screen App With ReactSupport two people playing face-to-face on an iPad with a split screenRené LemsBlockedUnblockFollowFollowingJun 5Photo by elizabeth lies on UnsplashWe were tasked to make an iPad app that would support two people playing a game at the same time, sitting across from each other, split screen, but also be able to switch to a single player view and vice versa.

The project needed to be completed as soon as possible, so we went with the technologies that we know best.

We decided to create the app in React and wrap it with Cordova.

React is generally our JS framework of choice, and Cordova would give us the native capability of changing the orientation of the app on request.

Split screen on iPadSplit Screen ComponentOur app lets two players login through a landscape oriented page, so the two users will be on the same side of the iPad through the initial process of the app.

Once they arrive at the first game stage of the app, they’re instructed to put the iPad on a specially designed table which has a dividing panel above it that can be pulled down once the iPad is in place.

From this moment on, player1 will see one half of the screen, and player2 will see the other half.

The aim is to help each other with answering some questions, without knowing what’s on the other player’s screen.

Login screen where both players can login on landscape orientationOur solution to splitting the screen was to create a Higher-Order Component that would encapsulate the split screen logic.

We came up with the idea of creating a SplitScreen component which is provided with two nodes — one for the upper side of the screen and one for the lower side.

Through CSS we give each side a height of 50%, and rotate the upper half (the topPane) 180 degrees.

Now, when we render a SplitScreen component and provide it with two nodes:<SplitScreen topPane={( <div> <h1>Player1</h1> </div> )} bottomPane{( <div> <h1>Player2</h1> </div> )}/>This would give us the following:SplitScreen component rendered in portrait orientationOrientationWe want this split screen to always be in portrait orientation, and some other screens (like the login screen) to always be in landscape orientation.

For this we use the Cordova’s Screen orientation plugin.

We keep a record of which pages in our app are meant to be split screen, and which ones aren’t.

On the highest level of our app we check with the router if our currently rendered page is meant to be split screen.

If it is, and the current orientation is not portrait yet, we trigger a switch to portrait mode.

This goes the same for landscape.

App component switching orientationDo note that we lock the orientation to the landscape-primary and portrait-primary modes.

This way we ensure player1 and player2 are always on the same side of the iPad when switching orientation.

PerspectiveAwarded score in wrong perspective for player1That was all fairly easy.

We can just render the SplitScreen component and provide it with two nodes — one for each player and one of them will be rotated 180 degrees.

The next problem at hand is that animations, like awarded score tags, are not rotated for player1 in split screen mode.

This would cause this player to see them upside down from his perspective.

These animated elements are rendered using React’s Portals to make them render outside the DOM hierarchy and placed above all other elements.

These animated elements have no idea whether they’re being rendered within the rotated half of the split screen or not.

We need to make sure that the AwardedScore component knows whether it’s rendered in the topPane of the SplitScreen component and rotate the element accordingly.

We used React’s Context to achieve this.

First we create a context.

export const SplitPaneContext = React.

createContext('default');The default value is our identifier for landscape mode.

We use this context to provide our top and bottom pane’s child components with the knowledge of where they’re being rendered.

SplitScreen component implementing the SplitPane contextWhen a component is rendered in the topPane, the context’s value is top.

If it’s rendered in the bottomPane, the value is bottom.

And when it’s rendered outside of these two nodes, the value will be default.

Now we can use this context value in our AwardedScore componentAwardedScore component implementing SplitPane contextWhen the AwardedScore component is rendered in the topPane, the context’s value is top and the .

upsideDown class is applied.

When it’s rendered in the bottomPane, the value is bottom and no class is applied.

In awardedScore.

scss we only want to rotate the content of theAwardedScore component rendered in the top pane.

If we would rotate the whole .

upsideDown element, the x and y axis of our animation would be reversed too, causing the animation itself to be reversed, not just the content.

This happens because our AwardedScorePortal renders outside of the root of the DOM, thus having the window as a reference for its x and y coordinates.

Note that you might want the whole element rotated in certain situations, depending on how you animate your element and how you calculate the x and y coordinates for your animations.

Modals in PerspectiveModals in split screen modeFor the awarded scores we use a portal to render it outside of the DOM hierarchy of the SplitScreen component.

This way the split screen functionality will not mess with the x and y coordinates of our coordinate based animations.

We also have modals in our application, and we want those rendered on top of everything within the SplitScreen component.

So here we use a portal to render the modal within the SplitScreen DOM hierarchy.

SplitScreen with modal rootNotice how we created empty div elements within the topPane and bottomPane with a unique id.

These contain our modals when rendered within the bottom or top pane.

We also have another <div id="modal-root-default" /> at the body level of our app on the highest level.

This is for modals in non-split screen mode.

Modal componentModalPortal componentNow, wherever we render our Modal component it will have the right perspective.

Do note that we add an extra .

split class to the Modal when it’s in the split screen mode — we want to change the modal’s style in this mode as we have less space on the screen.

Now the modal will be either rendered in the modal-root-default, modal-root-bottom or modal-root-top, and will be rotated along with its parent if necessary.

ConclusionIn conclusion, making an app split screen is easier than you might think — just a single component handling the rotation of one half of the screen.

We experienced some problems with correct perspective for animations, since it was rendered within a portal on the top DOM level, but solved this using context.

This way we could keep the animation on the top DOM level and the correct x and y axis for our animations.

Our modals did not rely on these axis, so we could create a portal within the rotated DOM part of the split screen and leverage the context again to render it in the correct root.

Disclaimer: since we only developed for one specific device, an iPad Pro 12.

9", I can’t guarantee this solution works on any other devices.

.

. More details

Leave a Reply