SVG
Et rektangel
Et enkelt rektangel kan se slik ut:
Koden er slik:
<svg width="5cm" height="5cm" viewBox="0 0 50 50"> <desc>Et enkelt eksempel</desc> <rect x="10" y="10" width="20" height="20" fill="yellow" stroke="blue" stroke-width="2"/> </svg>
Vi har laget et svg-element som beslaglegger et område på 5x5 cm. Det adresseområdet, viewBox, vi har definer er 50 X 50. Det vil si at når vi beskriver figurer i dette adresseområdet, så mappes dette til det 5x5 cm store området på siden (skjermen). Det eneste vi tegner ut er et rektangle som er fylt med gult og med blå kant. Du kan eksperimentere med koordinatene til rektangelet og til svg-elementet for å se hvordan mappingen via viewBox fungerer.
Default er origo oppe til venstre i det koordinatsystemet som etableres.
Du kan også av "arkeologiske" årsaker se, og inspisere, denne som en egen SVG-fil, laget før HTML5:
Flagget
Det norske flagget kan lages slik:
Koden er slik:
<svg width="300px" height="300px" viewBox="0 0 300 300"> <desc> Flaggets proposjoner: Horisontalt: 6R 1H 2B 1h 12R=22 Vertikalt: 6R 1H 2B 1H 6R=16 </desc> <g transform="translate(20,50)"> <rect x="0" y="0" width="220" height="160" fill="red" stroke="none" stroke-width="0"/> <rect x="0" y="60" width="220" height="40" fill="white" stroke="none"/> <rect x="60" y="0" width="40" height="160" fill="white" stroke="none"/> <rect x="0" y="70" width="220" height="20" fill="blue" stroke="none"/> <rect x="70" y="0" width="20" height="160" fill="blue" stroke="none"/> <g transform="translate(0,225)"> <text id="TextElement" x="0" y="0" font-family="Verdana" font-size="25" fill="black" stroke="none"> 17.mai </text> </g> </g> </svg>
Vi har tatt i bruk elementet g og vi bruker det til å flyttet origo mens vi "tegner", translate. Teksten som kommer under flagget er lagt inn i et eget g-element. Siden dette er omsluttet av det andre vil hele tegningen, flagget og teksten, kunne forskyves ved å endre parametrene til translate i det første, ytterste, g-elementet.
Smiley
En blid smiley har litt mer komplisert form enn de rektanglene vi har brukt ovenfor. Vi vil se at den runde hodeformen og øynene lar seg realisere med elementer som heter circle. Uten munn kan en smiley lages slik:
Koden er slik:
<svg width="200px" height="200px" viewBox="0 0 400 400"> <desc>En smiley</desc> <g transform="translate(200,200)"> <circle cx="0" cy="0" r="100" fill="yellow"/> <circle cx="40" cy="-40" r="20" fill="black"/> <circle cx="-40" cy="-40" r="20" fill="black"/> </g> </svg>
Hva så med munnen. Dette er litt mer utfordrende. Vi må på en eller annen måte kunne forme en kurve. Den enkleste måten å beskrive en kurve på er å angi punktene på kurven. I SVG kan vilkårlige polygoner (mangekanter) beskrives ved den vi kan kalle en blyant-metafor. Vi har en kommando for å løfte blyanten og flytte den og en kommando for å trekke en strek. Elementet
<path d="M 0,0 L 10,0 5,10 z" fill="none" stroke="black" stroke-width="1"/>
vil tegne en trekant. Attributten d(ata) sier at vi skal M(ove) blyanten til 0,0, så skal vi lage L(ine) fra punkt til punkt i lista som følger. z til slutt sier at kurven skal lukkes. På grunnlag av dette kan vi foreslå følgende smiley:
Koden er slik:
<svg width="200px" height="200px" viewBox="0 0 400 400"> <desc>En smiley</desc> <g transform="translate(200,200)"> <circle cx="0" cy="0" r="100" fill="yellow"/> <circle cx="40" cy="-40" r="20" fill="black"/> <circle cx="-40" cy="-40" r="20" fill="black"/> <path d="M-40,10 L -20,30 -10,35 0,40 10,35 20,30 40,10" fill="black" stroke="none"/> </g> </svg>
Dette er ikke helt vellykket. Vi har mange muligheter for forbedring. Vi kan lage flere og tettere punkter, eller vi kan bruke en matematisk måte å beskrive en glattere kurve. For de som er kjent med grafisk databehandling så er det f.eks. mulig å lage Bezierkurver. Vi forfølger ikke dette her.
Tekst
Vi brukte tekst ovenfor i flaggeksempelet uten å kommentere det noe videre. Det er relativt kurant å sett ut tekst i SVG-områder. F.eks. slik:
Koden er slik:
<svg width="400px" height="400px" viewBox="0 0 400 400"> <desc>litt ymse tekst</desc> <g transform="translate(200,200)"> <text id="TextElement1" x="0" y="0" transform="rotate(-30)" font-family="Verdana" font-size="20" fill="blue" stroke="none"> Hallo dette ble skjevt </text> <text id="TextElement2" x="-70" y="50" transform="rotate(30)" font-family="Verdana" font-size="20" fill="red" stroke="black" stroke-width="0.2"> Ja du store </text> </g> </svg>
Animasjon
Vi kan skape tidsstyrte animasjoner i SVG. Det er tre elementer som styrer slik animasjon. Nedenfor er de satt opp med noen typiske attributter. Du må selvsagt slå opp på SVG sidene i W3C for å få full oversikt.
<animateMotion from="0,0" to="50,50" begin="0s" dur="24s" repeatCount="indefinite"/> <animateTransform attributeName="transform" attributecode="XML" code="rotate" from="1" to="1440" begin="0s" dur="24s" repeatCount="indefinite"/> <animateColor attributeName="fill" attributecode="CSS" from="blue" to="red" begin="0s" dur="24s" repeatCount="indefinite"/>
Vi forsøker oss på litt tekst (reload siden):.
Koden er slik:
<svg width="300px" height="300px" viewBox="0 0 300 500"> <desc>litt dynamisk tekst</desc> <g transform="translate(200,200)"> <text id="TextElement3" x="-10" y="5" font-family="Verdana" font-size="5" fill="blue" stroke="none"> Hallo <animateMotion from="0,0" to="50,50" begin="0s" dur="12s" fill="freeze" /> <animateTransform attributeName="transform" attributeType="XML" type="rotate" from="1" to="1440" begin="0s" dur="6s" fill="freeze" /> <animateTransform attributeName="transform" attributeType="XML" type="scale" from="1" to="15" additive="sum" begin="0s" dur="12s" fill="freeze" /> <animateColor attributeName="fill" attributeType="CSS" from="blue" to="red" begin="0s" dur="24s" repeatCount="indefinite"/> </text> </g> </svg>
Dersom vi skal animere, f.eks. rotere, vår smiley må vi lage en konstruksjon som roterer alle delene. Dette kan vi oppnå ved å lage et g-element som inneholder det ønskede animasjonselementet og smileybeskrivelse. (reload siden for å animere)
Koden er slik:
<svg width="200px" height="200px" viewBox="0 0 400 400"> <desc>En smiley</desc> <g transform="translate(200,200)"> <g> <animateTransform attributeName="transform" attributeType="XML" type="rotate" from="1" to="1440" begin="0s" dur="6s" fill="freeze" /> <circle cx="0" cy="0" r="100" fill="yellow"/> <circle cx="40" cy="-40" r="20" fill="black"/> <circle cx="-40" cy="-40" r="20" fill="black"/> <path d="M-40,10 L -20,30 -10,35 0,40 10,35 20,30 40,10" fill="black" stroke="none"/> </g> </g> </svg>
Kartdata
SVG kan fungere interaktivt.
Interaksjonen i kartet er realisert ved hjelp av de eventene som er definert for SVG og litt DOM-programmering. Et utdrag av kildekoden er slik: (Polygondataene er redusert):
<svg width="100%" height="100%" viewBox="0 0 11939 15026"> <desc>Norgeskart</desc> <script type="text/ecmascript"> var lastPath=null; var markcolor="red"; var unmarkcolor="white"; function kommune_click(evt) { var path = evt.target; path.setAttribute("fill",markcolor); if (lastPath!=null) lastPath.setAttribute("fill",unmarkcolor); lastPath=path; var kommunename = path.getAttribute("id"); var komElement=document.getElementById("KommuneElement"); var komTextNode=document.createTextNode(kommunename); komElement.replaceChild(komTextNode,komElement.firstChild); } </script> <g transform="translate(250,1250)"> <text id="TextElement11" x="0" y="0" font-family="Verdana" font-size="500" fill="black"> Norge </text> </g><g transform="translate(250,1850)"> <text id="TextElement12" x="0" y="0" font-family="Verdana" font-size="350" fill="black"> 6551 punkter </text> </g> <g transform="translate(7250,7250)"> <text id="KommuneElement" x="0" y="0" font-family="Verdana" font-size="500" fill="black"> Move mouse on map </text> </g> <g transform="translate(0,15026)"> <g transform="scale(1.0,-1.0)"> <path onmouseover="kommune_click(evt)" id="Halden" d="M 3839,1188 L 3834,1257 ... z" fill="none" stroke="black" stroke-width="10"/> <path onmouseover="kommune_click(evt)" id="Sarpsborg" d="M 3599,1314 L 3594,1324 ... z" fill="none" stroke="black" stroke-width="10"/> <path onmouseover="kommune_click(evt)" id="Sør-Varanger" d="M 11642,13462 L 11633,13471 ... z" fill="none" stroke="black" stroke-width="10"/> </g> </g> </svg>
Merk at dataene er gamle (før siste kommunesammenslåing) og det er noen feil i polygonene.
Effekter
Filterdefinisjonen i koden nedenfor er lånt fra Eddie Traversa's artikkel: "Scalable Vector Graphics: The Art is in the Code", fra www.webreference.com.
Koden er slik:
<svg width="200px" height="200px" viewBox="0 0 400 400"> <defs> <filter id="metallic"> <feGaussianBlur result="blurredAlpha" in="SourceAlpha" stdDeviation="3"/> <feOffset result="offsetBlurredAlpha" in="blurredAlpha" dx="2" dy="1"/> <feDiffuseLighting result="bumpMapDiffuse" in="blurredAlpha" surfaceScale="5" diffuseConstant="0.5" style="lighting-color:rgb(255,255,255)"> <feDistantLight azimuth="135" elevation="60"/> </feDiffuseLighting> <feComposite result="litPaint" in="bumpMapDiffuse" operator="arithmetic" k1="1" k2="0" k3="0" k4="0" in2="SourceGraphic"/> <feSpecularLighting result="bumpMapSpecular" in="blurredAlpha" surfaceScale="5" specularConstant="0.5" specularExponent="10" style="lighting-color:rgb(255,255,255)"> <feDistantLight azimuth="135" elevation="60"/> </feSpecularLighting> <feComposite result="litPaint" in="litPaint" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" in2="bumpMapSpecular"/> <feComposite result="litPaint" in="litPaint" operator="in" in2="SourceAlpha"/> <feMerge> <feMergeNode in="offsetBlurredAlpha"/> <feMergeNode in="litPaint"/> </feMerge> </filter> </defs> <g transform="translate(200,200)"> <circle cx="0" cy="0" r="100" style="filter:url(#metallic);fill:yellow;stroke:rgb(11,11,13);stroke-width:1"/> <circle cx="40" cy="-40" r="20" fill="rgb(10,10,10)"/> <circle cx="-40" cy="-40" r="20" fill="rgb(10,10,10)"/> <path d="M-40.0 40 C-30.0 50 -20 60 0 60 20 60 30 50 40 40 " style="fill:none;stroke:rgb(11,11,13);stroke-width:6"/> </g> </svg>