|
|
|
|
|
|
|
|
<meta charset="utf-8"/> |
|
|
|
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="/pico.css" /> |
|
|
|
|
|
|
|
|
|
|
|
<style> |
|
|
|
|
|
body { |
|
|
|
|
|
margin: 0; |
|
|
|
|
|
} |
|
|
|
|
|
.media { |
|
|
|
|
|
position: fixed; |
|
|
|
|
|
top: 50; |
|
|
|
|
|
left: 100; |
|
|
|
|
|
width: 800; |
|
|
|
|
|
height: 300; |
|
|
|
|
|
background-color: crimson; |
|
|
|
|
|
padding: 1em; |
|
|
|
|
|
overflow: hidden; |
|
|
|
|
|
resize: both; |
|
|
|
|
|
} |
|
|
|
|
|
.videos { |
|
|
|
|
|
--pad: 3px; |
|
|
|
|
|
grid-gap: var(--pad); |
|
|
|
|
|
padding: var(--pad); |
|
|
|
|
|
height: calc(100% - 2 * var(--pad)); |
|
|
|
|
|
background-color: royalblue; |
|
|
|
|
|
} |
|
|
|
|
|
</style> |
|
|
|
|
|
|
|
|
|
|
|
<body> |
|
|
|
|
|
<div class="media"> |
|
|
|
|
|
<div class="videos"> |
|
|
|
|
|
<div class="video-container mirror"> |
|
|
|
|
|
<video autoplay></video> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div class="video-container mirror square"> |
|
|
|
|
|
<video autoplay></video> |
|
|
|
|
|
</div> |
|
|
|
|
|
<div class="video-container mirror"> |
|
|
|
|
|
<video autoplay></video> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
</body> |
|
|
|
|
|
|
|
|
|
|
|
<script> |
|
|
|
|
|
navigator.mediaDevices.getUserMedia({audio: false, video: true}) |
|
|
|
|
|
.then(stream => document.querySelectorAll('video') |
|
|
|
|
|
.forEach(video => video.srcObject = stream)) |
|
|
|
|
|
</script> |
|
|
|
|
|
<script> |
|
|
|
|
|
const doOne = ({target}) => target.style.setProperty('--height', `${target.clientHeight}px`) |
|
|
|
|
|
const doAll = (entries) => entries.forEach(doOne) |
|
|
|
|
|
sizer = new ResizeObserver(doAll) |
|
|
|
|
|
document.querySelectorAll('.video-container').forEach(el => sizer.observe(el)) |
|
|
|
|
|
document.querySelectorAll('.video-container').forEach(el => |
|
|
|
|
|
el.onclick = (ev) => el.classList.toggle('full-screen')) |
|
|
|
|
|
</script> |
|
|
|