Skapa en sidvändningseffekt

Denna artikel dök upp först i nummer 223 of .net magazine - världens mest sålda tidning för webbdesigners och utvecklare.

CSS-övergångar och transformationer är fortfarande relativt nya och syntaxen kan förändras innan den blir en standard. Vi kan fortfarande börja använda dessa egenskaper nu, dock: vi behöver bara se till att vi använder leverantörens prefixversioner. För att ge support för användare av alla webbläsare är det viktigt att inkludera alla leverantörsprefixversioner. Detta ger dock inte särskilt kortfattad kod, så för tydlighetens skull använder jag bara prefixet -webkit under hela denna handledning.

Introduktion till CSS-övergångar

CSS-övergångar är en ny funktion i CSS3 som ger dig möjlighet att animera element bara genom att ändra CSS-egenskaper. Med hjälp av övergångar berättar du webbläsaren vilka egenskaper som ska animeras, hur lång tid de borde ta och vilken lättnadsfunktion som ska användas. Här är ett exempel på hur ett element automatiskt kan blekas ut bara genom att lägga till en klass:

div#test{-webkit-transition-property: opacity;-webkit-transition-duration: 500ms;-webkit-transition-timing-function: ease;opacity: 1.0;}div#test.hidden{opacity: 0.0;}

Introduktion till CSS-omvandlingar

CSS-transformationer är också nya för CSS3 och låter dig utföra 2D- och 3D-manipulation på element som skalning, översättning och rotation. Här är ett exempel på hur du kan använda en transform för att rotera lite text:

p#test{-webkit-transform: rotate(45deg);}

Att använda CSS-övergångar och omvandlingar tillsammans är ett enkelt sätt att skapa riktigt övertygande animationer för din webbplats eller webbapp. Övergångar kan också accelereras hårdvara så att de fungerar mycket bättre på mobila enheter än de traditionella timerbaserade JavaScript-animationerna.

Här är en som jag skapade tidigare: sidvändningseffekten i aktion

Här är en som jag skapade tidigare: sidvändningseffekten i aktion

För att visa kraften i att kombinera CSS3-omvandlingar med övergångar, låt oss skapa en galleriwidget för jQuery som efterliknar en sidvändningseffekt. De flesta moderna webbläsare stöder nu CSS-övergångar, men inte alla stöder 3D-omvandlingar ännu. När vi skapar en 3D-effekt riktar vi oss bara till WebKit-webbläsare som Safari, Chrome och iOS.

hur man ritar ett lurvigt varghuvud

HTML-markering

Till att börja med måste vi ange vår markering så att widgeten har något att arbeta med:

Photo 1 Photo 2 Photo 3

För att göra detta skapar vi en enkel struktur med en serie bildelement inuti en innehållande div. Vi ger också detta element en klass så att åtkomst via jQuery är enklare. Det är viktigt att ställa in visningsegenskapen till ingen för alla utom den första bilden: på så sätt försämras renderingen bättre om klientens webbläsare av någon anledning inte stöder JavaScript.

Skapa widgeten

Nu när vi har vår markering måste vi skapa jQuery-widgeten (jQuery-widgets är en del av jQuery UI-biblioteket). Skapa följande grundläggande widgetmall i en separat fil:

(function($) {$.widget('ui.flipGallery', {options: {},_create: function() {// Setup widget}}});

Vi använder widgetkonstruktören (_create ()) för att ställa in DOM så att den är redo för vändningseffekterna. Vi måste också lägga till lite kod i huvud-HTML-dokumentet för att skapa galleriet vid laddning. För att göra detta, lägg till följande på din HTML-sida:

jQuery(document).ready(function($){$('div.gallery').flipGallery();});

Så det första vi behöver göra är en allmän inställning. Lägg till följande i dina widgets _create () -funktion:

var that = this;// Find all the images for the gallerythat.images = that.element.find('img');// If we only have one image then don't proceedif(that.images.length <= 1)return;that.currentImageIndex = 0;// Get image dimensionsthat.height = that.images.first().height();that.width = that.images.first().width();// Make sure the gallery element remains this sizethat.element.width(that.width).height(that.height);// Allow sub elements to be absolutely positioned within the gallerythat.element.css('position', 'relative');// Setup the element to support perspectivethat.element.css({'-webkit-perspective': 1100,'-webkit-perspective-origin': '50% 50%'})

Ovanstående kod får en lista över alla bilder som vi angav i markeringen och säkerställer att behållarelementet har rätt storlek. Det skapar också en instansvariabel för att hålla reda på indexnumret på bilden som visas. Vi använder det lite senare för att gå igenom bildsekvensen.

Den sista delen av den här koden ställer in perspektiv på gallerielementet. När vi skapar en 3D-effekt måste vi berätta för elementet att ha perspektiv annars ser det inte ut som att sidan kommer ut ur skärmen när vi kör övergången. Ju mindre antal som används för -webkit-perspektiv, desto mer uttalat är perspektivet. För denna effekt fann jag att värden runt 1100 ser bäst ut.

Skikten vi behöver skapa med DOM-element så att vi kan efterlikna utseendet på en sida som vänder och avslöjar efterföljande bild

Skikten vi behöver skapa med DOM-element så att vi kan efterlikna utseendet på en sida som vänder och avslöjar efterföljande bild

Lägg till dynamisk markering

Vi är nu redo att låta widgeten göra något. Först måste vi ta reda på vilka element vi behöver för den önskade effekten. När vi skapar en sidbläddring måste vi tänka på vad som händer när du bläddrar i en bok.

  1. Vi vill börja med att se den första bilden i sin helhet.
  2. Vi vill sedan se att den högra sidan av denna första bild roterar runt mitten och avslöjar den högra sidan av den andra bilden.
  3. När det roterade elementet är vinkelrätt mot skärmen vill vi fortsätta att rotera, men visa den vänstra sidan av den andra bilden istället.

För att uppnå detta kommer vi att vilja skapa en DOM-elementstruktur som återspeglar diagrammet ovan.

Låt oss nu skapa några DOM-element för att matcha önskad skiktning. Eftersom vi behöver kunna visa endast vissa delar av bilderna, istället för att rendera element kommer vi att tillämpa bilderna på bakgrunden av elementen. Detta gör det i huvudsak möjligt för oss att dynamiskt beskära (eller klippa) bilderna efter behag. För att skapa lager ett och två måste vi lägga till följande kod:

hur man lägger till texturer i Photoshop
// Create an element to show the left hand slide of image Athat.imageLeftA = $(' ', { 'class': 'imageLeftA'}).css({width: '100%',height: '100%',position: 'relative'});// Create an element to show the right hand side of image Bthat.imageRightB = $(' ', { 'class': 'imageRightB'}).css({// Full height, half widthwidth: '50%',height: '100%',// Cover the right hand part of imageLeftAposition: 'absolute',top: '0px',right: '0px',// Right align the background imagebackgroundPosition: 'right top'}).appendTo(this.imageLeftA);// Add to the DOMthat.imageLeftA.appendTo(that.element);

Därefter lägger vi till de element som representerar sidan som kommer att vända. Detta kommer att innehålla lager tre och fyra:

// Now create the 'page' that will flip overthat.page = $(' ', { 'class': 'page' }).css({// Full height, half widthwidth: '50%',height: '100%',// Cover the right hand part of the imagesposition: 'absolute',top: '0px',right: '0px',// We need to tell this element to preserve the orientation of sub elementsas it is transformed'-webkit-transform-style': 'preserve-3d'});that.imageRightA = $(' ', { 'class': 'imageRightA'}).css({// Fill the container (which is full height, half width)width: '100%',height: '100%',// Right align the background imagebackgroundPosition: 'right top',// Make sure the element starts at the top left of the pageposition: 'absolute',top: '0px',left: '0px',// We don't want to see the image when its facing away from us'-webkit-backface-visibility': 'hidden'}).appendTo(that.page);that.imageLeftB = $(' ', { 'class': 'imageLeftB'}).css({// Fill the container (which is full height, half width)width: '100%',height: '100%',// Make sure the element starts at the top left of the pageposition: 'absolute',top: '0px',left: '0px',// We need to rotate this panel as it should start with its back facing out ofthe screen'-webkit-transform': 'rotateY(180deg)',// We don't want to see the image when its facing away from us'-webkit-backface-visibility': 'hidden'}).appendTo(that.page);that.page.appendTo(that.element);

Det viktiga att notera i koden ovan är att den vänstra sidan av elementet som representerar bild B roteras 180 ° så att den vänds bort från skärmen när den startar. Det är också viktigt att vi säger till båda lagren inuti sidelementet att de bara visar deras framsida. Detta uppnås genom att använda CSS3-egenskapen '-webkit-backface-visibility':
'dold' och betyder att någon del av elementet som inte vetter mot skärmen inte kan ses av användaren. Genom att förhindra att elementens baksida visas, skapar vi intrycket att de två delelementen är vardera sidan av sidan.

Vi har också använt en ny CSS3-egenskap '-webkit-transform-style': 'preserve-3d' på sidelementet som innehåller de två lagren. Denna egenskap tvingar transformationerna på delelement att beräknas i förhållande till detta element. Det här är lite förvirrande, men för det här exemplet betyder det att när sidelementet roteras, kommer de två underordnade elementen att rotera med det. Utan det kommer du att få oväntat beteende.

När den första bilden vänds, exponeras den och den bakom den på ett liknande sätt

När den första bilden vänds, exponeras den och den bakom den på ett liknande sätt

Animerad

Vid den här tiden har vi satt upp alla våra DOM-element, så vi måste ta bort originalbilderna från behållaren och måla rätt bilder på våra olika lager. För att avsluta funktionen _create () lägg till följande två kodrader:

// Remove the images from the DOMthat.images.remove();that._setupImages();

Eftersom vi nu kallar en ny funktion måste vi definiera vad funktionen _setupImages () gör. Lägg till följande kod i din widget:

_setupImages: function() {var that = this;var nextImageIndex = that.currentImageIndex + 1;// Range check the next image indexif(nextImageIndex >= this.images.length)nextImageIndex = 0;// Setup the placeholder elements with the correct backgroundsthat.element.add(that.imageLeftA).add(that.imageRightA).css('background-image', 'url('+ $( that.images.get(that.currentImageIndex) ).attr('src') + ')');that.imageRightB.add(that.imageLeftB).css('background-image', 'url('+ $(that.images.get(nextImageIndex) ).attr('src') + ')');}

Vi har nu allt på plats för att kunna initiera galleriet, men just nu ser vi bara i webbläsaren den första bilden. Låt oss nu lägga till en funktion för att faktiskt utföra sidvändningen.
Först behöver vi ett sätt att utlösa effekten. Du kan göra detta genom att lägga till en knapp i din HTML-fil:

Show Next Image

Vi måste också ändra vår jQuery.ready-kod för att fästa en lyssnare till knappen. Ändra funktionen så att den ser ut så här:

jQuery(document).ready(function($){$('div.gallery').flipGallery();$('button.next').click(function(event){event.preventDefault();// Trigger a page flip$('div.gallery').flipGallery('turn');});});

När du trycker på knappen kommer den nu att aktivera svängfunktionen på vår widget. Låt oss nu implementera den här funktionen så att den skapar sidvändningseffekten. Lägg till följande kod:

turn: function() {var that = this;// Setup the transitionthat.page.css({'-webkit-transition-property': '-webkit-transform','-webkit-transition-duration': '1000ms','-webkit-transition-timing-function': 'ease',// Make sure the rotation pivots around the left hand edge'-webkit-transform-origin': 'left'});// Use setTimeout() to ensure the above settings have taken effect beforeproceedingsetTimeout(function() {that.page.css({// Flip from left to right around the Y axis'-webkit-transform': 'rotateY(-180deg)'});}, 50);}

Så vad gör ovanstående kod? Först ger vi vårt sidelement lite CSS för att berätta vilken egenskap som ska animeras och hur vi vill att animationen ska visas. I det här fallet vill vi att alla ändringar i egenskapen -webkit-transform ska animeras under en varaktighet på 1000 ms, och vi skulle vilja använda funktionen timing timing. Vi anger också att vi vill utföra transformationer runt elementets vänstra sida. Detta kommer att säkerställa att när vi roterar sidelementet (som representerar bildens högra sida) kommer det att vända runt bildens mitt.

Den andra delen av koden gäller sedan för rotationen och ställer in den nya positionen vi vill att sidelementet ska vara i. Eftersom vi har sagt att alla -webkit-transform-egenskapens ändringar ska animeras istället för att omedelbart byta till den nya rotationspositionen , kommer sidelementet att animeras smidigt och ge önskad sidvridningseffekt.

Det kan verka som om vi är färdiga, men hur ställer vi in ​​nästa bild så att vi kan bläddra igenom valfritt antal bilder? Lyckligtvis, när en övergång är klar kommer webbläsaren att utlösa en händelse, som vi kan lyssna på på samma sätt som vi kunde klicka eller en tangenttryckning. Låt oss ändra vår turn () -funktion genom att lägga till en eventlyssnare för att återställa för nästa övergång. Byt ut den första raden i turn () -funktionen med följande nya kod:

var that = this;// Setup a function to trigger when the transition has finishedvar transitionEnd = function(event) {// Stop listening for transition eventsthat.page.unbind('webkitTransitionEnd', transitionEnd);that.currentImageIndex++;// Range check the new image indexif(that.currentImageIndex >= that.images.length)that.currentImageIndex = 0;// Set the background of the gallery to the new imagethat.element.css('background-image', that.imageLeftB.css('background-image'));// Hide the created DOM elements to reveal the gallery backgroundvar elements = that.imageLeftA.add(that.page).hide();// Stop changes to the page from being animatedthat.page.css({'-webkit-transition-property': 'none'});setTimeout(function() {// Reset the elements for the next turnthat.page.css('-webkit-transform', 'none');that._setupImages();elements.show();}, 50);}// Listen for when the transition has finishedthat.page.bind('webkitTransitionEnd', transitionEnd);

Nu när en övergång är klar utför vi följande steg för att återställa för nästa sida:

  1. Öka det aktuella bildindexet.
  2. Ställ in bakgrunden för gallerielementen som den nya bilden.
  3. Dölj våra anpassade lager.
  4. Inaktivera övergångar och återställ rotationen på vårt sidelement.
  5. Ring _setupImages () för att måla de aktuella bilderna på våra lager för aktuella och nästa bilder i sekvensen.

Och efter allt det hårda arbetet har vi vår färdiga produkt - en återanvändbar jQuery-widget som kan ge fantastiska sidflipeffekter som kommer att se bra ut för ett portföljgalleri.