Een jQuery-afbeeldingenscroller maken

In deze zelfstudie gaan we een afbeeldingschuif maken, gebruik makend van de uitstekende animatiefuncties van jQuery en over het algemeen plezier hebben met code. Image-scrollers zijn natuurlijk niets nieuws; er komen altijd versies van uit. Velen van hen zijn echter door de gebruiker geïnitieerd; wat inhoudt dat de bezoeker op een knop moet klikken of een andere actie moet uitvoeren om de momenteel weergegeven inhoud te laten wijzigen. Deze schuifregelaar zal anders zijn omdat deze volledig autonoom is en begint te scrollen zodra de pagina wordt geladen.


De voltooide widget is volledig cross-browser en presteert zoals verwacht in de nieuwste versies van alle gangbare browsers. We zullen ook wat interactie opbouwen door besturingselementen toe te voegen waarmee de bezoeker de richting van de animatie kan wijzigen. We werken met alleen jQuery en een beetje HTML en CSS in deze zelfstudie en zouden in staat moeten zijn om de voorbeelden uit te voeren zonder een volledige configuratie van de webserver.


Ermee beginnen

Laten we eerst de onderliggende HTML-pagina maken; voeg op een nieuwe pagina in je teksteditor de volgende code toe:

      imageScroller Beeldcarrousel   
appel Firefox jQuery tjilpen jQuery UI

Bewaar deze als imageScroller.html in een nieuwe map. We linken naar een aangepast stylesheet in de kop van de pagina, die we binnenkort zullen coderen, en we voegen een link naar de gehoste versie van de nieuwste versie van jQuery aan de onderkant van de pagina toe. Het laden van scripts aan het einde van het lichaam is een erkende techniek om de prestaties van uw pagina te verbeteren en moet daarom waar mogelijk worden toegepast.

Onze widget bestaat uit een reeks geneste containers en een stapel afbeeldingen verpakt in links. De afbeeldingen die in de containers zijn geplaatst, zijn om redenen van toegankelijkheid hard op de pagina gecodeerd. We zullen de afbeeldingen niet dynamisch ophalen; alle afbeeldingen die in de widget worden geplaatst, worden automatisch geschoven (mits ze zijn ingepakt in een koppeling met de juiste klassenaam).

De meest buitenste container wordt voornamelijk gebruikt voor positionele en weergavedoeleinden, terwijl de volgende container wordt gebruikt om de widget te verfraaien met een achtergrondafbeelding. De buitenste container is ook nodig om de besturingselementen toe te voegen, zodat ze in IE boven de inhoud verschijnen.

De binnenste container is het element dat wordt gebruikt om de afbeeldingen door te nemen. Dit element krijgt de klasse js-disabled die puur wordt gebruikt voor bezoekers die JavaScript hebben uitgeschakeld. We gebruiken deze klasse om elk van de afbeeldingen te verkleinen met CSS, zodat ze allemaal kunnen worden bekeken.

De afbeeldingen zijn allemaal uniform van formaat en de containers worden op maat gemaakt om ze netjes op te bergen. De afbeeldingsgrootte wordt ook gebruikt in het script dat we zullen toevoegen; Ik zal specifiek aangeven waar deze referenties voorkomen, maar je moet weten dat als je afbeeldingen van een andere grootte wilt gebruiken, het script en de grootte van de containers dienovereenkomstig moeten worden aangepast.


De widget stylen

Na de koppeling naar jQuery hebben we een aangepast scriptelement met jQuery document.ready snelkoppeling, wachtend op ons om de code toe te voegen die de widget tot leven brengt. Voordat we dat echter doen, laten we de CSS snel toevoegen. Voeg in een ander nieuw bestand in uw teksteditor de volgende selectors en stijlregels toe:

 / * js-disabled class - stel de beeldformaten zo in dat ze allemaal in de viewer passen * / .js-disabled img width: 100px; Hoogte: 100px; display: block; float: left; marge: 30 px 0 0;  #outerContainer width: 542px; Hoogte: 202px; margin: auto; position: relative;  #imageScroller width: 542px; Hoogte: 202px; position: relative; achtergrond: # 000000 url (images / imageScrollerBG.png) no-repeat;  #viewer width: 522px; Hoogte: 182px; overloop verborgen; margin: auto; position: relative; top: 10px;  #imageScroller a: active, #imageScroller a: visited color: # 000000;  #imageScroller een img border: 0;  #controls width: 534px; hoogte: 47px; achtergrond: url (images / controlsBG.png) no-repeat; positie: absoluut; top: 4px; left: 4px; z-index: 10;  #controls a width: 37px; hoogte: 35px; positie: absoluut; top: 3px;  #controls a: active, #controls a: visited color: # 0d0d0d;  #title color: #ffffff; font-family: Arial; font-size: 100%; font-weight: bold; Breedte: 100%; text-align: center; margin-top: 10px;  #rtl background: url (images / rtl.png) geen herhaling; left: 100px;  #rtl: hover background: url (images / rtl_over.png) geen herhaling; left: 99px;  #ltr background: url (images / ltr.png) geen herhaling; rechts: 100px;  #ltr: hover background: url (images / ltr_over.png) geen herhaling; 

Als JavaScript is uitgeschakeld en terwijl de pagina wordt geladen, zijn alle afbeeldingen zichtbaar

Bewaar deze als imageScroller.css in dezelfde map als de webpagina. Eerst hebben we de klasse-selector die op ons is gericht js-disabled klasse; met deze regels worden de afbeeldingen eenvoudigweg op maat gemaakt, zodat ze klein genoeg zijn om naast elkaar over de breedte van de widget op te stapelen. Als JavaScript is uitgeschakeld en terwijl de pagina wordt geladen, zijn alle afbeeldingen zichtbaar - een zeer snelle en eenvoudige terugval, maar een die niet noodzakelijkerwijs fool-proof is en zeker niet volledig Progressive Enhancement is. De opgegeven waarden voor de breedte en hoogte moeten variëren afhankelijk van het aantal afbeeldingen in de viewer.

Hierna hebben we de selectors en regels die de widget stylen en deze correct laten werken. Het grootste deel van de code is hier puur voor weergavedoeleinden, achtergrondafbeeldingen, kleuren, enz. Een belangrijke regel, waarop de implementatie vertrouwt om correct te werken, is het instellen van overloop: verborgen in de binnenkijkerhouder. Hiermee worden de afbeeldingen verborgen die nog moeten worden getoond en de afbeeldingen die al door de kijker zijn gepasseerd. In deze fase waarin we de pagina uitvoeren, zouden we zoiets als dit moeten zien:

Een deel van de CSS stellen we in een ogenblik in op het JavaScript en sommige elementen die we in de CSS targeten bestaan ​​nog niet, maar dit is alles dat in het CSS-bestand moet worden opgenomen.


De widget tot leven brengen

In de laatste fase van deze tutorial voegen we JavaScript met jQuery-smaak toe waardoor de widget werkt en het gewenste gedrag creëert. Voeg de volgende code toe in de lege anonieme functie onder aan de HTML-pagina:

 // verwijder js-disabled class $ ("# viewer"). removeClass ("js-disabled"); // maak een nieuwe container voor afbeeldingen $ ("
") .attr (" id "," container "). css (positie:" absoluut "). width ($ (". wrapper "). length * 170) .hoogte (170) .appendTo (" div # viewer "); // afbeeldingen toevoegen aan container $ (". wrapper "). each (function () $ (this) .appendTo (" div # container ");); // werk de duur van de animatie uit op basis van aantal afbeeldingen (1 seconde voor elke afbeelding) var duration = $ (". wrapper"). length * 1000; // opslagsnelheid voor latere var-snelheid = (parseInt ($ ("div # container"). width ()) + parseInt ($ ("div # viewer"). width ())) / duration; // richtingsrichting var direction = "rtl"; // stel beginpositie en klasse in op basis van richting (richting == "rtl")? $ ("div # container"). css ("left", $ ("div # viewer"). width ()). addClass ("rtl"): $ ("div # container"). css ("left") , 0 - $ ("div # container"). Width ()). AddClass ("ltr");

Eerst en vooral verwijderen we de klasse js-disabled uit de viewercontainer. Vervolgens maken we een nieuwe container voor alle afbeeldingen die in de widget worden gevonden. De belangrijkste reden hiervoor is dat in plaats van elke afbeelding afzonderlijk te animeren, wat resulteert in een potentieel groot aantal gelijktijdig uitgevoerde animaties, we slechts één element hoeven animeren - de container die we nu maken.

De breedte van de nieuwe container wordt ingesteld op het aantal afbeeldingen vermenigvuldigd met de breedte van elke afbeelding, in dit voorbeeld is dit 170 pixels. Dit is een van de stukjes code die ik eerder heb genoemd, en die iets moet worden gewijzigd als we besluiten afbeeldingen van een andere grootte te gebruiken. De hoogte van de container is ook specifiek ingesteld op de hoogte van elk beeld.

Het is handig om later in het script bepaalde dingen te weten over de aard van de animatie, zoals de snelheid, de duur ervan en de reisrichting, dus hebben we vervolgens een reeks variabelen ingesteld om deze informatie in op te slaan. de duur is exact gelijk aan één seconde per afbeelding en is opnieuw gebaseerd op het aantal afbeeldingen in de widget.

De snelheid is gemakkelijk uit te werken, uiteraard de afstand van de reis gedeeld door de duur van de reis. Ter referentie: in dit voorbeeld is de exacte snelheid van de animatie 0,274 pixels per milliseconde. De laatste variabele, richting, is een eenvoudige string die aangeeft dat de animatie van rechts naar links zal gaan, hoewel we dit gemakkelijk naar ltr kunnen veranderen als we dat zouden willen.

Ten slotte stellen we de startpositie van de nieuwe container in; omdat de animatie momenteel is ingesteld op rtl, moeten we de nieuwe afbeeldingscontainer zo plaatsen dat de linkerrand ervan zich aan de rechterrand van de viewer bevindt. Als we de animatie echter op ltr instellen, wordt de rechterkant van het element uitgelijnd met de linkerrand van de container. We bepalen de richting met behulp van de ternaire JavaScript-voorwaarde. Naast zijn positie geven we de nieuwe container ook een klassennaam die overeenkomt met zijn richting, die we op verschillende punten in het script kunnen testen.

Vervolgens moeten we een nieuwe functie definiëren om de animatie te initiëren en te bestendigen. Er zijn verschillende tijden tijdens de normale uitvoering van het script dat we moeten beginnen met animeren, dus het omwikkelen van deze functionaliteit in een functie die we kunnen gebruiken wanneer we hulp nodig hebben, helpt de hoeveelheid code te verminderen. Voeg de volgende code toe:

 // animator-functie var-animator = functie (el, tijd, richting) // welke richting om te scrollen als (dir == "rtl") // add direction class el.removeClass ("ltr"). addClass ("rtl "); // animeer het el el.animate (left: "-" + el.width () + "px", time, "linear", function () // reset containerpositie $ (this) .css ( links: $ ("div # imageScroller"). width (), right: ""); // animatieanimator opnieuw starten ($ (this), duration, "rtl"); // bedieningselementen verbergen als deze zichtbaar zijn ($ (" div # controls "). length> 0)? $ (" div # controls "). slideUp (" slow "). remove (): null;);  else // add direction class el.removeClass ("rtl"). addClass ("ltr"); // animeer el el.animate (left: $ ("div # viewer"). width () + "px", time, "linear", function () // plaats container resetten $ (this). css (left: 0 - $ ("div # container"). width ()); // herstart animatie-animator ($ (this), duration, "ltr"); // verberg besturingselementen indien zichtbaar ($ (" div # controls "). length> 0)? $ (" div # controls "). slideUp (" slow "). remove (): null;); 

De animatiefunctie accepteert drie argumenten; het te animeren element, de lengte van de tijd dat de animatie moet lopen en de richting waarin het element moet worden geanimeerd. De functie is opgesplitst in twee verschillende blokken, één voor rtl-animatie en de andere voor ltr.

Binnen elk blok van de conditionele update werken we de klassenaam van de afbeeldingscontainer bij om de huidige richting weer te geven, voor het geval de richting is gewijzigd (dit is een van de door bezoekers geïnitieerde interacties).

Vervolgens definiëren we de animatie, waarbij de beeldcontainer plus voor ltr of minus wordt verplaatst voor rtl de breedte van de beeldcontainer, waardoor deze de indruk krijgt over de viewer te schuiven. Helaas kunnen we de ingebouwde trage, normale of snelle animaties niet gebruiken, omdat zelfs de langzame instelling de animatie beperkt tot een totale runtime van slechts 600 milliseconden, wat veel te snel is, zelfs voor het kleine aantal afbeeldingen dat we gebruiken in dit voorbeeld.

We specificeren de string lineair als het derde argument van de animatiemethode die de easing-functie is om te gebruiken en stelt de animatie in op een uniforme snelheid van start tot finish; als we dit niet hadden ingesteld, zou de animatie merkbaar versnellen en vertragen aan het begin en einde van de animatie.

Uiteindelijk voegen we een anonieme callback-functie toe die wordt uitgevoerd zodra de animatie eindigt; binnen deze callback-functie retourneren we de afbeeldingscontainer naar zijn startpositie, roepen we de animatiefunctie opnieuw opnieuw aan in de juiste instellingen, afhankelijk van welke vertakking van de voorwaardelijke gebeurtenis wordt uitgevoerd en verbergt het configuratiescherm als dit zichtbaar is. We hebben de code die het configuratiescherm maakt nog niet toegevoegd, maar we moeten deze code hier nog toevoegen voor wanneer we die hebben.

Om de animatie te starten wanneer de pagina is geladen, moeten we nu de functie bellen die we zojuist hebben gedefinieerd; voeg de volgende functieaanroep toe:

 // start anim animator ($ ("div # container"), duur, richting);

Alles wat we doen, is de functie die in het element voorbij komt om te animeren en de variabelen die we in het eerste gedeelte van de code plaatsen. Als we de pagina nu uitvoeren, moeten we vaststellen dat de animatie wordt gestart zodra de pagina is geladen en voor onbepaalde tijd wordt voortgezet, zoals wordt weergegeven (soort van) in de volgende schermafbeelding:


Een beetje interactie toevoegen

We bevinden ons nu in het stadium waarin we de kernfunctionaliteit van de widget hebben en kunnen beginnen met het toevoegen van de extra interactiviteit die het aantrekkelijk maakt. Voer na de oproep aan de animatiefunctie de volgende code in:

 // pauze op mouseover $ ("a.wrapper"). live ("mouseover", functie () // stop anim $ ("div # container"). stop (true); // show controls ($ (") div # controls "). length == 0)? $ ("

Zoals de opmerking aangeeft, stopt deze gebeurtenishandler de animatie wanneer de bezoeker de aanwijzer op een van de afbeeldingen in de widget plaatst.

We gebruiken de methode live jQuery (nieuw voor 1.3!) Om de handler aan de elementen te koppelen en een anonieme functie op te geven die moet worden uitgevoerd wanneer de gebeurtenis plaatsvindt.

Binnen deze functie stoppen we eerst de animatie met de jQuery stop-methode, waarbij een echte Booleaanse waarde als een argument wordt doorgegeven. Dit argument annuleert de animatiewachtrij als deze bestaat; het zou niet moeten doen, want er zou altijd maar één animatie op elk moment moeten zijn, maar het is handig om dit argument te gebruiken voor het geval dat.

We controleren of het controlepaneel al bestaat en op voorwaarde dat het geen nieuw div-element maakt, een ID geeft zodat het onze stijlregels ophaalt en deze aan de buitencontainer toevoegt. Vervolgens gebruiken we de css-methode van jQuery om de dekking op een cross-browser manier in te stellen om te voorkomen dat we verschillende browsers met onze CSS moeten targeten en de bedieningselementen naar beneden schuiven.

We maken ook enkele koppelingen en voegen deze toe aan het configuratiescherm; deze links fungeren als knoppen waarmee de bezoeker de richting van de afbeeldingen kan veranderen. We zullen handlers voor deze knoppen in een ogenblik toevoegen. Ten slotte verkrijgen we de inhoud van het titelattribuut van de wrapper-koppeling die de mouseover-gebeurtenis heeft geactiveerd en maakt een nieuw alinea-element met de interne tekst ingesteld op de titel. We zijn sterk afhankelijk van de voorwaardelijke JavaScript-snelkoppeling in dit deel van de code, omdat deze een uitstekend mechanisme biedt voor het maken en toevoegen van elementen als deze nog niet bestaan.

Het is je misschien ook opgevallen dat we een variabele instellen om de inhoud van het titelattribuut van de huidige trigger vast te houden, je vraagt ​​je misschien af ​​waarom we in plaats daarvan niet de volgende code gebruiken:

 // voeg p toe als dit niet bestaat, werk het bij als dit het doet ($ ("p # title"). length == 0)? $ ("

") .attr (" id "," title "). text ($ (this) .attr (" title ")). appendTo (" div # controls "): $ (" p # title "). tekst (titel );

De reden hiervoor is dat er geen onduidelijkheid bestaat over waar $ (dit) naar verwijst. Het gebruik van de bovenstaande code werkt, maar het werpt fouten op, die niet-fataal zijn en toch niet zo geruststellend zijn voor potentiële gebruikers van de widget. Het gebruik van de variabele zorgt ervoor dat deze fouten worden voorkomen. Het bedieningspaneel, indien zichtbaar, wordt weergegeven zoals in de volgende schermafbeelding:

Na de muisaanwijzer wordt de animatie gestopt; we kunnen het gemakkelijk opnieuw starten met behulp van een event-handler voor mouseout, die we als volgende moeten toevoegen:

 // herstart op mouseout $ ("a.wrapper"). live ("mouseout", functie (e) // verberg besturingselementen als deze niet zweeft (e.relatedTarget == null)? null: (e.relatedTarget. id! = "controls")? $ ("div # controls"). slideUp ("slow"). remove (): null; // werk totale reisafstand uit var totalDistance = parseInt ($ ("div # container") .width ()) + parseInt ($ ("div # viewer"). width ()); // werk afstand af om te reizen var distanceLeft = ($ ("div # container"). hasClass ("ltr")) ? totalDistance - (parseInt ($ ("div # container"). css ("left")) + parseInt ($ ("div # container"). width ())): totalDistance - (parseInt ($ ("div # kijker "). width ()) - (parseInt ($ (" div # container "). css (" left ")))); // nieuwe duur is afstand links / snelheid) var newDuration = distanceLeft / speed; // start anim animator opnieuw ($ ("div # container"), newDuration, $ ("div # container"). attr ("class")); );

Wederom gebruiken we de live-methode van jQuery, maar deze keer geven we ook het onbewerkte gebeurtenisobject door aan onze anonieme callback-functie. We maken meteen gebruik van dit object om te zien of de aanwijzer naar het bedieningspaneel is verplaatst. Als dit niet het geval is, verbergen we de besturingselementen, maar als dit het geval is, doen we niets en gaan we verder met het opnieuw starten van de animatie. Merk op hoe we een geneste ternair gebruiken die equivalent is aan een if else conditional.

Het belangrijkste doel van de anonieme functie is om de animatie opnieuw te starten, maar voordat we dat kunnen doen, moeten we de duur van de animatie berekenen; we kunnen de waarde niet hardcoderen omdat de afbeeldingscontainer is verplaatst. De initiële duur was ingesteld op 1 seconde voor elke afbeelding, in dit voorbeeld 5 seconden. Als er slechts één afbeelding zichtbaar is in de viewer en we de animatie opnieuw instellen op 5 seconden, zal de animatie aanzienlijk trager verlopen.

We gaan eerst na wat de totale afstand is die de afbeeldingscontainer aflegt in een volledige animatie. Vervolgens bepalen we hoeveel van de volledige afstand nog moet worden afgelegd. We zullen een andere berekening moeten doen, afhankelijk van het feit of de animatie van links naar rechts of het tegenovergestelde gebeurt, dus we maken opnieuw gebruik van de ternaire conditionele.

Als de animatie van links naar rechts plaatsvindt, is de resterende afstand om te reizen het kenmerk links van de afbeeldingscontainer (verkregen met de css jQuery-methode) toegevoegd aan de breedte van de afbeeldingscontainer, afgetrokken van de totale afstand. Als de afbeeldingscontainer echter van rechts naar links beweegt, is de resterende afstand om te reizen de breedte van de afbeeldingscontainer minus het kenmerk voor de linker stijl, afgetrokken van de totale afstand. De jQuery-methoden width en css retourneren tekenreekswaarden, dus gebruiken we de parseInt-functie van JavaScript om deze naar numerieke waarden te converteren.

De nieuwe duur van de animatie wordt dan berekend door de resterende afstand te delen door de snelheid die we aan het begin van de code hebben berekend. Zodra we dit cijfer hebben, kunnen we de animatiefunctie opnieuw bellen door de vereiste parameters door te geven, waardoor de animatie opnieuw start van waar hij gestopt is, in dezelfde rijrichting.


Richting wijzigen

Voor het laatste deel van ons script kunnen we de handlers toevoegen voor de links in het configuratiescherm die worden gebruikt om de richting van de animatie te wijzigen. Direct na de code die we zojuist hebben toegevoegd, voert u de volgende code in:

 // handler voor ltr button $ ("# ltr"). live ("klik", functie () // stop anim $ ("div # container"). stop (true); // klassennamen $ ("ruilen) div # container "). removeClass (" rtl "). addClass (" ltr "); // werk totale reisafstand uit var totalDistance = parseInt ($ (" div # container "). width ()) + parseInt ($ ( "div # viewer"). width ()); // werk resterende afstand af var distanceLeft = totalDistance - (parseInt ($ ("div # container"). css ("left")) + parseInt ($ ("div # container "). width ())); // nieuwe duur is afstand links / snelheid) var newDuration = distanceLeft / speed; // start anim animator opnieuw ($ ("div # container"), newDuration, "ltr"); );

Deze functie, geactiveerd wanneer de knop van links naar rechts wordt geklikt, is relatief eenvoudig en bevat code die erg lijkt op wat we al hebben gebruikt; we stoppen eerst de huidige animatie (deze zal worden hervat wanneer de bezoeker de aanwijzer over het bedieningspaneel beweegt) en dan de klassenaam omwisselen zodat deze overeenkomt met de nieuwe rijrichting. Vervolgens berekenen we de nieuwe duur van de animatie op dezelfde manier als we eerder deden, voordat we eindelijk onze animatiefunctie opnieuw aanriepen. Dit is alleen de handler voor de knop ltr; de handler voor de RTL-knop is bijna identiek, maar gebruikt de juiste berekening voor de tegenovergestelde rijrichting:

 // handler voor rtl-knop $ ("# rtl"). live ("klik", functie () // stop anim $ ("div # container"). stop (true); // klassennamen $ ("ruilen) div # container "). removeClass (" ltr "). addClass (" rtl "); // werk totale reisafstand uit var totalDistance = parseInt ($ (" div # container "). width ()) + parseInt ($ ( "div # viewer"). width ()); // werk resterende afstand af var distanceLeft = totalDistance - (parseInt ($ ("div # viewer"). width ()) - (parseInt ($ ("div # container") ) .css ("left")))); // nieuwe duur is afstand links / snelheid) var newDuration = distanceLeft / speed; // start anim animator opnieuw ($ ("div # container"), newDuration, "rtl"); );

Dit is nu al de code die we moeten schrijven, als je de pagina nu in een browser uitvoert, zou je moeten merken dat de widget werkt zoals bedoeld.


Samenvatting

In deze zelfstudie hebben we een leuke en interactieve widget gemaakt voor het weergeven van een reeks afbeeldingen en kunnen worden gebruikt om logo's weer te geven van de fabrikanten van producten die u verkoopt, of de logo's van software die u aanbeveelt, of iets anders dat u bevalt. We hebben ons voornamelijk gericht op de animatie- en interactieaspecten van de widget, maar ook op zaken als een eenvoudige fallback voor het geval JavaScript is uitgeschakeld in de browser.