Po co komu frameworki, gdy przy odrobinie czystego JavaScript jesteśmy w stanie osiągnąć efekt znany z wielu sklepów e-commerce!
Cześć, w tym wideo pokażę wam jak zrobić lupę do zdjęć
Zaczynajmy
[ intro kodu.je ]
Zapewne na wielu sklepach internetowych spotkaliście się z sytuacją,
gdzie po najechaniu na zdjęcie, otwiera się wam jego przybliżony podgląd
W tym materiale pokażę wam jak w prosty sposób zaimplementować taką funkcjonalność
Zaczniemy od stworzenia diva o klasie "photo"
Reprezentować on będzie nasze zdjęcie,
które będziemy mogli przybliżyć
Wewnątrz niego dynamicznie przy pomocy JSa,
będziemy tworzyli diva
o klasie "magnifier",
który będzie symbolizował nam właśnie lupę,
no i obok samego diva o klasie "photo",
utworzymy sobie nasze przybliżone
zdjęcie
Więc tak będzie wyglądał markup,
część jego będziemy tworzyli dynamicznie, więc nadajmy podstawowe stylowanie
temu naszemu markupowi
Nasz divo klasie "photo" będzie miał
szerokość 400px
oraz wysokość 400px
Ustawimy mu background-image na taki,
jaki chcielibyśmy aby nasze zdjęcie posiadało
'photo.jpg'
oraz ustawimy background-size na 400px
Wypozycjonujemy go relatywnie,
bo to się nam przyda do naszej lupy
i ostylujmy naszego "magnifier"
czyli tak naprawdę tą naszą lupę
Ustawimy żeby miała ona połowę wysokości rodzica,
ustawimy to już w pikselach - niech będzie
Border ustawimy na 1px o kolorze srebrnym,
wypozycjonujemy to absolutnie względem rodzica,
ustawimy początkową pozycję na lewy górny róg,
box-sizing ustawimy na border-box,
tak aby ten border był wliczony w tą szerokość 200px i wysokość
Możemy nadać analogiczny kolor #c9c9c9 jako tło
i zmniejszymy mu trochę opacity, powiedzmy na połowę
Ten element będzie nam się przesuwał w momencie kiedy będziemy przesuwali myszkę
i tak naprawdę kiedy wyjedziemy myszką poza obszar tego zdjęcia,
to on nie będzie widoczny
Ostylujmy jeszcze nasze przybliżone zdjęcie
Również ustawimy mu szerokość na taką samą jak naszemu głównemu zdjęciu czyli 400px,
background-image równiez taki sam,
natomiast background-size ustawimy na 800px
i cała mechanika tego przykładu będzie polegała na tym,
że będziemy przesuwać background-position w momencie,
gdy będziemy ruszali myszką na naszym głównym elemencie "photo"
Ustawimy jeszcze sobie background-repeat na no-repeat
i możemy przejść do pisania logiki naszego programu
Więc na początku pobierzemy sobie to nasze "photo" document.querySelector (.'photo')
Następnie potrzebowalibyśmy zmiennych, w których przechowamy nasze elementy magnifire
Możemy je ustawić domyślnie na null,
no i nasze przybliżone zdjęcie, czyli zoom - również na null
Jak już powiedzieliśmy - chcielibyśmy aby ten magnifire był tworzony w momencie,
kiedy wjedziemy myszką na nasze zdjęcie, więc stwórzmy sobie funkcję createMagnifire
i wewnątrz niej będziemy tworzyli sobie magEl z document.createElement ('div')
Nadamy mu klasę .magnifire
i ustawimy, że nasza globalna zmienna mag,
będzie równa temu magEl
Dodamy sobie jeszcze do naszego 'photo' ten element
Analogicznie powinniśmy stworzyć sobie zmienną usuwającą ten element,
czyli removeMagnifier
i będziemy usuwali z naszego 'photo' removeChild, - ten nasz magElement
Możemy jeszcze sobie to uwarunkować, że jeżeli mag,
to usuńmy oczywiście mag, nie magElement,
ponieważ to była zmienna lokalna, dostępna jedynie w createMagnifier
Więc mając te dwie zmienne możemy przypisać sobie już zdarzenia do naszego photo.adEventListener
i chcielibyśmy, że w momencie kiedy wjedziemy myszką na nasze 'photo',
to chcielibyśmy aby wywołała się funkcja createMagnifier
Analogicznie na 'mouseleave' wywoła nam się removeMagnifier
'mouseenter' i 'mouseleave' zostanie wywołane tylko 1 raz w momencie wjechania na obszar zdjęcia,
bądź jego opuszczenia
Usuńmy sobie tego diva i zobaczmy czy nasz przykład działa - no działa
Jak widzimy dopóki myszka nie znajduje się na obszarze 'photo',
to tego elementu magnifier nie ma,
natomiast po najechaniu myszką on się tutaj pojawia
Poprawmy tylko tutaj wcięcia w naszym markupie
i przejdźmy do dalszej części przykładu
Chcielibyśmy aby po najechaniu myszką,
w momencie kiedy ruszamy myszką po naszym zdjęciu,
to żeby ten magnifier podążał za tą myszką
Więc stwórzmy sobie zmienną onMouseMove,
to będzie funkcja i przypiszmy ją do zdarzenia 'photo' onMouseMove
Oczywiście te funkcje też możemy sobie przenieść do analogicznych funkcji o nazwach onMouseEnter
oraz onMouseLeave, removeMagnifier i wpisujemy onMouseEnter, onMouseLeave
Dzięki temu gdybyśmy chcieli aby więcej zdarzeń,
czy więcej funkcji wywoływało się w momencie tego konkretnego zdarzenia,
to będziemy mogli po prostu dopisać je do odpowiednich funkcji onMouseLeave czy onMouseEnter
Więc jak chcemy tak naprawdę przesuwać tego naszego diva magnifier?
Będziemy robili to na podobnej zasadzie co w naszym materiale Sticky Notes -
adnotacja powinna wam wyskoczyć w prawym górnym rogu ekranu,
więc jeśli chcielibyście wiedzieć dokładnie i szczegółowo jak działa fragment kodu,
który za chwile napiszemy - możecie obejrzeć tamto wideo
Na początku pobierzemy sobie bounding naszego zdjęcia,
to będzie po prostu za pomocą thisa getBoundingClientRect
Następnie dodamy sobie tutaj obiekt zdarzenia jako parametr
i zdefiniujemy zmienne X i Y, gdzie X będzie równe ev.clientX odjąć właśnie photoBounding.left,
czyli tak naprawdę pozycję od lewej strony naszego zdjęcia
Obliczamy w tym momencie relatywną pozycję myszki względem naszego 'photo'
Analogicznie utworzymy sobie zmienną Y ev.clientY minus photoBounding.top,
Zapiszemy sobie również photoSize,
wykorzystamy do tego window.getComputedStyle
i podamy jako parametr właśnie nasze 'photo',
moglibyśmy tutaj też wykorzystać naszą zmienną 'photo',
odwołamy się do parametru height
i to nam zwróci sumaryczną wartość faktyczną w przeglądarce tego elementu,
jaką on ma wysokość, natomiast będzie to wartość w pikselach,
dlatego wykorzystamy sobie do tego parseInt aby przekonwertować sobie to na inta,
na liczbę całkowitą
Analogicznie pobierzemy sobie magSize,
mag - tak naprawdę moglibyśmy tutaj dać warunek,
aby sprawdzać czy ten mag na pewno istnieje,
natomiast zdarzenie mouseEnter wywoła się pierwsze niż mouseMove,
więc w sumie moglibyśmy to pominąć
Sam element magnifier będziemy przesuwali za pomocą translate'ów,
więc tworzymy sobie transformCSSValues
i chcielibyśmy aby w osi Y nasz div został przesunięty w momencie ruszania myszką o wartość X -
oczywiście będziemy musieli jeszcze parę rzeczy tutaj ustawić,
no i aby w osi Y przesunęło się o wartość Y pikseli
To będziemy przypisywali do naszego mag,
ustawiali transform na właśnie transformCSSValues
No i jak widzimy, nasz magnifier ma swoją pozycję startową w tamtym miejscu,
gdzie mamy kursor
My docelowo chcielibyśmy aby ten kursor znajdował się możliwie jak najbardziej na środku tej lupy,
więc musimy zrobić troszkę obliczeń
Jako, że znamy szerokość i wysokość naszego obiektu magnifier
(zakładamy oczywiście, że one są równe)
możemy tę naszą wartość X, Y pomniejszyć o połowę wielkości tego elementu,
dzięki temu pozycja naszego obiektu (w momencie przesuwania myszką) będzie na środku
No oczywiście w momencie kiedy zbliżymy się za bardzo do krawędzi,
to niestety ten nasz obiekt magnifier - on nam wychodzi poza to nasze zdjęcie,
więc chcielibyśmy zrobić, że jeżeli zbliżamy się już do krawędzi,
to myszka może się ruszać dalej w kierunku krawędzi,
natomiast sam obiekt magnifier zostanie w tej samej pozycji
Tutaj musimy zrobić kilka warunków,
czyli sprawdźmy sobie najpierw czy X wyszedł poza zakres
Dodamy sobie całą szerokość obiektu magnifier
i sprawdzimy czy jest większa od całego photoSize -
jeśli tak, to chcielibyśmy aby X równało się photoSize minus magSize,
czyli było najbardziej jak to możliwe przesunięte w tej osi do krawędzi
Zobaczmy efekt - jak widzimy, gdy zbliżamy się do prawej krawędzi,
to już poza nią nie wyjdziemy
No i oczywiście w momencie, gdy opuścimy nasze 'photo',
to ten element nam zniknie,
więc tak naprawdę musimy jeszcze zrobić tylko analogiczne warunki dla pozostałych krawędzi
i poruszanie naszą lupą będzie zakończone
To photoSize i magSize możemy sobie zamknąć w zmiennej, bo to się nam przyda
Nazwijmy to sobie MAX_POSITION np.
No i chcielibyśmy aby X równa się MAX_POSITION,
jeśli Y plus magSize jest większy niż photoSize,
to Y równa się MAX_POSITION,
no i jeśli X jest mniejsze od zera,
czyli tak naprawdę z lewej strony wychodzi nam poza zakres,
to chcielibyśmy je po prostu wyzerować analogicznie wyzerujemy też wartość Y
Zobaczmy efekt - no jak widzimy, przy poruszaniu naszą myszką po tym obszarze,
nie możemy już wysunąć tego obiektu poza nasze 'photo'
No oczywiście nasza lupę możemy już poruszać, natomiast zdjęcie po prawej,
które jest tym przybliżonym zdjęciem, ono się nam nie przesuwa analogicznie do tego,
gdzie wskazujemy naszym kursorem
Więc zanim dopiszemy tutaj sobie odpowiedni fragment kodu,
aby to zrealizować, to może sprawmy aby ten podgląd przybliżony był widoczny tylko w momencie,
kiedy najechaliśmy na nasze zdjęcie,
więc usuniemy sobie z naszego markupu naszego diva o klasie "zoom"
i stworzymy sobie funkcję createZoomedPhoto np.
Ustawimy, że wyżej zdefiniowany zoom to będzie nowy div o klasie zoom
i dodamy go sobie od razu do naszego body
Analogicznie stworzymy sobie var removeZoomedPhoto,
to będzie funkcja i sprawdzamy - jeśli zoom,
to document.body.removeChild(zoom),
no i wyzerujmy sobie tego zoom do nulla
Tutaj też oczywiście musimy sobie nasze mag wyzerować do nulla
Tak naprawdę te createZoomedPhoto i removeZoomedPhoto,
możemy dodać oczywiście do naszych funkcji mouseEnter i mouseLeave -
createZoomedPhoto oraz removeZoomedPhoto
No i zapisujemy, zobaczmy co się stanie,
kiedy poruszamy się po naszym zdjęciu, to jego przybliżony ekwiwalent też jest już widoczny,
więc pozostało nam tylko zmieniać background position na naszym przybliżonym zdjęciu,
w zależności od tego gdzie znajdujemy się myszką na naszym głównym divie 'photo'
Więc w naszym onMouseMove damy sobie taką linijkę,
że zoom.style.backgroundPosition
i tutaj podamy sobie X pomnożonego razy 2,
jako że nasz backgroundSize jest większy na tym elemencie dwukrotnie,
czyli tak naprawdę mamy skalę 2 w stosunku do naszego oryginalnego 'photo'
No i oczywiście dopisujemy pikseli oraz Y razy 2px
No oczywiście musimy sobie tu wstawić spację,
ponieważ tutaj załóżmy, że byłoby 100px aby wskazać pozycję Y,
to musimy podać spację i dopiero kolejne - załóżmy 100px
Zapisujemy, sprawdzamy, no i jak widzimy - to nie do końca działa tak jakbyśmy się tego spodziewali,
ponieważ background position ma w pewnym sensie odwróconą oś,
można powiedzieć - musimy po prostu wstawić sobie tutaj minusiki
i jak widzimy, nasze zdjęcie przybliża się tam, gdzie poruszamy naszą myszką
Możemy jeszcze szybciutko dodać na naszym 'photo' jakiś margin-right,
załóżmy 20px i jak widzimy, możemy sobie przybliżać nasze zdjęcia
To jest zdjęcie Damiana z tegorocznych Warszawskich Dni Informatyki,
dajcie znać czy byliście na tym wydarzeniu i jak widzimy -
stworzenie takiego przykładu jest koncepcyjnie bardzo proste,
nie wymaga też wiele wysiłku, jeśli chodzi o implementację,
oczywiście ten przykład moglibyśmy dalej rozszerzać, np. dodając możliwość podglądania innych zdjęć,
czy tak naprawdę sprawianie, aby ten kod był bardziej uniwersalny
Jeżeli będziecie zainteresowani takim zagadnieniem, koniecznie dajcie nam znać w komentarzu
Jeszcze jedna ważna informacja
Niedawno ruszyliśmy ze sklepem internetowym, gdzie możecie zakupić przeprowadzone przez nas Webinary
Możecie odwiedzić go klikając w odnośnik widoczny po lewej stronie ekranu
Trzymajcie się i do zobaczenia wkrótce
[ blooper ]
No cóż... można powiedzieć, że było to od zawsze :)
Nie mam nic do ukrycia! Eksperymentuj z moimi przykładami :)
Cześć! Nazywam się Wojciech Połowniak i jestem programistą Fullstack z zacięciem do tworzenia jakościowych materiałów szkoleniowych.
Uwielbiam automatyzację, VR oraz interaktywne sposoby przekazywania wiedzy. Tematy takie jak UX, dostępność czy devops również nie są mi obce.
Jestem też organizatorem meet.js oraz Techspeakerem pod banderą Mozilli... A to jeszcze nie wszystko.
Na wyciągnięcie ręki. Za darmo, na YouTube
W tym wideo dowiesz się jak wykorzystać zaawansowane selektory CSS aby stworzyć dostępny system oceny gwiazdkami.
Zobacz jak stworzyć wykresy kołowe bez grama JavaScriptu czy preprocesorów CSS
SVG to świetny format grafik wektorowych. Zobacz co się stanie, gdy dodamy animacje!
W tym wideo opowiem Ci czym są i jak działają pseudoelementy.
W tym wideo tworzymy animowaną kostkę 3D, stworzoną w samym CSS.
W tym wideo przedstawię Ci najważniejsze aspekty właściwości position.
Jeśli chcesz być na bieżąco z najnowszymi inicjatywami od twórców koduje? Zapisz się na newsletter - nie spamujemy!
W przyszłości, możemy udostępnić Ci informacje o dodatkowych kursach naszego autorstwa.
Komentarz od autora
Myślę, że dalej jest to solidny materiał - pomimo tego, że unikałem wtedy ES6 (aby nie wdrażać "nowości" i skupić się na przykładzie), jednak umówmy się - jest już 2022 i ES6+ to w dzisiejszych czasach - po prostu JavaScript, wspierany we wszystkich istotnych przeglądarkach.
Gdybym robił ten materiał dzisiaj, zdecydowanie korzystałbym z dobrodziejstw nowej składni języka - template strings, let / const, arrow functions... Czy chociażby deklarowanie zmiennych na osobnych liniach - bez wymieniania ich po przecinku.