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> |
Или, может быть посоветуете способ загрузки видео по клику?
Это гораздо лучше, но по клику не корректно работает на мобильных устройствах. Там запрещено автовоспроизведение, и нужно кликать дважды: первый раз, чтоб отобразить видео, второй раз, чтоб его воспроизвести |
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> |
рони,
Не знал о IntersectionObserver, спасибо большое! |
Часовой пояс GMT +3, время: 09:17. |