Chętnie zabrałem się za ten feature z dwóch powodów:
- jest bardzo przydatny, sam używam floating video na youtubie
- nigdy czegoś takiego nie pisałem, więc chętnie się pobawię
Na samym początku trzeba rozgryźć jak zhakować wykop aby uzyskać ten efekt.
🐱💻 Hakowanie
Zobaczmy jak wygląda kod html gdzie player jest umieszczony.

Hmm widać, że to nie jest zaembedowany youtube, lecz preview złożony z obrazka oraz linka. Po kliknieciu w preview, leci wywołanie ajaxem a obrazek zastępowany jest przez iframe youtuba

Elementy mamy namierzone. Teraz musimy poszukać czegoś co się stanie floatem. .videoWrapper wygląda tutaj bardzo sensownie. F12 i dodajemy w konsoli style

Efekt mnie zaskoczył. Wszystko zninęło. Nawet po ustawieniu Height: z 0 na 1000px nic się nie pojawia

Szukamy dalej hmm

.embed-youtube jest zbyt wysoko, ponieważ już łapie treść posta (Test), a chcemy zrobić floata wyłącznie na playerze. Uderzamy w iframe

Yeah! Mały sukces. Iframe drgnął i osadził się w stałym miejscu (position: fixed)

Jeszcze zmienimy aby player był na pierwszym planie przez dodanie z-index

Świetnie, pierwszy krok zrobiony. Trzeba pomyśleć jak sam feature ma działać.
🐱👤 Działanie
- Jako użytkownik klikam w playera
- Filmik sie uruchamia
- Przewijam stronę w dół
- Player znika z ekranu
- Player przenosi się w prawy dolny róg ekranu
🐱🏍 Piszemy kod!
Co na ten moment mamy? Potrafimy ustawić odpowiedni element (iframe) jako position: fixed. Najważniejszą teraz rzeczą jest wykrycie czy element zniknął nam z ekranu (viewport). Szybka grzebanina po necie, wiadomo SDD (StackOverflow Driven Development)
function isElementInViewport($element) {
var rect = $element.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <=
(window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
Wykrywanie czy element jest widoczny działa. Trzeba to przyczepić do window.scrolla
window.addEventListener("scroll", function () {
getAllVideoPlayers().forEach(function ($videoPlayer) {
if (isElementInViewport($videoPlayer)) {
console.log("is visible")
}
else {
console.log("is NOT visible")
}
});
});
Szybki test… wygląda OK. Brniemy w to dalej!
function makeFloatVideo($player) {
$player.setAttribute(
"style",
"position: fixed; top: 75%; left: 81%; width: 320px; height: 190px; z-index: 100000"
);
}
Niby działa ale coś dziwnie. Przy każdym scrollu cały proces się uruchamia na nowo, iframe mruga, dzieją się rzeczy niestworzone.
Hmm nie ma sensu aby nawet najdelikatniejszy scroll odpalał całą procedurę od nowa. Przecież jak element już jest niewidoczny, to po co znów ustawiać style?
Idziemy w najprostsze rozwiązanie, Robimy flagę, która będzie czuwać nad uruchomieniem makeFloatVideo. Jeśli dojdzie do zmiany stanu (widoczny => niewidoczny) wtedy dopiero uruchomimy makeFloatVideo
function onVisibilityChange($element, invisibleCallback) {
var prevVisibility = $element.getAttribute(DATA_VISIBLE_ATTR);
if (prevVisibility === null) {
prevVisibility = false; // domyślna wartosc
} else {
prevVisibility = Boolean(prevVisibility); // musimy zrobic parsing dla boola, żeby nie operować na stringu: true/false
}
var currentVisibity = isElementInViewport($element);
if (currentVisibity != prevVisibility) { // jeśli poprzednia wartość flagi z obecną się nie zgadzają, znaczy że zaszła zmiana
$element.setAttribute(DATA_VISIBLE_ATTR, currentVisibity);
if (!currentVisibity) {
invisibleCallback();
}
}
}
Działa i to jeszcze jak! 😉 Reszta rzeczy to już kosmetyka i drobnica, o której nie będę pisać, bo nie ma sensu. Nic ciekawego się w dalszej części prac nie dzieje.
👉 Dla zainteresowanych odsyłam do githuba.
🏍️ Światła! Kamera! Akcja!

👉 Klikamy w VIDEO

👉 SCROLL w doł

🔥Ale piękny floating video wyszedł🔥
Później trochę odsunę od krawędzi, bo jest zbyt blisko. Generalnie jestem zadowolony z (d)efektu.
Zapraszam do pobrania rozszerzenia Chrome Web Store i uczestnictwa w projekcie!
to be continued ヘ( ^o^)ノ\(^_^ )