Как реализовать переключение видео по прокрутке, как в YouTube Shorts, с помощью HTML/CSS/JavaScript?

Вопросы и ответы

Я работаю над дизайном контейнера для видео с использованием HTML, CSS и JavaScript, и хочу реализовать функцию, которая будет автоматически переключать видео при прокрутке, подобно тому, как это делает YouTube Shorts.

У меня есть базовый дизайн, где я загружаю видео вместе с кнопками взаимодействия, такими как подписка, лайк, комментарий и поделиться. Однако мне нужна помощь с функциональностью JavaScript, которая позволяет видео меняться, когда пользователь прокручивает мимо текущего видео.

Вот моя HTML-структура:

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Адаптивный дизайн Shorts</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="container">
        <!-- Видео секция -->
        <div class="video-container">
            <video id="video-player" src="videos/video1.mp4" controls></video>
            <!-- Кнопка подписки -->
            <button class="follow-button">Подписаться</button>

            <!-- Кнопки взаимодействия на проигрывателе видео -->
            <div class="actions">
                <div class="action-button like">
                    <span><i class="fa-regular fa-heart"></i></span>
                    <span>452</span>
                </div>
                <div class="action-button comment">
                    <span><i class="fa-regular fa-comment"></i></span>
                    <span>6</span>
                </div>
                <div class="action-button share">
                    <span><i class="fa-solid fa-share"></i></span>
                    <span>Поделиться</span>
                </div>
            </div>
        </div>
    </div>

    <script src="scripts.js"></script>
</body>
</html>

А вот и мой CSS:

/* Глобальные стили */
body, html {
    margin: 0;
    padding: 0;
    overflow-x: hidden;
}

.container {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    overflow: hidden;
}

.video-container {
    width: 100%;
    height: 100%;
}

video {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: Arial, sans-serif;
}

body {
    background-color: #181818;
    color: white;
}

.container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    padding: 20px;
    height: 100vh;
}

/* Видео секция */
.video-container {
    width: 100%;
    max-width: 400px;
    height: 800px;
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
}

video {
    width: 100%;
    height: 100%;
    border-radius: 10px;
    position: relative;
}

/* Кнопка подписки */
.follow-button {
    position: absolute;
    top: 10px;
    right: 10px;
    padding: 8px 12px;
    background-color: #ff0000;
    color: white;
    border: none;
    border-radius: 20px;
    cursor: pointer;
    font-size: 14px;
    transition: background-color 0.3s ease;
}

.follow-button:hover {
    background-color: #cc0000;
}

/* Секция действий: кнопки справа от видео */
.actions {
    position: absolute;
    right: 10px;
    top: 20%;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.action-button {
    margin: 10px 0;
    color: white;
    text-align: center;
    cursor: pointer;
    padding: 10px;
    background-color: rgba(0, 0, 0, 0.5); /* Полупрозрачный фон */
    border-radius: 50%;
    width: 50px;
    height: 50px;
    opacity: 0.8; /* Эффект прозрачности */
    transition: opacity 0.3s ease;
}

.action-button:hover {
    opacity: 1;
}

/* Убедитесь, что иконкиCentered внутри кнопок */
.action-button span {
    display: block;
}

/* Секция подписки */
.subscribe-section {
    display: flex;
    align-items: center;
    justify-content: space-between;
    background-color: #333;
    padding: 10px 15px;
    border-radius: 10px;
    max-width: 400px;
    width: 100%;
    margin-top: 10px;
}

.profile-pic {
    width: 50px;
    height: 50px;
    border-radius: 50%;
}

.subscribe-info {
    flex-grow: 1;
    padding-left: 10px;
}

.subscribe-button {
    padding: 10px 15px;
    background-color: #ff0000;
    border: none;
    border-radius: 5px;
    color: white;
    cursor: pointer;
}

/* Адаптивные медиа-запросы */
@media (max-width: 768px) {
    .actions {
        right: 5px;
        top: 15%;
    }

    .subscribe-section {
        flex-direction: column;
        align-items: center;
        padding: 15px;
    }

    .profile-pic {
        width: 40px;
        height: 40px;
    }

    .subscribe-button {
        margin-top: 10px;
        width: 100%;
    }
}

@media (max-width: 480px) {
    .video-container {
        max-width: 100%;
    }

    .actions {
        position: static;
        flex-direction: row;
        width: 100%;
        justify-content: space-evenly;
    }
}

Идея состоит в том, чтобы автоматически переключаться между несколькими видео на основе взаимодействия пользователя с прокруткой. У меня есть массив видео, и мне нужно загружать следующее при прокрутке. Вот JavaScript, который я пробовал:

document.addEventListener('DOMContentLoaded', function() {
    const videos = [
        "videos/video1.mp4",
        "videos/video2.mp4",
        "videos/video3.mp4",
        // Добавьте больше видео по мере необходимости
    ];

    let currentVideoIndex = 0;
    const videoPlayer = document.getElementById('video-player');

    // Функция для загрузки следующего видео
    function loadNextVideo() {
        currentVideoIndex++;
        if (currentVideoIndex >= videos.length) {
            currentVideoIndex = 0; // Вернуться к первому видео
        }
        videoPlayer.src = videos[currentVideoIndex];
        videoPlayer.play();
    }

    // Использование IntersectionObserver для определения, когда пользователь прокручивает мимо текущего видео
    const observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                // Если текущее видео полностью видно, воспроизведите его
                videoPlayer.play();
            } else {
                // Если видео больше не видно, загрузите следующее видео
                loadNextVideo();
            }
        });
    }, {
        threshold: 0.75 // Видео считается видимым, когда 75% его отображается на экране
    });

    // Наблюдение за контейнером видео
    observer.observe(videoPlayer);
});

Проблема:
Я хочу добиться такого же опыта, как в YouTube Shorts, где каждое прокручивание напрямую переходит к следующему видео. Однако я не уверен, является ли этот подход с IntersectionObserver лучшим для этого случая, или есть лучшее решение.

Какой будет лучший способ реализовать такое переключение видео на основе прокрутки?

Правка:
мой обновленный js:

console.log("Scroller");

// Определите массив видео
const videos = [
    "videos/video1.mp4",
    "videos/video2.mp4",
    "videos/video3.mp4",
    // Добавьте больше видео по мере необходимости
  ];

  // Получите элементы контейнера и проигрывателя видео
  const container = document.querySelector('.container');
  const videoPlayer = document.getElementById('video-player');

  // Инициализируйте индекс текущего видео
  let currentVideoIndex = 0;

  // Инициализируйте флаг, чтобы указать, взаимодействовал ли пользователь с документом
  let userHasInteracted = false;

  // Добавьте слушателя событий прокрутки к контейнеру
  container.addEventListener('scroll', (e) => {
    // Получите смещение видео и высоту
    const videoOffset = videoPlayer.offsetTop;
    const videoHeight = videoPlayer.offsetHeight;

    // Получите положение прокрутки и направление
    const scrollPosition = container.scrollTop;
    const scrollDirection = e.deltaY > 0 ? 'down' : 'up';

    // Проверьте, прокрутил ли пользователь вниз и текущее видео больше не видно
    if (scrollDirection === 'down' && scrollPosition > videoOffset + videoHeight - 20) {
      // Загрузите следующее видео
      loadNextVideo();
    }
  });

  // Функция для загрузки следующего видео
  function loadNextVideo() {
    // Увеличьте индекс текущего видео
    currentVideoIndex++;

    // Вернуться к первому видео, если мы достигли конца массива
    if (currentVideoIndex >= videos.length) {
      currentVideoIndex = 0;
    }

    // Обновите источник воспроизводителя видео
    videoPlayer.src = videos[currentVideoIndex];

    // Если пользователь взаимодействовал с документом, воспроизведите видео автоматически
    if (userHasInteracted) {
      videoPlayer.play();
    }
  }

  // Добавьте слушателя событий к документу, чтобы слушать взаимодействие пользователя
  document.addEventListener('click', () => {
    // Установите флаг, чтобы указать, что пользователь взаимодействовал с документом
    userHasInteracted = true;

    // Если видео не воспроизводится, воспроизведите его
    if (!videoPlayer.paused) {
      videoPlayer.play();
    }
  });

  // Инициализируйте проигрыватель видео с первым видео
  videoPlayer.src = videos[0];

Ответ

Чтобы реализовать функцию переключения видео на основе прокрутки, как в YouTube Shorts, мы можем воспользоваться обработчиком событий прокрутки в сочетании с некоторыми простыми математическими расчетами. Ниже представлен полный пример кода, который будет реализовывать эту функциональность.

Полный Код:

HTML

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Дизайн коротких видео</title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div class="container">
        <div class="video-container">
            <video id="video-player" src="videos/video1.mp4" controls></video>
            <button class="follow-button">Подписаться</button>
            <div class="actions">
                <div class="action-button like">
                    <span><i class="fa-regular fa-heart"></i></span>
                    <span>452</span>
                </div>
                <div class="action-button comment">
                    <span><i class="fa-regular fa-comment"></i></span>
                    <span>6</span>
                </div>
                <div class="action-button share">
                    <span><i class="fa-solid fa-share"></i></span>
                    <span>Поделиться</span>
                </div>
            </div>
        </div>
    </div>
    <script src="scripts.js"></script>
</body>
</html>

CSS

/* Общие стили */
body, html {
    margin: 0;
    padding: 0;
    overflow-x: hidden;
}

.container {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    overflow-y: scroll; /* Разрешить вертикальную прокрутку */
}

.video-container {
    width: 100%;
    height: 100vh; /* Высота контейнера равна высоте экрана */
}

video {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.actions {
    position: absolute;
    right: 10px;
    top: 20%;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.action-button {
    margin: 10px 0;
}

JavaScript

document.addEventListener('DOMContentLoaded', function() {
    const videos = [
        "videos/video1.mp4",
        "videos/video2.mp4",
        "videos/video3.mp4",
        // Добавьте больше видео при необходимости
    ];

    const videoPlayer = document.getElementById('video-player');
    let currentVideoIndex = 0;

    // Функция для загрузки следующего видео
    function loadNextVideo() {
        currentVideoIndex++;
        if (currentVideoIndex >= videos.length) {
            currentVideoIndex = 0; // Зацикливание на первом видео
        }
        videoPlayer.src = videos[currentVideoIndex];
        videoPlayer.play();
    }

    // Обработчик события прокрутки
    const container = document.querySelector('.container');
    container.addEventListener('wheel', (event) => {
        // Проверяем направление прокрутки
        if (event.deltaY > 0) {
            loadNextVideo();
        } else if (event.deltaY < 0) {
            currentVideoIndex--;
            if (currentVideoIndex < 0) {
                currentVideoIndex = videos.length - 1; // Зацикливание на последнем видео
            }
            videoPlayer.src = videos[currentVideoIndex];
            videoPlayer.play();
        }
        // Предотвращаем стандартное поведение прокрутки
        event.preventDefault();
    });

    // Инициализация первого видео
    videoPlayer.src = videos[currentVideoIndex];
});

Объяснение Код

  1. HTML-структура: Здесь создается основной контейнер с видео и кнопками взаимодействия. Видео прописывается через элемент <video>, что позволяет использовать его возможности.

  2. Стили CSS: Контейнеру и видео задается полная высота экрана, что позволяет прокручивать контейнер и видеть полное видео.

  3. JavaScript логика:
    • Массив с видео файлами.
    • При прокрутке колесом wheel определяем направление. Если прокрутка вниз, загружаем следующее видео, если вверх – загружаем предыдущее.
    • Используется event.preventDefault(), чтобы предотвратить стандартное поведение прокрутки страницы, тем самым обеспечивая фокус на видео.

Итоги

Это решение позволяет вам переключать видео прокручивая страницу, создавая эффект, схожий с YouTube Shorts. В дальнейшем вы можете добавлять дополнительные функции, такие как управления музыкой, плейлистами и событиями на конце видео.

Оцените материал
Добавить комментарий

Капча загружается...