Vartannat vecka tar vi ett ultrafokuserat utseende på en intressant och användbar effekt, plugin, hack, bibliotek eller till och med en snygg teknik. Vi försöker sedan antingen dekonstruera koden eller skapa ett roligt litet projekt med det.
Idag ska vi titta på ett plugin som implementerar en ganska snygg effekt - det är ganska svårt att förklara i en mening så att du också kan klicka på fortsättsknappen för att komma igång efter hoppet.
Som webbutvecklare har vi tillgång till en svimlande mängd förbyggd kod, vare sig det är ett litet fragment eller en fullsträckt ram. Om du inte gör något oerhört specifikt, är chansen att det redan finns något förbyggt för att du ska kunna utnyttja. Tyvärr försvinner många av dessa stellära erbjudanden i anonymitet, speciellt för de icke-hardcore publiken.
Denna serie syftar till att åtgärda problemet genom att införa en riktigt välskriven, användbar kod - vare sig det är en plugin, effekt eller en teknik för läsaren. Vidare, om det är tillräckligt liten, försöker vi dekonstruera koden och förstå hur den gör det voodoo. Om det är mycket större, försöker vi skapa ett mini-projekt med det för att lära sig repen och förhoppningsvis förstå hur använda det i den verkliga världen.
Här är några snabba info:
I många fall behöver du innehållet att flyta när du bläddrar, men bara inom sin förälder.
Flytande innehåll som en användare rullar igenom resten av sidan är barnspel. Ingen JavaScript krävs - du kan göra det med bara vanlig gammal CSS. Slap a position: fast
deklaration på det och boom!, du har en behållare som är fixad i en viss plats på sidan - den är flytande på sidan för att vara mer vardaglig.
Men låt oss möta det, det fungerar inte med alla layouter. Du kan planera lite framåt och placera den på sidan så att den aldrig skulle störa viktiga delar men det skulle inte heller vara helt idiotsäker eller återanvända någon annanstans utan omfattande förändringar.
I dessa fall behöver du innehållet att flyta när du bläddrar, men bara inom sin förälder.. Om du undrar, ja, den här funktionen är en variation av den som Andrew visade dig i förra veckans handledning, vilket är hur jag fick veta om det här pluginet.
Som du hittar i webbutveckling, precis som multivariabel kalkyl, finns det ofta ett antal lösningar på ett visst problem. Låt oss titta på en av de alternativa lösningarna.
Den allmänna logiken eller arbetsflödet i pluggen är faktiskt ganska enkelt. Låt mig visa dig. Tänk på att jag ska referera till det element som behöver flödas som klibbig från och med nu.
Men innan vi börjar, här är en snabb mockup för att visa hierarkin:
Hela logiken i plugin kan vattnas ner till:
Om du är förvirrad, var inte. Låt oss exempelvis titta på några provnummer:
Så baserat på ovanstående information kan du härleda det
I scenario ett - den klibbiga bör återflödes på lämpligt sätt. Varför? Sidan har blivit rullad 10px från toppen - 10 kommer från själva sidan medan resten kommer från den klibbiga föräldern. Således är föräldern synlig i huvudvyporten.
I scenario två - den klibbiga kan lämnas ensam. Av 150px kommer 10 från sidan, 100 från moderelementet och resten tas upp av resten av sidans element. Detta innebär att användaren har rullat förbi föräldern och vi behöver inte göra någonting.
Om du fortfarande är fuzzy vid denna tidpunkt, oroa dig inte. Jag förklarar lite mer när jag går igenom källan.
Källan avskriven av kommentarer är bara en smidgen över 30 linjer lång. Som alltid går vi igenom koden och förklarar vad varje rad gör.
Här är källan, för din referens.
$ .fn.stickyfloat = funktion (alternativ, lockBottom) var $ obj = this; var parentPaddingTop = parseInt ($ obj.parent (). css ('padding-top')); var startOffset = $ obj.parent (). offset (). topp; var opts = $ .extend (startOffset: startOffset, offsetY: parentPaddingTop, duration: 200, lockBottom: true, options); $ obj.css (position: 'absolute'); om (opts.lockBottom) var bottomPos = $ obj.parent () .höjd () - $ obj.height () + parentPaddingTop; om (bottomPos < 0 ) bottomPos = 0; $(window).scroll(function () $obj.stop(); var pastStartOffset = $(document).scrollTop() > opts.startOffset; var objFartherThanTopPos = $ obj.offset (). top> startOffset; var objBiggerThanWindow = $ obj.outerHeight () < $(window).height(); if( (pastStartOffset || objFartherThanTopPos) && objBiggerThanWindow ) var newpos = ($(document).scrollTop() -startOffset + opts.offsetY ); if ( newpos > bottomPos) newpos = bottomPos; om ($ (dokument) .scrollTop () < opts.startOffset ) newpos = parentPaddingTop; $obj.animate( top: newpos , opts.duration ); ); ;
Tiden att se vad det egentligen gör. Jag antar, du har en ganska grundläggande grepp om JavaScript.
$ .fn.stickyfloat = funktion (alternativ, lockBottom) ;
Steg 1 - Den generiska omslaget för ett jQuery-plugin. Som du säkert vet, alternativ
är ett objekt som innehåller olika alternativ för att konfigurera pluginets beteende. lockBottom
, intressant, specificerar om funktionaliteten vi vill är på eller inte. Vi lämnar den på.
var $ obj = this;
Steg 2 - Håll en hänvisning till det godkända elementet. I detta sammanhang, detta
pekar på DOM-elementet som matchar väljaren du har skickat in. Till exempel, om du passerade in #meny
, detta
pekar på elementet med det ID-numret.
var parentPaddingTop = parseInt ($ obj.parent (). css ('padding-top'));
Steg 3 - Detta är bara för att släpa ut effekten är moderelementet har en stor polstring. Om så är fallet kommer detta att inkludera vaddering i beräkningen.
var startOffset = $ obj.parent (). offset (). topp;
Steg 4 - Vi beräknar förälderns position i förhållande till dokumentet med hjälp av offset
jQuery-metoden. Vi arbetar genom DOM med hjälp av förälder
metod. Vi $ obj
eftersom vi redan har cachat det klibbiga. Hämta dokumentationen för jQuery API om du inte är bekant med dessa metoder.
I det här fallet är avståndet från toppen tillräckligt så att vi får det värdet ensamt.
var opts = $ .extend (startOffset: startOffset, offsetY: parentPaddingTop, duration: 200, lockBottom: true, options);
Steg 5 - En ganska generisk del av jQuery-pluginutvecklingsprocessen. Vi sammanfogar i huvudsak de överförda alternativen tillsammans med några förinställningar för att få en slutlig uppsättning alternativ som används i hela koden. Tänk på att de överförda parametrarna alltid har företräde framför standardinställningarna.
$ obj.css (position: 'absolute');
Steg 6 - Effekten i fråga kommer att skapas genom att manipulera elementets topp
CSS-värde så kommer vi bara fortsätta och sätta sin position till absolut om den inte redan har ställts in på det sättet.
om (opts.lockBottom) var bottomPos = $ obj.parent () .höjd () - $ obj.height () + parentPaddingTop; om (bottomPos < 0 ) bottomPos = 0;
Steg 7 - Som noterats ovan lockBottom
alternativet anger om den aktuella effekten fungerar eller inte. Om det är aktiverat kan vi börja beräkna. Vad vi beräknar är cutoff-punkten bortom vilket vi inte skulle behöva omplacera den klibbiga.
Naturligtvis kan du gå genom att bara beräkna förälderns höjd men effekten blir oraffinerad. Du måste ta hänsyn till höjden på den klibbiga sig längs någon paddings på föräldern själv.
$ (fönster) .scroll (funktion () // Massor av kod)
Steg 8 - Vi kopplar vår kod, inuti en anonym funktion, till Windows ' skrolla
händelse. Beviljas, det här är inte det effektivaste sättet att gå vidare, men vi ignorerar det för tillfället.
$ Obj.stop ();
Steg 9 - Första ordningsföljden är att stoppa alla löpande animationer på det klibbiga elementet. De sluta
Metoden tar hand om detta.
var pastStartOffset = $ (dokument) .scrollTop ()> opts.startOffset; var objFartherThanTopPos = $ obj.offset (). top> startOffset; var objBiggerThanWindow = $ obj.outerHeight () < $(window).height();
Steg 10 - Dessa tre variabler innehåller värden som vi kommer att använda lite senare.
pastStartOffset
kontrollerar om vi har rullat över den översta gränsen för moderelementet. Kom ihåg att vi använde offset
metod för att ta reda på mellanrummet mellan moderelementet och dokumentet. Vi får hur långt ner du har rullat med scrollTop
metod. Detta är avståndet mellan dokumentets övre del och toppen av det aktuella visningsporten. objFartherThanTopPos
kontrollerar om den klibbiga är i sin standardposition - högst upp i sin förälder. Om vi har rullat bortom topp
av föräldern, vi vill inte att den svävar ute.objBiggerThanWindow
kontrollerar huruvida den totala höjden på den klibbiga är större än storleken på fönstret. Om så är fallet är det ingen mening att manipulera det klibbiga elementet. om ((pastStartOffset || objFartherThanTopPos) && objBiggerThanWindow) // Mer kod
Steg 11 - Det här är där plugin beräknar om vi behöver manipulera det klibbiga elementet. Vad ovanstående rad gör det:
Vi fortsätter endast om både av dessa villkor är uppfyllda.
var newpos = ($ (dokument) .scrollTop () -startOffset + opts.offsetY);
Steg 12 - Denna rad definierar en variabel, newpos
, som anger vilken position det klibbiga elementet måste animeras till. Som du kanske märkte är beräkningen ganska grundläggande om du tänker på bilden ovan. Ta reda på det rullade avståndet, lägg till förälderens toppadding och slutligen dra avståndet mellan dokumentet och föräldern - utgångspunkten. Detta ger dig avståndet, i pixlar, mellan överdelen av moderelementet till punkten inuti, där den klibbiga ska placeras.
om (newpos> bottomPos) newpos = bottomPos;
Steg 13 - Om vi har rullat bortom grundelementets nedre gräns behöver du inte manipulera saker. Lås dess position där.
om ($ (dokument) .scrollTop () < opts.startOffset ) newpos = parentPaddingTop;
Steg 14 - Om vi har rullat över den översta gränsen för föräldern, håll den låst där så att den inte rör sig längre upp.
$ obj.animate (top: newpos, opts.duration);
Steg 15 - Klart! Vi animerar helt enkelt det klibbiga elementet som passerar i erforderligt topp
värde tillsammans med effektens varaktighet med hjälp av animera
jQuery-metoden.
Som du kanske har antagit vid denna tidpunkt är användningen som sådan:
$ ('# meny'). stickyfloat (duration: 500);>
I stället för att förklara provminimprojektet, precis som förra gången, har jag istället bestämt mig för att bara bygga den och ge dig koden.
Här är de relevanta delarna av demo, resten är panna:
Klibbig menyJag ville skriva något oerhört, orubbligt vittigt här. Jag misslyckades. :(Ja, jag följer dig överallt så länge du är inom min förälderDu förväntade dig något smart här, eller hur? Jag vet att du gjorde! Fess upp!
.avsnitt vaddering: 10px; bredd: 900px; marginal: 0 auto; background-color: # f1f1f1; positioner: relativ; .snitt.innehåll höjd: 800px; bakgrundsfärg: #ddd; margin-left: 250px; text-align: center; color: # 333; font-size: 16px; .sektion .menu position: absolut; vänster: 10px; bredd: 240 pixlar; höjd: 100px; bakgrund: # 06C; text-align: center; färg: #fff; font-size: 14px;
$ ('# meny'). stickyfloat (duration: 400); $ ('# menu2'). stickyfloat (duration: 400);
Om du går igenom filerna som du läser den här artikeln borde det vara ganska självförklarande men du är mer än välkommen att träffa mig med frågor om någon del är oklart.
Och vi är klara. Vi kollade på ett otroligt användbart plugin, gick igenom källkoden och slutligen avslutade genom att skapa ett mini-projekt med det.
Frågor? Trevliga saker att säga? Kritik? Klicka på kommentarfältet och lämna mig en kommentar. Tack så mycket för att läsa!