În fiecare săptămână, vom analiza cu atenție un aspect interesant și util, plugin, hack, bibliotecă sau chiar o tehnologie minunată. Vom încerca apoi fie să deconstruăm codul, fie să creăm un mic proiect distractiv.
Astăzi, vom analiza un plugin care implementează un efect destul de curat - este destul de greu de explicat într-o propoziție, astfel încât să puteți da click pe butonul Continuă pentru a începe după salt.
În calitate de dezvoltatori web, avem acces la o sumă uimitoare de cod pre-construit, fie că este vorba de un fragment mic sau de un cadru complet. Dacă nu faci ceva incredibil de specific, există șanse, există deja ceva preconfirmat pentru a vă folosi. Din nefericire, multe dintre aceste oferte stelare se distrug în anonimitate, în special pentru mulțimea non-hardcore.
Această serie urmărește să remedieze această problemă introducând un cod cu adevărat bine scris și util - fie un plugin, un efect sau o tehnologie pentru cititor. Mai mult, dacă este suficient de mic, vom încerca să deconstruăm codul și să înțelegem cum o face voodoo. Dacă este mult mai mare, vom încerca să creăm un mini-proiect cu el pentru a învăța funiile și, sperăm, să înțelegem cum îl folosim în lumea reală.
Iată câteva informații rapide:
În multe cazuri, aveți nevoie ca conținutul să plutească pe măsură ce defilați, dar numai în cadrul părintelui.
Conținutul plutitor, pe măsură ce un utilizator trece prin restul paginii, este copilul. Nu este necesar JavaScript - poți să o faci doar cu CSS vechi simplu. Slap a pozitie: fixa
declarație și boom !, aveți un container care este fixat într-o anumită locație din pagină - plutește în pagină pentru a fi mai vorbitor.
Dar haideți să facem față, nu funcționează cu fiecare aspect. Ați putea să vă planificați un pic înainte și să o poziționați pe pagină, astfel încât să nu intervină niciodată cu elemente importante, dar nu ar fi complet protejat și nici reutilizabil în altă parte fără schimbări extinse.
În aceste cazuri, aveți nevoie ca conținutul să plutească pe măsură ce defilați, dar numai în cadrul părintelui.. Dacă vă întrebați, da, această funcționalitate este o variantă a celei pe care Andrew ți-a arătat-o în tutorialul din săptămâna trecută, așa cum am aflat despre acest plugin.
Așa cum veți găsi în dezvoltarea web-ului, la fel ca și calculul multivariabil, există adesea o serie de soluții pentru orice problemă dată. Să ne uităm la una dintre acele soluții alternative.
Logica generală sau fluxul de lucru al conectorului sunt de fapt destul de simple. Lasa-ma sa-ti arat. Rețineți că mă voi referi la elementul care trebuie să fie plutind ca lipicios de-acum inainte.
Dar înainte de a începe, iată un mockup rapid pentru a arăta ierarhia:
Întreaga logică a pluginului poate fi udată până la:
Dacă ești confuz, nu fi. De exemplu, să examinăm câteva exemple de numere:
Deci, pe baza acestor informații de mai sus, puteți deduce acest lucru
În scenariul unu - lipicioasa ar trebui repetată corespunzător. De ce? Pagina a fost derulată 10px din partea de sus - 10 provine de la pagina în sine, în timp ce restul provine de la părintele lipicios. Astfel, părintele este vizibil în fereastra principală.
În scenariul doi - lipicioasa poate fi lăsată singură. Din cele 150 de pixeli, 10 provin de la pagină, 100 de elemente elementare, iar restul sunt preluate de restul elementului paginii. Aceasta implică faptul că utilizatorul a trecut prin părinte și nu trebuie să facem nimic.
Dacă încă nu sunteți îngrozit în acest moment, nu vă faceți griji. Voi explica un pic mai mult în timp ce mergeți prin sursă.
Sursa dezbrăcat de comentarii este doar un smidgen peste 30 de linii lungime. Ca întotdeauna, vom trece prin cod și vom explica ceea ce face fiecare linie.
Iată sursa, pentru referință.
$ .fn.stickyfloat = funcția (opțiuni, lockBottom) var $ obj = this; var părintePaddingTop = parseInt ($ obj.parent (). css ("padding-top")); var startOffset = $ obj.parent () offset () top; var opts = $ .extend (startOffset: startOffset, offsetY: parentPaddingTop, durata: 200, lockBottom: true, opțiuni); $ obj.css (poziție: 'absolut'); dacă (opts.lockBottom) var bottomPos = $ obj.parent () .înălțime () - $ obj.height () + parentPaddingTop; dacă (bottomPos < 0 ) bottomPos = 0; $(window).scroll(function () $obj.stop(); var pastStartOffset = $(document).scrollTop() > opts.startOffset; var objFartherThanTopPos = $ obj.offset () sus> startOffset; var objBiggerThanWindow = $ obj.outerHeight () < $(window).height(); if( (pastStartOffset || objFartherThanTopPos) && objBiggerThanWindow ) var newpos = ($(document).scrollTop() -startOffset + opts.offsetY ); if ( newpos > bottomPos) newpos = bottomPos; dacă ($ (document) .scrollTop () < opts.startOffset ) newpos = parentPaddingTop; $obj.animate( top: newpos , opts.duration ); ); ;
E timpul să vedem ce face de fapt. O să presupun că aveți o bază destul de simplă a JavaScript-ului.
$ .fn.stickyfloat = funcție (opțiuni, lockBottom) ;
Pasul 1 - Inventatorul generic pentru un plugin jQuery. După cum probabil știți, Opțiuni
este un obiect care conține opțiuni asortate pentru a configura comportamentul pluginului. lockBottom
, interesant, specifică dacă funcționalitatea pe care o dorim este activată sau nu. O vom lăsa pe loc.
var $ obj = aceasta;
Pasul 2 - Mențineți o referință la elementul trecut. În acest context, acest
indică elementul DOM care se potrivește cu selectorul în care ați trecut. De exemplu, dacă ați trecut #meniul
, acest
indică elementul cu ID-ul respectiv.
var părintePaddingTop = parseInt ($ obj.parent (). css ("padding-top"));
Pasul 3 - Acest lucru este doar pentru a netezi efectul este elementul părinte are un padding mare. În caz afirmativ, acest lucru va include în calcul calculația.
var startOffset = $ obj.parent () offset () top;
Pasul 4 - Calculam poziția părintelui față de document folosind ofset
metoda jQuery. Lucrăm prin DOM folosind mamă
metodă. Noi $ obj
deoarece deja am cache-ul lipicios. Apăsați documentația API jQuery dacă nu sunteți familiarizat cu aceste metode.
În acest caz, distanța de la vârf este suficientă, astfel încât vom obține acea valoare singură.
var opts = $ .extend (startOffset: startOffset, offsetY: parentPaddingTop, durata: 200, lockBottom: true, opțiuni);
Pasul 5 - O porțiune destul de generică a procesului de dezvoltare a pluginului jQuery. În mod esențial, fuzionăm în opțiunile trecute împreună cu unele presetări pentru a obține un set final de opțiuni care este utilizat în întregul cod. Rețineți că parametrii trecuți au întotdeauna prioritate față de valorile implicite.
$ obj.css (poziție: 'absolut');
Pasul 6 - Efectul în cauză va fi creat prin manipularea elementului top
Valoarea CSS, așa că vom merge mai departe și vom stabili poziția sa absolută în cazul în care nu a fost deja stabilită în acest mod.
dacă (opts.lockBottom) var bottomPos = $ obj.parent () .înălțime () - $ obj.height () + parentPaddingTop; dacă (bottomPos < 0 ) bottomPos = 0;
Pasul 7 - După cum sa menționat mai sus, lockBottom
opțiunea specifică dacă efectul în cauză funcționează sau nu. Dacă este activată, putem începe calculul. Ceea ce calculam este punctul de delimitare dincolo de care nu ar fi nevoie să repoziționăm lipicioasa.
Firește, puteți trece prin calcularea înălțimii părintelui, dar efectul va fi nerăbdător. Veți avea nevoie să țineți cont de înălțimea lipicioasă însăși de-a lungul oricăror plăcuțe pe părintele însuși.
$ (fereastră) .scroll (funcție () // Lot de cod
Pasul 8 - Ne-am legat codul, într-o funcție anonimă, sul
eveniment. Acordat, acest lucru nu este cel mai eficient mod de a continua, dar o vom ignora deocamdată.
$ Obj.stop ();
Pasul 9 - Prima ordine a cuvântului este de a opri toate animațiile care rulează pe elementul lipicios. Stop
metoda se ocupă de acest lucru.
var pastStartOffset = $ (document) .scrollTop ()> opts.startOffset; var objFartherThanTopPos = $ obj.offset () sus> startOffset; var objBiggerThanWindow = $ obj.outerHeight () < $(window).height();
Pasul 10 - Aceste trei variabile dețin valori pe care le vom folosi puțin mai târziu.
pastStartOffset
verifică dacă am trecut prin limita superioară a elementului părinte. Amintiți-vă, am folosit ofset
pentru a afla spațiul dintre elementul părinte și document. ObŃinem cât de departe te-ai derulat folosind scrollTop
metodă. Aceasta este distanța dintre partea de sus a documentului și partea superioară a ferestrei de vizualizare curente. objFartherThanTopPos
verifică dacă lipicioasa se află în poziția implicită - în partea superioară a părintelui. Dacă am derulat dincolo de top
a părintelui, nu vrem să plutească afară.objBiggerThanWindow
verifică dacă înălțimea totală a lipiciului este mai mare decât dimensiunea ferestrei. Dacă este așa, nu are rost să manipulezi elementul lipicios. dacă ((trecutStartOffset || objFartherThanTopPos) && objBiggerThanWindow) // Mai mult cod
Pasul 11 - Aici pluginul calculează dacă va trebui să manipulăm elementul lipicios. Ce face linia de mai sus:
Procedăm numai dacă ambii din aceste condiții sunt îndeplinite.
var newpos = ($ (document) .scrollTop () -startOffset + opts.offsetY);
Pasul 12 - Această linie definește o variabilă, et NewPos
, care specifică poziția la care trebuie animat elementul lipicios. După cum ați observat, calculul este destul de fundamental dacă țineți cont de imaginea de mai sus. Aflați distanța derulată, adăugați suprapunerea părintelui la ea și, în final, scădeți distanța dintre document și părinte - punctul de pornire. Acest lucru vă oferă distanța, în pixeli, între partea superioară a elementului părinte și punctul din interior, în cazul în care lipiciosul trebuie poziționat.
dacă (newpos> bottomPos) newpos = bottomPos;
Pasul 13 - Dacă am derulat dincolo de limita inferioară a elementului părinte, nu este nevoie să manipulăm în continuare lucrurile. Blocați poziția sa acolo.
dacă ($ (document) .scrollTop () < opts.startOffset ) newpos = parentPaddingTop;
Pasul 14 - Dacă am derulat deasupra limitei superioare a părintelui, păstrați-l blocat acolo, astfel încât să nu se miște mai sus.
$ obj.animate (top: newpos, opts.duration);
Pasul 15 - Totul este gata! Pur și simplu animăm elementul lipicios care trece prin cerințele necesare top
valoare, împreună cu durata efectului folosind anima
metoda jQuery.
Așa cum ați putea probabil deduce în acest moment, utilizarea este așa:
$ ("meniu"). stickyfloat (duration: 500);>
În loc să explicăm exemplul mini-proiectului, ca și ultima oară, am decis în schimb să construiesc și să vă dau codul.
Iată părțile relevante ale demo-ului, restul este boilerplate:
Meniul lipiciosAm vrut să scriu ceva incredibil, nemaivăresc de aici. Am esuat. :(Da, te voi urmări oriunde ai fi în părintele meuAi așteptat ceva deștept aici, nu-i așa? Știu că ai făcut-o! Fess sus!
.secțiune padding: 10px; lățime: 900px; marja: 0 auto; background-color: # f1f1f1; Poziția: relativă; .secția .content height: 800px; culoare de fundal: #ddd; margin-left: 250px; text-align: center; Culoare: # 333; font-size: 16px; .secție .menu poziție: absolută; stânga: 10px; lățime: 240 de pixeli; height: 100px; fundal: # 06C; text-align: center; Culoare: #fff; font-size: 14px;
$ ("meniu"). stickyfloat (duration: 400); $ ('# menu2'). stickyfloat (duration: 400);
Dacă treceți prin fișiere în timp ce citiți acest articol, ar trebui să fie destul de auto-explicativ, dar sunteți mai mult decât binevenit să mă lovești cu întrebări dacă orice parte este neclară.
Și am terminat. Am aruncat o privire la un plugin incredibil de util, am trecut prin codul sursă și, în final, am terminat prin crearea unui proiect miniatural cu acesta.
Întrebări? Ce lucruri frumoase de spus? Critici? Activați secțiunea de comentarii și lasă-mă un comentariu. Vă mulțumesc foarte mult pentru lectură!