Det är självklart att SVG inte är så allmänt använd som många människor i webbutvecklingssamhället tror att det borde vara. Att ställa debatten åt sidan, i denna handledning kommer jag att demonstrera hur man använder inline SVGs, som täcker en rad tekniker och undersöker interaktionen mellan webbsida och grafik. När de används tillsammans med andra nya standarder i HTML5, JavaScript och CSS3 kan inline SVGs avsevärt öka användarupplevelsen.
Du kan interagera med SVG-elementen med DOM-tekniker, som du skulle med andra webbsidor.
I denna handledning kommer vi att arbeta genom ett praktiskt exempel på en inline SVG genom att skapa en enkel komponent som representerar ett rekorddäck. Skivan spinner och användaren kommer att kunna interagera med det - tryck för att sakta ner det och släppa för att påskynda det igen. SVG kommer också att innehålla en knapp som användare kan klicka för att ändra posten, vilket gör att utseendet ändras något. De synliga SVG-elementen kommer att förbättras med gradienter och drop-shadow-filter.
Kolla in demoen nu så att du har en klar uppfattning om vad vi bygger.
Som du troligen kommer att vara medveten om, faller SVG: er inom de nya HTML5-standarderna, så koden vi använder i denna handledning stöds inte fullt ut i alla webbläsare. Även om inline SVGs teoretiskt stöds i alla nuvarande versioner av de stora webbläsarna, kommer de interna animationerna och interaktiva effekter som vi använder inte att vara så bra stödda än. Slutresultatet ska fungera korrekt i nuvarande versioner av Firefox, Chrome och Opera. Som alltid med HTML5-tekniker, se till att du inte lita på dessa effekter på alla levande webbplatser du jobbar med och inkludera alternativ där det är möjligt.
Låt oss gräva in och börja med att skapa en HTML5-sidrapp, så här:
En av de främsta fördelarna med att använda SVG är hur skalbar det är. För att utnyttja detta ska vi i första hand använda relativa värden för att definiera SVG-innehållet. Lägg till ett behållarelement för SVG i sidokroppen:
För att se hur SVG sitter inom det innehållande elementet, lägg till följande i avsnittet Style i sidhuvudet:
#picHolder background: #dedeff; gräns: 1px fast # 666666;
Lägg till SVG-elementets disposition i behållarelementet i din sida på följande sätt:
Vi har satt bredden och höjden till 100%, eftersom vi ska ange bredden på det innehållande elementet. I stället för att explicit ange dimensionerna använder vi istället en JavaScript-funktion för att avslöja hur enkelt du kan skala SVG upp och ner. Du kan inkludera en fast bredd och höjd i den öppna SVG-taggen eller stilavsnittet.
De synliga formerna i grafiken definieras inuti SVG-elementet. Innan det kommer vi att arbeta på defs sektion. De defs avsnittet är där du lägger definitioner som du senare kan hänvisa till när du skapar dina former. För denna handledning, defs avsnittet kommer att innehålla definitioner för några gradientfyllningar och ett par droppskuggor. Lägg till den här nya delen i SVG-elementet:
De objekt som vi placerar i det här avsnittet visas inte i bilden, men kommer att användas som fyllningar och filter för de former som gör. Vi inkluderar flera gradientfyllningar; så låt oss arbeta genom var och en i sin tur.
Först upp är en linjär gradient:
Denna gradient kommer att anges som fyllning för bakgrundsrektangelområdet. De x1 och y1 attribut representerar utgångspunkten för gradienten i den fyllda formen, varvid gradienten utvecklas därifrån till den punkt som representeras av x2 och y2. I detta fall kommer lutningen att gå från topp till botten. Stoppelementen representerar färgpunkter i lutningen. Den första säger att 10% från början av lutningen kommer att vara en solid mörkröd färg och det andra stoppet att 90% från slutet av lutningen kommer att vara en gul färg. Mellan dessa två punkter kommer gradienten att blanda färgerna i varandra. Båda färgerna har full opacitet.
Därefter lägger vi till en gradient för själva posten. Den här är lite mer komplex - det är en radiell gradient med flera färgstoppar:
En radiell gradient börjar från insidan av cirkeln, med de innersta och yttersta delarna av cirkeln som definieras av cx, cy, fx och fy, listad längs radien. I detta fall kommer den radiella gradienten att uppta hela den cirkulära rekordformen. Huvuddelen av skivan kommer att vara svart, med två ringar med något ljusare färg som representerar de slätare delarna i mitten av skivan och dess kanter. Vi kommer också att placera en etikett på posten i mitten, så den första patchen av ljusare färg på posten kommer att visas precis utanför det. Lägg till etikettgradientfyllningen nästa:
Detta är en enkel linjär gradient som kommer att användas som fyllning för den cirkulära plåtiketten. Observera dock att gradient-id har en noll i slutet av den. Detta beror på det faktum att vi ska lägga till en interaktiv funktion, så att användaren kan "ändra posten". En JavaScript-funktion kommer att växla mellan ett antal gradientfyllningar för etikettelementet. För detta ändamål, lägg till ytterligare ett par gradienter:
Gradienterna har var och en ett ID som slutar med ett inkrementellt heltal, så att vi kan iterera genom dem i JavaScript. Definiera nu en annan gradient för att skapa en sken effekt ovanpå posten:
Den här gången stannar gradienten opak och alfa genomskinlig färg; effekten blir en subtil sken över posten. Slutligen behöver vi en metallfyllning för knappen och spindeln:
Den här gången är den radiella gradienten något utanför centrum för att skapa en känsla av djup och ljus, vilket kommer att kompletteras med ett droppskuggfilter.
Innan vi slutar med defs avsnitt, lägg till ett par droppe skuggor för att ge några av formerna lite mer djup:
Den här kommer att dyka upp bakom rekordområdet. De x, y, bredd och höjd Egenskaper refererar till position och dimensioner i formen med detta filter. Förskjutningen definierar skuggan i förhållande till den ursprungliga formen. Oskärpa förhindrar offsetformen från att vara fast färg, så att den verkar som en skugga. I detta fall kommer endast skuggan att visas, inte själva formen - skuggan kommer att definieras av en särskild form som kommer att placeras bakom rekordformen. För användarkontrollerna, som är cirkulära och metalliska, vill vi också ha en droppskugga, men vi vill att formen själv ska visas också:
Denna huvudsakliga skillnad här är, bortsett från skuggans skala, blandningselementet, vilket bevarar den ursprungliga formen samtidigt som den visar skuggan runt den.
Det är tillräckligt med förberedelse; låt oss fortsätta med grafiken! Varje objekt du lägger till i SVGs kropp kommer att visas ovanpå tidigare listade element, så vi kommer att arbeta från botten upp, börjar med formerna på baksidan och slutar med de på framsidan.
Lägg först till en rektangelform för bakgrunden:
De rect Elementens dimensioner och position anges i förhållande till innehållet SVG, vilket, om du kommer ihåg, är relativt storleken på det innehållande elementet. Vi ställer in det här senare i JavaScript. Vi kommer att använda relativa storlek och positionsvärden, var det är möjligt, så att hela bild plus animering och interaktion kan skala upp eller ner på efterfrågan. Observera att elementfyllet anger en av de gradienter som vi definierat, med dess ID-attribut.
Nästa uppifrån längst ner är rekordskuggan, med hjälp av ett av de skuggfiltre som vi skapade:
Skuggan kommer att ligga bakom skivan, som en cirkulär form med en radie som är ungefär en tredjedel av det utrymme som tilldelats bilden, placerad i mitten. Eftersom filtret i det här fallet inte gäller blandning med bilden, visas inte cirkeln själv, bara dess skugga.
Nästa upp är posten själv:
Liksom med skuggan, den cx och cy attribut representerar mitten av posten, som centreras i bilden horisontellt och vertikalt, med en radie av ungefär en tredjedel. Återigen använder vi en av de gradienter som vi definierat, vilket vi kommer att göra i varje form.
Ovanpå skivan är dess etikett, så lägg till det nästa:
Etikettcirkeln har samma centrala punkt som posten, över vilken den sträcker sig ungefär en tredjedel av vägen. Vi börjar med det första av etikettgradientalternativen som vi definierat och kommer att implementera användaren som växlar mellan dessa senare - vi inkluderar en ID-attribut här för att hänvisa till detta element i JavaScript.
Låt oss nu lägga lite glans på toppen av posten:
När skivan spinner kommer den att flytta till höger och nere bara lite, så vi håller skenan något mindre än skivan så att den inte verkar spridas bortom den när den rör sig. Detta element har också ett ID-attribut för att upptäcka användarinteraktion.
För fullständighet, låt oss lägga till en liten spindel i mitten av posten:
Denna form använder den metalliska gradienten vi skapade. Vi applicerar också det andra droppskuggfiltret, vilket inkluderar blandning så att formen och skuggan båda visas.
Sist men inte minst behöver vi en liten knapp för att användare ska kunna styra byte av posten, med samma fyllning och filter som spindeln:
Den här gången, i stället för ett självstängande element, skiljer vi taggarna för öppning och stängning av cirklar. Detta beror på att vi kommer att animera knappen när användarna klickar på den och kommer att inkludera animeringseffekten mellan dessa taggar. Observera att vi har kunnat återanvända fylla och filtrera element från defs sektion. Här är grafikkens ursprungliga utseende när siddimensionerna är på plats:
Varje objekt du lägger till i SVGs kropp kommer att visas ovanpå tidigare listade element.
Nu har vi våra visuella element på plats, låt oss lägga till lite animering. Vi kan göra rekordspinnningen med hjälp av SVG-animationstransformationer, som är en förlängning av SMIL-animering. Dessa animerade effekter definieras inom SVG-markupen. En effekt gäller vad som helst SVG-element som det förekommer inom. Du kan använda CSS3-omvandlingar på SVG-element, men de SMIL-baserade alternativen ger dig större kontrollnivå.
Vi kommer att inkludera två enkla animeringar: posten ska snurra och knappen kommer att flytta lite när användaren klickar på den. Låt oss börja med den lite mer rakt framåt animationen för knappen.
Inuti knappen formelement, mellan de öppnande och stängande cirkel taggar som vi skapade, lägg till animera transformen enligt följande:
De animateTransform gäller för ett XML-attribut inom det element som det visas i. I det här fallet är det en translate-transform. De från och till attribut representerar start- och slutpositionerna för elementet - dessa är i förhållande till startpositionen, så knappen kommer att flytta till höger och nere genom en enda bildpunkt. Transformen börjar när en användare klickar, går över en tiondel av en sekund och utför en gång. Knappen återgår till sin ursprungliga position när animationen är klar. Tips: För att behålla ett element i slutpositionen efter en animering, ange fylla = "frysa".
Nu för att spinna rekordet. En animateTransform gäller för ett SVG-element, men vi behöver att spinnet gäller för mer än ett element - specifikt till posten och etiketten (inte till sken eller skugga). I stället för att skapa separata animeringar för varje och genomföra dem samtidigt kan vi använda en enda transform genom att gruppera dessa element tillsammans. Innan cirkelelementet som representerar posten (med "recordGrad" som dess fyllning) lägger till en öppningsgrupps tagg:
När cirkeln representerar etiketten stänger du gruppen:
Lägg nu till transformen före den här stängningsgruppens tagg så att den gäller hela gruppen:
Den här animerade effekten är den här rotationsomvandlingen. Elementet kommer att rotera 360 grader, och för att lägga till effekten flyttas det till höger och nere genom en enda bildpunkt på varje rotation under en period av en sekund och upprepas i obestämd tid. Denna omvandling kommer också att innehålla en från attribut, eftersom det är nödvändigt att ange den ursprungliga positionen för elementen som roteras. Om du inte anger den här positionen roterar elementen runt 0, 0 Peka som standard. För närvarande kan du emellertid inte tillhandahålla relativa (dvs procentvärden) värden till dessa attribut, endast fasta värden. Av den anledningen kommer vi att ställa in från ange när vi anger SVG-dimensionerna i JavaScript.
Låt oss nu genomföra våra interaktiva funktioner: klicka på knappen för att ändra posten och trycka på posten för att sakta ner den.
Först, i skriptdelen i ditt sidhuvud, lägg till dessa variabler för att räkna och hålla reda på etikettdesignerna:
// hålla koll på aktuell plåtikett var currLabel = 0; // ändra detta för ett annat antal etiketter var numLabels = 3;
Nu, inuti öppningstaggen för cirkelelementet som representerar knappen (som nu har en animering mellan dess taggar) lägger du till följande klickhändelseloggare:
onclick = "changeRecord ()"
Tillbaka i huvudskriptavsnittet, lägg till funktionsschemat:
funktionsändringRecord ()
Varje gång användaren trycker på knappen flyttar vi till nästa etikett, flyttar tillbaka till den första när vi når den sista:
// flytta till nästa etikett currLabel ++; // återställ om vid högsta tal om (currLabel> numLabels - 1) currLabel = 0; // Ange fyllningsattributet till nästa gradient document.getElementById ("recordLabel"). setAttribute ("fill", "url (#labelGrad" + currLabel + ")");
Den sista raden visar här hur du kan interagera med SVG-elementen med DOM-tekniker, som du skulle med andra webbsidor. Här ställer vi in fylla attributet för etikettcirkelelementet för att använda nästa gradientfyllning och specificera fyllnings-id.
Lägg nu följande händelseattribut i rekordskenelementet (med "shineGrad" som dess fyllning), eftersom vi ska använda musen ner och upp händelser på den för att utlösa sakta nedteckningen och påskynda den igen:
onmousedown = "onRecord ()" onmouseup = "offRecord ()"
Tillbaka i skriptavsnittet, lägg till funktionen för när en användare trycker på posten:
// funktion som heter när användaren trycker på inspelningsfunktionen onRecord ()
Inne i den här funktionen kan vi sakta ner rekordspinnningsanimationen genom att ändra animateTransform varaktighet. Vi ändrar också glansdispersibiliteten för att skapa intryck av att trycka ner:
// sakta ner animationsvaraktigheten document.getElementById ("spinTrans"). setAttribute ("dur", "5s"); // minska skenhetens opacitet document.getElementById ("shine"). style.opacity = "0.7";
När användaren släpper posten vill vi att den ska gå tillbaka till normal hastighet och utseende, så lägg till "mus upp" -funktionen nästa:
// funktion som heter när användaren släpper in rekordfunktionen offRecord () // återställs till normal hastighet document.getElementById ("spinTrans"). setAttribute ("dur", "1s"); // ställa opacitet tillbaka till normal document.getElementById ("shine"). style.opacity = "1.0";
Vi kan äntligen ställa SVGs totala storlek nu. Överst i skriptavsnittet lägger du till en ny variabel:
// önskad storlek på SVG varstorlek = 300;
Vi kommer till att börja använda 300
pixlar för både bredden och höjden på grafiken, men du kan ändra det här när som helst. Definiera en funktion i skriptavsnittet för att ställa in dessa dimensioner:
// funktion att ställa in SVG dimensioner funktion setSize () // set css och transform storlek varhållare = document.getElementById ("picHolder"); holder.style.height = Storlek + "px"; holder.style.width = Storlek + "px"; document.getElementById ("spinTrans"). setAttribute ("från", "0," + storlek / 2 + "," + storlek / 2 + "");
Vi ställer in storleken på innehållet div element. Titta på sista linjen i den här funktionen. Eftersom animationen för rotationsomvandling inte kan använda relativa procentvärden måste vi ställa in från element med hjälp av storleksvariabeln (dividerad med två för den centrala punkten i posten). Med 300 som SVG-storlek, så är omvandlingen med fasta värden:
Om du vill använda fasta värden i ditt SVG kan du göra det. Vi använder endast den här tekniken för att demonstrera med relativa dimensioner. Slutligen, ring denna funktion i slutet av skriptavsnittet:
window.addEventListener ("DOMContentLoaded", setSize, false);
Vår interaktiva SVG-animering är nu klar! Öppna din sida i en stödjande webbläsare för att se effekten; glöm inte att försöka interagera med posten och knappen. Prova att ändra storlek variabeln för att se hur SVG-elementen alla anpassar sig till passar, inklusive animationer och interaktioner.
Om du vill utforska SVG vidare, är det några ämnen att tänka på, inklusive sökvägar, text, maskering och klippning. Det finns också en rad extra animeringsalternativ att överväga. Naturligtvis kommer dessa effekter inte att fungera för alla användare just nu, men förhoppningsvis en dag snart ...