Niestandardowe paski przewijania są bardzo rzadkie. Główną przyczyną jest to, paski przewijania to jeden z pozostałych elementów internetu, niestylowa (patrzę na Ciebie, selektor daty). Można używać JavaScriptu do tworzenia własnych treści, ale jest to kosztowne i niedrogie. i może działać z opóźnieniem. W tym artykule omówimy za pomocą niekonwencjonalnych macierzy CSS do utworzenia niestandardowego elementu przewijania, który nie wymaga JavaScript podczas przewijania, tylko trochę kodu konfiguracji.
TL;DR
Nie interesują Cię drobiazgi? Wystarczy spojrzeć na Prezentacja z kotami Nyan i dołączyć do biblioteki? Kod demonstracyjny znajdziesz w repozytorium GitHub.
LAM;WRA (długie i matematyczne – można przeczytać mimo to)
Jakiś czas temu zbudowaliśmy mechanizm przewijania paralaksy (Czy znasz ten artykuł? To naprawdę dobre, warte Twojego czasu). Odpychając elementy za pomocą CSS 3D po przekształceniu, elementy przesuwały się wolniej niż rzeczywista szybkość przewijania.
Podsumowanie
Zacznijmy od podsumowania działania funkcji przewijania paralaksy.
Jak pokazano na animacji, efekt paralaksy udało się uzyskać, przesuwając elementy. „do tyłu” w przestrzeni 3D, wzdłuż osi Z. Przewijanie dokumentu przesunięcia wzdłuż osi Y. Jeśli więc przewiniesz w dół o, powiedzmy 100 pikseli, zostanie przesunięty w górę o 100 pikseli. Dotyczy to wszystkich elementów, nawet tych, które są „bardziej oddalone”. Ale ponieważ są one w większej odległości aparat, obserwowany ruch na ekranie będzie mniejszy niż 100 pikseli, odpowiedni efekt paralaksy.
Oczywiście przesunięcie elementu w przestrzeń kosmiczna też zmniejszy jego rozmiar, Korygowany jest przez ponowne skalowanie elementu. Dokładnie obliczyliśmy gdy tworzyliśmy paralaksa przewijana, więc nie będę powtarzać wszystkich szczegółów.
Krok 0. Co chcesz zrobić?
Paski przewijania. To właśnie zamierzamy stworzyć. Ale czy kiedykolwiek zastanawialiście się, o tym, co robią? Ja nie. Paski przewijania wskazują na: jaka część dostępnych treści jest obecnie widoczna i jaki jest postęp. jak czytelnik. Jeśli przewiniesz w dół, pasek przewijania do wskazuje, że idzie Ci do końca. Jeśli cała zawartość pasuje w widocznym obszarze, a pasek przewijania jest zwykle ukryty. Jeśli treść jest 2 razy większa niż widoczny obszar, wypełnia on 1⁄2 wysokości widocznego obszaru. Treść warta 3 razy więcej widoczny obszar skaluje pasek przewijania do 1⁄3 widocznego obszaru itd. Widać wzorzec. Zamiast przewijać, możesz też kliknąć i przeciągnąć pasek przewijania, aby poruszać się po nim. działanie strony. To zaskakujące zachowania dla tak niepozornej firmy, taki element. Zagrajmy po jednej bitwie.
Krok 1. Odwrotność
W CSS 3D możemy sprawić, że elementy będą przesuwały się wolniej niż przewijanie zgodnie z opisem w artykule z przewijaniem z efektem paralaksy. Czy możemy też odwrócić kolejność wskazówkę? Okazuje się, że możemy to zrobić. Niestandardowy pasek przewijania. Aby zrozumieć, jak to działa, musimy omówić podstawy CSS 3D.
Aby uzyskać dowolną perspektywę w sensie matematycznym, trzeba prawdopodobnie wykorzystasz jednorodne współrzędne. Nie chcę mówić szczegółowo, czym są i dlaczego działają, ale możesz pomyśleć o tym, je jak współrzędne 3D z dodatkową, czwartą współrzędną o nazwie W. Ten powinna wynosić 1, chyba że chcesz uzyskać zniekształcenie perspektywy. Śr nie musimy zaprzątać sobie głowy szczegółami w, ponieważ nie będziemy używać żadnego inną niż 1. Dlatego wszystkie punkty pochodzą od teraz na 4-wymiarowe wektory [x, y, z, w=1], a w związku z tym macierze muszą 4 x 4.
Jedną z sytuacji, w której można zobaczyć, że usługa porównywania cen używa jednorodnych współrzędnych w kolumnie
definiowania własnych macierzy 4x4 we właściwości przekształcenia za pomocą funkcji
matrix3d()
. Funkcja matrix3d
przyjmuje 16 argumentów (ponieważ tablica to
4 x 4), określając jedną kolumnę po drugiej. Możemy więc użyć tej funkcji do
ręcznie określać obroty, tłumaczenia itd. Pozwala nam to jednak
ma bałagan z koordynatorem.
Zanim zaczniemy używać elementu matrix3d()
, potrzebny jest kontekst 3D.
w kontekście 3D nie doszłoby do zniekształcenia perspektywy.
jednorodne współrzędne. Aby utworzyć kontekst 3D, potrzebujemy kontenera z
perspective
i kilka znajdujących się w nim elementów, które możemy przekształcić w nowoczesnym
utworzono przestrzeń 3D. Dla:
przykład:
![Fragment kodu CSS zniekształcający element div za pomocą atrybutu CSS
i perspektywy.](https://developer.chrome.com/static/docs/css-ui/custom-scrollbar/image/a-piece-css-code-distor-1ed892aadfd7c.png?authuser=4&hl=pl)
Elementy wewnątrz kontenera perspektywy są przetwarzane przez silnik CSS w następujący sposób:
- Przekształć każdy róg (wierzchołek) elementu w jednorodne współrzędne
[x,y,z,w]
względem kontenera perspektywy. - Zastosuj wszystkie przekształcenia elementu jako macierze od prawej do lewej.
- Jeśli perspektywę można przewijać, zastosuj macierz przewijania.
- Zastosuj macierz perspektyw.
Macierz przewijania to przesunięcie wzdłuż osi Y. Jeśli przewiniemy w dół o 400 pikseli, wszystkie elementy należy przesunąć w górę o 400 pikseli. Macierz perspektyw to macierz, która „przyciąga” punkty bliżej punktu znikania w trójwymiarze, w przestrzeni kosmicznej. Efekt jest w obu przypadkach mniejszy. są oddalone od siebie i sprawiają, że podczas tłumaczenia „przesuwają się wolniej”. Jeśli element zostanie przesunięty wstecz, przesunięcie o 400 pikseli spowoduje, że element przesunięcie o 300 pikseli po ekranie.
Aby poznać wszystkie szczegóły, przeczytaj specyfikacja usługi porównywania cen ale na potrzeby tego artykułu uprościłem model algorytmem opisanym powyżej.
Nasze pudełko znajduje się wewnątrz kontenera perspektywy z wartością p dla perspective
i załóżmy, że kontener można przewijać
n pikseli.
Pierwsza macierz to macierz perspektyw, a druga to przewijanie. lub macierz. Podsumujmy: zadaniem macierzy przewijania jest przesuwanie w górę elementu, przewijają w dół, stąd znak minus.
Na pasku przewijania chcemy jednak widzieć przeciwieństwem – chcemy, by element
przesuń w dół, gdy przewijamy w dół. Oto miejsca, w których możemy użyć sztuczki:
Odwrócenie współrzędnej W rogów prostokąta. Jeśli współrzędna W to
-1, wszystkie tłumaczenia będą działały w odwrotnym kierunku. Jak
to? Mechanizm CSS konwertuje rogi pola na
jednorodne współrzędne i ustawia w na 1. matrix3d()
– czas zabłysnąć!
.box {
transform:
matrix3d(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, -1
);
}
Ta tablica robi nic innego niż negowanie w. Gdy więc mechanizm usług porównywania cen
przekształci każdy róg w wektor o postaci [x,y,z,1]
, macierz
przekonwertować go na: [x,y,z,-1]
.
Jestem przedstawiony jako krok pośredni, który pokazuje efekt przekształcenia elementu. lub macierz. Jeśli nie czujesz się dobrze z matematyką matrycową, nic nie szkodzi. Eureka Moment jest taki, że w ostatnim wierszu dodajemy przesunięcie przewijania n do wartości y zamiast jej odejmowania. Element zostanie przesunięty w dół. po przewinięciu w dół.
Jeśli jednak umieścimy tę macierz w naszym przykład, element nie będzie wyświetlany. Dzieje się tak, ponieważ specyfikacja CSS wymaga, wierzchołek z w < Wartość 0 blokuje renderowanie elementu. A ponieważ współrzędna to obecnie 0, a p to 1, W to -1.
Na szczęście możemy wybrać wartość z! Aby mieć pewność, że kończymy w=1, musimy , aby ustawić Z = –2.
.box {
transform:
matrix3d(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, -1
)
translateZ(-2px);
}
Oto nasz box powraca!
Krok 2. Daj z siebie wszystko
Nasze pudełko jest dostępne i wygląda tak samo jak bez innych przekształcenia. Obecnie kontenera perspektywy nie można przewijać, ale wiemy, że nasz element pójdzie w innym kierunku, gdy przewinięto. Może zaczniemy przewijać kontener? Wystarczy dodać element odstępu, który zajmuje miejsce:
<div class="container">
<div class="box"></div>
<span class="spacer"></span>
</div>
<style>
/* … all the styles from the previous example … */
.container {
overflow: scroll;
}
.spacer {
display: block;
height: 500px;
}
</style>
A teraz przewiń okno! Czerwone pole przesuwa się w dół.
Krok 3. Dobierz odpowiedni rozmiar
Widać element, który przesuwa się w dół, gdy strona przewija się w dół. To jest to trudne że brakuje im drogi. Teraz musimy nadać jej styl, tak by wyglądał jak pasek przewijania, uczynić go bardziej interaktywnym.
Pasek przewijania zwykle składa się z „kciuka” i „ścieżki”, ale nie jest zawsze widoczne. Wysokość kciuka jest wprost proporcjonalna do wysokości jest widoczna.
<script>
const scroller = document.querySelector('.container');
const thumb = document.querySelector('.box');
const scrollerHeight = scroller.getBoundingClientRect().height;
thumb.style.height = /* ??? */;
</script>
scrollerHeight
to wysokość elementu, który można przewijać, a
scroller.scrollHeight
to łączna wysokość treści, które można przewijać.
scrollerHeight/scroller.scrollHeight
to część treści, która jest
widoczne. Odstęp między osłonami na kciuki w pionie powinien być równy
proporcje widocznej treści:
<script>
// …
thumb.style.height =
scrollerHeight * scrollerHeight / scroller.scrollHeight + 'px';
// Accommodate for native scrollbars
thumb.style.right =
(scroller.clientWidth - scroller.getBoundingClientRect().width) + 'px';
</script>
Rozmiar kciuka to wygląda nieźle, ale porusza się za szybko. W tym miejscu opanujemy technikę funkcja przewijania paralaksy. Jeśli przesuniemy element dalej do tyłu, będzie on przesuwał się wolniej, przewijanie. Możemy go skorygować, skalując go w górę. Ale jak bardzo odwrócić? Czas na matematykę! To ostatni raz, lub obiecywanie.
Ważne jest, aby kciukiem znajdował się na dole
wyrównaj z dolną krawędzią elementu możliwego do przewijania po przewinięciu do końca
w dół. Innymi słowy: jeśli przewinęliśmy stronę
scroller.scrollHeight - scroller.height
pikseli, chcemy mieć kciuk
tłumaczenie: scroller.height - thumb.height
. Na każdy piksel przewijania
chcemy, by kciuk przemieścił ułamek piksela:
To nasz współczynnik skalowania. Teraz trzeba przekonwertować współczynnik skalowania na
przesunięcie wzdłuż osi Z, co zrobiliśmy już przy przewijaniu paralaksy.
. Według
odpowiedniej sekcji specyfikacji:
Współczynnik skalowania jest równy p/(p – z). Możemy rozwiązać równanie Z do
określić, jak bardzo kciuk należy przesunąć wzdłuż osi Z. Ale zachowaj
pamiętaj, że ze względu na koordynację działań musimy przetłumaczyć
dodatkowe -2px
wzdłuż wartości z. Pamiętaj też, że stosowane są przekształcenia elementu.
od prawej do lewej, co oznacza, że tłumaczenia sprzed naszej specjalnej macierzy
zostaną odwrócone, jednak wszystkie tłumaczenia po naszej specjalnej macierzy Zaczynajmy
Skoduj to!
<script>
// ... code from above...
const factor =
(scrollerHeight - thumbHeight)/(scroller.scrollHeight - scrollerHeight);
thumb.style.transform = `
matrix3d(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, -1
)
scale(${1/factor})
translateZ(${1 - 1/factor}px)
translateZ(-2px)
`;
</script>
Mamy pasku przewijania. Jest to po prostu element DOM, który możemy dowolnie zmieniać. Jedna rzecz, w przypadku ułatwień dostępu ważne jest, aby kciuk reagował kliknij i przeciągnij, bo wielu użytkowników korzysta z paska przewijania w ten sposób. Aby nie wydłużać tego posta, nie będę wyjaśniać, aby dowiedzieć się więcej na ten temat. Zwróć uwagę na: kod biblioteki .
A co z iOS?
Ach, mój stary przyjaciel Safari na iOS. Podobnie jak przy przewijaniu z paralaksą, natknęliśmy się na
ten problem. Ponieważ przewijamy element, musimy określić
-webkit-overflow-scrolling: touch
, ale powoduje to wygładzanie 3D i
efekt przewijania przestanie działać. Rozwiązaliśmy ten problem w narzędziu do przewijania paralaksy
wykrywając przeglądarkę Safari w iOS i stosując protokół position: sticky
jako obejście problemu;
tutaj zrobimy dokładnie to samo. Zwróć uwagę na:
artykuł paralaksujący
aby odświeżyć wspomnienie.
A co z paskiem przewijania w przeglądarce?
W przypadku niektórych systemów musimy korzystać ze stałego, natywnego paska przewijania.
Dawniej paska przewijania nie można było ukryć (z wyjątkiem
niestandardowy pseudoselektor).
Aby ją ukryć, musimy uciekać się do jakiegoś ataku hakerów. Skupiamy się na
przewijany element w kontenerze z parametrem overflow-x: hidden
i ustaw tag
przewijany element jest szerszy niż kontener. Natywny pasek przewijania w przeglądarce to
jest teraz niewidoczny.
Fin
Po połączeniu wszystkich tych elementów możemy utworzyć idealną ramkę paska przewijania, takiego jak Prezentacja Nyan Cat.
Jeśli nie widzisz Nyan cat, wykryty i zgłoszony błąd podczas tworzenia wersji demonstracyjnej (kliknij kciuk, aby pojawił się kot Nyan). Chrome naprawdę świetnie radzi sobie z unikaniem niepotrzebnej pracy np. malowania lub animowania rzeczy, które nie są widoczne na ekranie. Zła wiadomość jest taka, sprawiają, że Chrome uważa, że ten GIF z kotem Nyan nie pojawia się na ekranie. Mamy nadzieję, że wkrótce problem zostanie rozwiązany.
I o to chodzi. Wymagało to dużo pracy. Dziękuję za przeczytanie całego To jest niektóre jest to dość skomplikowane i niezwykle jest warte wysiłku, z wyjątkiem sytuacji, gdy niestandardowy pasek przewijania jest istotnym elementem obsługi. Ale dobrze wiedzieć, że to możliwe, prawda? Fakt, że jest to trudne do zrobienia, niestandardowy pasek przewijania pokazuje, że po stronie CSS jest jeszcze coś do zrobienia. Ale nie bójcie się! W przyszłości Houdini AnimationWorklet zrobi czy tworzenie idealnych ramek czy przewijanie.