Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 23.10.2021, 13:44
Аватар для lgick
Аспирант
Отправить личное сообщение для lgick Посмотреть профиль Найти все сообщения от lgick
 
Регистрация: 23.11.2013
Сообщений: 82

iframe загрузка видео youtube
Для оптимизации скорости загрузки страницы загружаю youtube-видео после того, как контейнер под видео будет в области видимости, до этого момента отображаю просто картинку

Необходимо убирать картинку, когда видео будет полностью загружено загружено.

Но когда вешаю onload на iframe, он срабатывает дважды, в момент когда видео ещё не готово к проигрыванию. Как это исправить, чтоб картинка убиралась после загрузки и готовности видео к воспоизведению?

<div class="youtube-video-lazy" data-video="5qap5aO4i9A" style="width: 480px; height: 320px; position: absolute; top: 0px; left: 0px; border: none;">
  <img src="" alt="video">
  <button style="border: none; background: transparent; cursor: pointer; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);">
    <svg width="68" height="48" viewBox="0 0 68 48">
      <path class="video-play-shape" style="fill: #212121; fill-opacity: 0.8;" d="M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z">
      </path>
      <path class="video-play-icon" style="fill: #ffffff;" d="M 45,24 27,14 27,34"></path>
    </svg>
  </button>
  <iframe style="width: 100%; height: 100%; display: block; object-fit: cover; border: none;" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture;" allowfullscreen=""></iframe>
</div>

<script>
function loadYoutubeElem(el) {
  let videoId = el.getAttribute('data-video');
  let iframe = el.querySelector('iframe');
  let query = '?rel=0&showinfo=0&autoplay=1';
      
  iframe.setAttribute('src', 'https://www.youtube.com/embed/' + videoId + query);
  iframe.onload = e => {
   // срабатывает два раза, 
    el.querySelector('img').remove();
    el.querySelector('button').remove();
}
}

function visibleYoutubeElem() {
  let elem = document.querySelectorAll('.youtube-video-lazy')[0];
  let targetPosition = {
    top: window.pageYOffset + elem.getBoundingClientRect().top,
    left: window.pageXOffset + elem.getBoundingClientRect().left,
    right: window.pageXOffset + elem.getBoundingClientRect().right,
    bottom: window.pageYOffset + elem.getBoundingClientRect().bottom
  };
  
  let windowPosition = {
    top: window.pageYOffset,
    left: window.pageXOffset,
    right: window.pageXOffset + document.documentElement.clientWidth,
    bottom: window.pageYOffset + document.documentElement.clientHeight
  };

  if (targetPosition.bottom > windowPosition.top &&
    targetPosition.top < windowPosition.bottom &&
    targetPosition.right > windowPosition.left &&
    targetPosition.left < windowPosition.right) {
    loadYoutubeElem(elem);
    window.removeEventListener('scroll', visibleYoutubeElem);
  };
}

window.addEventListener('scroll', visibleYoutubeElem);

document.querySelectorAll('.youtube-video-lazy').forEach(el => {
	let videoId = el.getAttribute('data-video');
	let img = el.querySelector('img');
	let youtubeImgSrc = 'https://i.ytimg.com/vi/' + videoId + '/sddefault.jpg';
  	let styles = 'width: 100%; height: 100%; display: block; object-fit: cover; border: none;';
    img.setAttribute('style', styles);
	img.setAttribute('src', youtubeImgSrc);
});
</script>
Ответить с цитированием
  #2 (permalink)  
Старый 23.10.2021, 13:47
Аватар для lgick
Аспирант
Отправить личное сообщение для lgick Посмотреть профиль Найти все сообщения от lgick
 
Регистрация: 23.11.2013
Сообщений: 82

Или, может быть посоветуете способ загрузки видео по клику?
Это гораздо лучше, но по клику не корректно работает на мобильных устройствах. Там запрещено автовоспроизведение, и нужно кликать дважды: первый раз, чтоб отобразить видео, второй раз, чтоб его воспроизвести
Ответить с цитированием
  #3 (permalink)  
Старый 23.10.2021, 16:33
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 31,150

youtube ленивая загрузка
lgick,

<!DOCTYPE html>
<html>
<head>
    <title>Untitled</title>
    <meta charset="utf-8">
    <style type="text/css">
        .youtube-video-lazy {
            width: 480px;
            height: 320px;
            position: relative;
            top: 0px;
            left: 0px;
            border: none;
        }
        iframe.youtube-video-lazy {
            transform: scale(0.9);
            opacity: 0;
            transition: transform .5s, opacity 1.5s;
        }
        iframe.youtube-video-lazy.ready {
            opacity: 1;
            transform: scale(1);
        }
        .youtube-video-lazy>img {
            width: 100%;
            height: 100%;
            display: block;
            object-fit: cover;
            border: none;
        }
        .youtube-video-lazy>button {
            border: none;
            background: transparent;
            cursor: pointer;
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
        }
        p {
            height: 1000px;
        }
    </style>
</head>
<body>
    <p></p>
    <div class="youtube-video-lazy" data-video="5qap5aO4i9A">
        <img src="" alt="video">
        <button>
        <svg width="68" height="48" viewBox="0 0 68 48">
            <path class="video-play-shape" style="fill: #212121; fill-opacity: 0.8;" d="M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z">
            </path>
            <path class="video-play-icon" style="fill: #ffffff;" d="M 45,24 27,14 27,34"></path>
        </svg>
    </button>
    </div>
    <p></p>
    <div class="youtube-video-lazy" data-video="xwmDe0OhhPs">
        <img src="" alt="video">
        <button>
        <svg width="68" height="48" viewBox="0 0 68 48">
            <path class="video-play-shape" style="fill: #212121; fill-opacity: 0.8;" d="M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z">
            </path>
            <path class="video-play-icon" style="fill: #ffffff;" d="M 45,24 27,14 27,34"></path>
        </svg>
    </button>
    </div>
    <p></p>
    <script>
        let tag = document.createElement('script');
        tag.src = "https://www.youtube.com/iframe_api";
        let firstScriptTag = document.getElementsByTagName('script')[0];
        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
        function onYouTubeIframeAPIReady() {
            let lazyYoutube = divs =>
                divs.forEach(el => {
 
                    if (el.intersectionRatio > 0.8) {
                        let div = el.target;
                        observer.unobserve(div);
                        div.visibleYoutubeElem()
                    }
                });
            let observer = new IntersectionObserver(lazyYoutube, {
                rootMargin: "0px",
                threshold: [.8]
            });
            let youtube = document.querySelectorAll('.youtube-video-lazy');
            youtube.forEach(div => {
                let videoId = div.dataset.video;
                let img = div.querySelector('img');
                let youtubeImgSrc = `https://i.ytimg.com/vi/${videoId}/hqdefault.jpg`;
                img.src = youtubeImgSrc;
                observer.observe(div);
                const onPlayerReady = function(q) {
                    q.target.h.classList.add('ready')
                }
                div.visibleYoutubeElem = _ => {
                    new YT.Player(div, {
                        height: '320',
                        width: '480',
                        videoId,
                        events: {
                            'onReady': onPlayerReady
                        }
                    });
                }
            })
        }
    </script>
</body>
</html>

Последний раз редактировалось рони, 23.10.2021 в 17:10.
Ответить с цитированием
  #4 (permalink)  
Старый 23.10.2021, 20:58
Аватар для lgick
Аспирант
Отправить личное сообщение для lgick Посмотреть профиль Найти все сообщения от lgick
 
Регистрация: 23.11.2013
Сообщений: 82

рони,
Не знал о IntersectionObserver, спасибо большое!
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
youtube iframe работает неправильно ethereal Элементы интерфейса 1 24.08.2021 22:24
Предварительная загрузка видео html5 arkadii_parovozov Общие вопросы Javascript 1 20.04.2019 14:13
Просмотрщик видео с YouTube на JS egor8 Общие вопросы Javascript 0 10.02.2019 13:17
Загрузка iframe по клику в кнопке Ilya_Ru Элементы интерфейса 5 07.11.2016 02:39
Загрузка видео на Youtube с помощью XHR2 RazDroid AJAX и COMET 2 15.01.2013 02:06