Алло! Ваш дизайнер ещё на месте? Нужно на нашем сайте сделать фон зеркальным, чтобы пользователь заходил и видел своё отражение
Если вы видели этот мем, то наверняка посмеялись над странными идеями заказчиков, и быть может, заинтересовались темой зеркального фона.
В принципе, зеркальный фон не так сложно реализовать, как может показаться. Давайте разбираться! Нам нужно:
- Знание HTML, CSS и Javascript
- Веб-камера пользователя
- Немножко смекалки
Я не буду приводить весь код, опишу только важные моменты. Для начала возьмём два контейнера: первый будет зеркальным фоном, второй — телом документа.
<div class="video">
<video id="video" autoplay="autoplay" width="1920" height="1080"></video>
</div>
<div class="body">
<div class="body-content">
<h1>Сайт с зеркальным фоном</h1>
<p>Чтобы фон на сайте стал зеркальным, нам необходимо получить доступ к вашей веб-камере. Нажмите на кнопку в браузере, чтобы разрешить доступ.</p>
</div>
</div>
<div class="video">
будет у нас в качестве фона, а <div class="body">
— телом документа. Также мы добавляем тег <video>
для загрузки самого видео и <div class="body-content">
в качестве контейнера содержимого сайта. Итак, HTML-разметка у нас есть. Возьмёмся за CSS.
<style>
body > div {
position: absolute;
width: 100%;
height: 100%;
}
.video {
z-index: 1;
}
.body {
z-index: 2;
}
video {
position: absolute;
width: 100%;
height: 100%;
}
</style>
Что мы сделали? Во-первых, мы спозиционировали два родительских контейнера абсолютно и задали им стопроцентные ширину и высоту, чтобы оба контейнера занимали всё пространство документа. Далее мы выставили им очерёдность, контейнер с видео отправили назад, а тело документа — вперёд.
Теперь немного магии
<script>
window.onload = function() {
var video = document.getElementById( 'video' );
var videoStreamUrl = false;
//navigator.getUserMedia (Для каждого браузера определяем правильный метод)
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
//window.URL.createObjectURL (Для каждого браузера определяем правильный метод)
window.URL.createObjectURL = window.URL.createObjectURL || window.URL.webkitCreateObjectURL || window.URL.mozCreateObjectURL || window.URL.msCreateObjectURL;
//Запрашиваем разрешение на доступ к видео-потоку
navigator.getUserMedia( {
video : {
width : { ideal : window.width },
height : { ideal : window.height },
facingMode: "user"
}
}, function( stream ) {
//Разрешение от пользователя получено
//Получаем url поточного видео
videoStreamUrl = window.URL.createObjectURL( stream );
// устанавливаем как источник для video
video.src = videoStreamUrl;
}, function() {
console.log( 'Что-то не так с видео-потоком или пользователь запретил его использовать!' );
} );
};
</script>
При загрузке страницы мы находим элемент video
и записываем его в переменную. Далее необходимо получить метод getUserMedia объекта navigator — navigator.getUserMedia
. Этот метод и делает всю работу за нас: просит у пользователя разрешение на использование веб-камеры, инциализирует её, управляет видео-потоком, и так далее. Мы всего лишь настраиваем его на вывод видео-потока в нужном месте.
На вход метод принимает объект MediaStreamConstraints, в котором есть всего два свойства: video
и audio
. Эти свойства принимают значения типа boolean или MediaStreamConstraints. Мы используем снова MediaStreamConstraints. Но на этот раз мы укажем уже необходимые параметры видео-потока. Нам нужны только ширина width : { ideal : window.width }
— указываем идеальную ширину, равную ширине экрана, высота height : { ideal : window.height }
— указываем идеальную высоту, равную высоте экрана, и facingMode: "user"
на случай, если у пользователя 2 камеры — передняя и задняя (используем переднюю).
Второй параметр — это функция, в которой мы получаем объект видео-потока stream
, который можем использовать в своих целях. Нам необходимо получить URL. Делаем это с помощью метода window.URL.createObjectURL( stream )
и передаём полученный URL-адрес в атрибут src
нашего элемента video
. Вот и всё! Больше нам ничего не нужно.
Ну как же без траблов
Если вы уже опробовали этот код в действии, то, наверняка, заметили, что фон получился не полностью зеркальный, а, скорее, анти-зеркальный — мы видим обратное отражение. Чтобы получить полное зеркало, нужно применить небольшую трансформацию… Добавим в CSS-стиль элемента video
следующее свойство:
<style>
video {
transform: scale(-1, 1);
}
</style>
Первый параметр отвечает за масштабирование по горизонтали, а второй — по вертикали. Таким образом мы отразим элемент по горизонтали и получим «настоящее зеркало».
Также вы могли заметить, что на некоторых устройствах наше «зеркало» занимает не весь экран, по сторонам видны пустые полосы. Это происходит из-за того, что веб-камера отдаёт видео-поток не в том разрешении, в котором мы видим окно браузера, а в том, в котором она способна его отдавать. А браузер, в свою очередь, пытается уместить в окне весь видео-поток. Давайте исправим эту ситуацию с помощью той же трансформации. Изменим свойство transform
на следующее:
<style>
video {
transform: scale(-1.6, 1.6);
}
</style>
Увеличив оба коэффициента, мы увеличим видео в браузере, и оно займёт больше места, чем занимало изначально. Вы можете «поиграться» с коэффициентами и выбрать подходящие для вашего конкретного случая.
Посмотреть на всё это вживую можно по этой ссылке.