I am working on a video calling application using reactjs. LocalTile component contains video of local user and RemoteTiles is returning videos of all remote users. My desired layout is like for 3 users:
===video1=video2===
=======video3======
for 4 users:
===video1=video2===
===video3=video4===
for 5 users:
===video1=video2=video3===
=======video4=video5======
<div id='gallery-parent' style={{ display: 'flex', flex: '1 1', flexDirection: 'column', gap: '1rem', position: 'relative' }}>
<div style={{ alignItems: 'stretch', display: 'flex', flex: '1 1', gap: '1rem',justifyContent:'center'}}>
<LocalTile />
<RemoteTiles />
</div>
</div>
its not working for me as all users are rendering in same column and shrinking videos.
I'm not 100% sure how you'd implement this in your larger codebase, but this is how I'd do it in vanilla JS. After the list of callers is rendered, you can grab the one just past halfway and insert a non-shrinking full-width element before it which will force the wrap to happen.
This little example utility allows n number of users in the input box and will split them as expected
function updateHandler(){
if(input.value === '') return;
//else
const n = parseInt(input.value),
half = Math.ceil(n/2)
output.innerHTML = Array.apply(null, Array(n)).map(() => `<div class="caller"></div>`).join('')
const halfwayElem = output.querySelectorAll('.caller')[half],
splitter = document.createElement('hr')
splitter.className = 'callers-divider'
output.insertBefore(splitter, halfwayElem)
}
updateHandler()
input.oninput = updateHandler
#output {
width: 100%;
display: flex;
flex-wrap: wrap;
}
.caller {
flex: 1;
border: 1px solid black;
margin: 8px;
aspect-ratio: 4/3;
}
.callers-divider {
display: block;
width: 100%;
flex-shrink: 0;
}
<label>Number of users connected: <input id="input" value="5" /></label>
<div id="output"></div>
Alternatively, if you don't want the second row to take up the full width
and just center the two callers, it can be done with CSS instead of DOM manipulation. This uses the bitwise operator n ^ 1
to determine if n
is odd and if so, bump it up to the next even number
function updateHandler(){
if(input.value === '') return;
//else
let n = parseInt(input.value)
output.innerHTML = Array.apply(null, Array(n)).map(() => `<div class="caller"></div>`).join('')
const shiftedN = n ^ 1
if(n !== shiftedN){
++n
}
const callerWidth = (200/n) + '%'
output.style.setProperty('--caller-width', callerWidth)
}
updateHandler()
input.oninput = updateHandler
#output {
width: 100%;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.caller {
border: 1px solid black;
aspect-ratio: 4/3;
box-sizing: border-box;
width: var(--caller-width);
}
<label>Number of users connected: <input id="input" value="5" /></label>
<div id="output"></div>