Алло! Ваш дизайнер ещё на месте? Нужно на нашем сайте сделать фон зеркальным, чтобы пользователь заходил и видел своё отражение

- 4 сентября 2017 года

Если вы видели этот мем, то наверняка посмеялись над странными идеями заказчиков, и быть может, заинтересовались темой зеркального фона.

В принципе, зеркальный фон не так сложно реализовать, как может показаться. Давайте разбираться! Нам нужно:

  • Знание 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>

Увеличив оба коэффициента, мы увеличим видео в браузере, и оно займёт больше места, чем занимало изначально. Вы можете «поиграться» с коэффициентами и выбрать подходящие для вашего конкретного случая.

Посмотреть на всё это вживую можно по этой ссылке.

Понравилось? Поделитесь статьей в социальных сетях:

На нашем сайте используются файлы cookies, которые делают его более удобным для каждого пользователя. Посещая страницы сайта, вы соглашаетесь с нашей Политикой конфиденциальности. Подробнее ознакомиться с политикой и тем, для чего именно необходимы файлы cookies, можете узнать здесь

Walnut Team
Начать проект