SVG
Vi ønsker selvsagt å inludere SVG i vevsider som også består av andre språkelementer. Typisk vil vi ha en side med XHTML og SVG, eller XHTML, SVG og MathML, eller XHTML, SVG og RDF. Mer om dette senere. Vi starter med noen rene SVG-dokumenter for å illustrere noen grunnleggende prinsipper.
Et rektangel
Et enkelt SVGdokument, svgdok1.svg, kan se slik ut:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="5cm" height="5cm" viewBox="0 0 50 50"
xmlns="http://www.w3.org/2000/svg">
<desc>Et enkelt eksempel</desc>
<rect x="10" y="10" width="20" height="20"
fill="yellow" stroke="blue" stroke-width="2"/>
</svg>
Vi har etablert en fil med riktig dtd, og vi har et rotelement: svg. Dette elementet er kvalifisert via et namspace og vår SVG-tegning beslaglegger et område på 5x5 cm. Det adresseområdet 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(, så svenskene får sitt). 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.
Flagget
Det norske flagget kan lages slik:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="300px" height="300px" viewBox="0 0 300 300"
xmlns="http://www.w3.org/2000/svg">
<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ørst, 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, svgsmiley1.svg:
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg width="200px" height="200px" viewBox="0 0 400 400" xmlns="http://www.w3.org/2000/svg"> <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 enklsete 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, svgsmiley2.svg
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="200px" height="200px" viewBox="0 0 400 400"
xmlns="http://www.w3.org/2000/svg">
<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, svgtext1.svg:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="400px" height="400px" viewBox="0 0 400 400"
xmlns="http://www.w3.org/2000/svg">
<desc>litt ymse tekst</desc>
<g transform="translate(200,200)">
<text id="TextElement" x="0" y="0"
transform="rotate(-30)"
font-family="Verdana" font-size="20"
fill="blue" stroke="none">
Hallo dette ble skjevt
</text>
<text id="TextElement" 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,svgtext2.svg.
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="400px" height="500px" viewBox="0 0 500 400"
xmlns="http://www.w3.org/2000/svg">
<desc>litt dynamisk tekst</desc>
<g transform="translate(200,200)">
<text id="TextElement" 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, svgtext3.svg:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="200px" height="200px" viewBox="0 0 400 400"
xmlns="http://www.w3.org/2000/svg">
<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 er ganske raskt.
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):
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="100%" height="100%" viewBox="0 0 11939 15026"
xmlns="http://www.w3.org/2000/svg">
<desc>Norgeskart</desc>
<!-- ECMAScript to identify a kommune after mouseover -->
<script code="text/ecmascript"> <![CDATA[
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.getFirstChild());
}
]]> </script>
<g transform="translate(250,1250)">
<text id="TextElement" x="0" y="0" font-family="Verdana"
font-size="500" fill="black">
Norge
</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"/>
<path onmouseover="kommune_click(evt)" id="Sarpsborg"
d="M 3599,1314 L 3594,1324 ... z" fill="none" stroke="black"/>
<path onmouseover="kommune_click(evt)" id="Fredrikstad"
d="M 3509,1154 L 3509,1171 ... z" fill="none" stroke="black"/>
...
</g>
</g>
</svg>
Den komplette kildekoden finner du her: norge_svg.html.
Merk at dataene er gamle (før siste kommunesammenslåing) og det er noen feil i polygonene.
Som del av et dokument
Utgangspunktet er at vi ønsker å legge SVG-komponenter inn på en HTML-side. Det er flere måter å tenke seg dette løst på:
Vi kan tenke oss en løsning der vi rett og slett legger SVG-elementene på plass og kvalifiserer dem med namespace, De fleste lærebøkene i XML bruker slike filer om eksempel:
<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>mixed SVG</title>
</head>
<body>
<h1>En side</h1>
<svg xmlns="http://www.w3.org/2000/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>
<p>med blandet innhold</p>
</body>
</html>
Dette forutsetter at programmet som leser fila er forberedt på å generere SVG når den treffer på en slk node i DOM-treet. Nettleserne synes ikke være klare for det, og greier ikke å kople plug-ins til slik SVG-rendering.
Dersom SVG blir akseptert som en del av det normale nettlesere skal kunne handtere uten plug-in vil denne koden være den naturlige formen å inkludere SVG på.
Alternativet er å bruke det generelle <embed> </embed> elementet, slik vi gjør når vi vil legge inn andre komponenter som fordrer plug-in. Følgende element vi vise fila etbilde.svg, eventuelt tilby seg å installere plug-in først:
<embed width="100px" width="100px" src="supersmiley.svg"
pluginspace="http://www.adobe.com/svg/viewer/install/">