Navigace

Hlavnφ menu

 

Kurz SVG - DOM a JavaScript p°i programovßnφ animacφ

V tomto Φlßnku vßs Φekß prvnφ pomoc p°i programovßnφ (alias skriptovßnφ) v prost°edφ SVG. ZφskanΘ znalosti si hned vyzkouÜφme v n∞kolika zajφmav²ch praktick²ch p°φkladech. Myslφte si nap°φklad, ₧e znßte vÜechny v²hody, kterΘ majφ vektorovΘ mapy v SVG formßtu? Mo₧nß ano, ale i tak se vßs pokusφm p°esv∞dΦit, ₧e SVG mapy toho dovedou jeÜt∞ vφce, ne₧ jste Φekali.

Jeliko₧ ne vÜechny ·lohy lze zvlßdnout jen s animaΦnφmi prvky SVG specifikace, podφvßme se na mo₧nosti, kterΘ nßm nabφzφ skriptovßnφ. U₧ d°φve jsem v tomto kurzu n∞kolikrßte zmi≥oval, ₧e zvlßdßte-li techniku DHTML, jako byste ji₧ um∞li programovat i SVG. V nßsledujφcφm textu tΘto podobnosti tak trochu zneu₧iji a upozornφm vßs spφÜe na odliÜnosti a specifika SVG, ne₧ abych vysv∞tloval vÜe od zßkladu.

Pozor, nßsledujφcφ text p°edpoklßdß, ₧e s JavaScriptem ji₧ n∞jakΘ zkuÜenosti mßte a ₧e rovn∞₧ mßte p°edstavu o objektovΘ datovΘ struktu°e HTML (XML) strßnek. V p°φpad∞ pot°eby odkazuji na n∞kterΘ z nesΦetn²ch text∙ o DOM (Document Object Model) a DHTML, z nich₧ °ada je dostupnß i zde na Intervalu. V tomto textu nynφ zmφnφm jen n∞kterΘ zßkladnφ a nejΦast∞ji pou₧φvanΘ konstrukce. Detaily SVG-DOM bez problΘmu dohledßte v dokumentaci k ASV3.

Test aktivnφho SVG prohlφ₧eΦe

Hned ze zaΦßtku sΘrie text∙ o SVG jste se o Adobe SVG3 prohlφ₧eΦi mohli dozv∞d∞t, ₧e jednφm z hlavnφch rozdφl∙ oproti p°edchozφ verzi je implementace plnohodnotnΘho interpreteru JavaScriptu. Tato informace je pro nßs nynφ klφΦovß. Programßto°i firmy Adobe tφm v²razn∞ zv²Üili kompatibilitu prohlφ₧eΦe nap°φΦ vÜemi platformami a r∙zn²mi webov²mi prohlφ₧eΦi. Osobn∞ siln∞ doporuΦuji jako prvnφ krok p°i spouÜt∞nφ jak²chkoli skript∙ v SVG prost°edφ provΘst test verze prohlφ₧eΦe. Dovoluji si vßm nabφdnout svΘ odlad∞nΘ °eÜenφ:

<script type="text/ecmascript">
<![CDATA[
function testAdobe() {
  //created by Martin Hejral, 2003
  //test if Adobe SVG Viewer 3 (ASV3) or greater is present
  if(window.navigator)
    if( (navigator.appName=="Adobe SVG Viewer")
     && (navigator.appVersion>="3.0") )
      return true;
  alert("PROSIM, nainstalujte novou verzi Adobe SVG prohlizece!!!");
  return false;
}
]]>
</script>

A hned mohu dodat, ₧e zßpis k≤du uvnit° SVG souboru se °φdφ obecn²mi XML pravidly, proto je nutnΘ programovΘ k≤dy v₧dy uzav°φt do sekce CDATA, jak jste si vÜichni urΦit∞ povÜimli v p°edchßzejφcφm v²pisu.

Nejd∙le₧it∞jÜφ p°φkazy a postupy

Toto je notoricky znßmß konstrukce, kterou zaΦφnß tΘm∞° ka₧d² DHTML (a SVG) skript, kter² pracuje s DOM. Zjistφme takto ukazatel na objekt, se kter²m pot°ebujeme pracovat - a¥ u₧ Φφst jeho atributy, nebo n∞co modifikovat.

//zjisti ukazatel na SVG objekt
var obj = document.getElementById("nejake_id");

Adobe doporuΦuje ke stejnΘmu ·Φelu o n∞co slo₧it∞jÜφ postup. Ten vznikl p°edevÜφm k zamezenφ mo₧n²ch problΘm∙ v p°φpadech, kdy skript provßd∞l webov² prohlφ₧eΦ (v ASV2) a v HTML strßnce bylo souΦasn∞ vlo₧eno n∞kolik SVG prvk∙.

<svg onload="svgInitialize(evt)" width="320" height="200">

...

var svgDocument = null; //globalni promenna

function svgInitialize(evt)
{
svgDocument = evt.getTarget().getOwnerDocument();
var obj = svgDocument.getElementById("nejake_id");
...
}

...

Vidφte, ₧e namφsto toho, aby se vyu₧il standardnφ objekt document, je zjiÜ¥ovßn objekt "vlastnφcφ" ty konkrΘtnφ SVG prvky, se kter²mi zrovna pot°ebujeme pracovat. (Abych byl zcela p°esn², hledßme vlastnφka objektu, kter² byl zdrojem udßlosti onload, tedy prvku svg.) Pro ka₧d² vlo₧en² SVG soubor se toti₧ vytvo°φ jeden dalÜφ objekt document.

Pom∞rn∞ hojn∞ vyu₧φvanΘ jsou i nßsledujφcφ p°φkazy, rovn∞₧ znßmΘ z DHTML:

  • window.status="text" - prom∞nnß
  • window.alert("text") - funkce

V²znamnΘ usnadn∞nφ prßce p°i programovßnφ vßm poskytnou funkce zjednoduÜujφcφ prßci s atributy SVG element∙ - jejich slu₧eb vyu₧ijete p°i prßci s SVG velmi Φasto:

  • obj.getAttribute( "transform" )
  • obj.setAttribute( "transform", "translate(11,22)" )

Nßsledujφcφ v²pis ukazuje, jak modifikovat a Φφst obsah atributu style. Prozatφm p°φliÜ nedoporuΦuji pou₧φvßnφ style z d∙vod∙ kompatibility, jeliko₧ prohlφ₧eΦe mΘn∞ vysp∞lΘ ne₧ ASV2 v∞tÜinou CSS zatφm uspokojiv∞ nepodporujφ.

var svgobj = svgdoc.getElementById("nejake_id");
if (svgobj != null)
{
var svgstyle = svgobj.getStyle();
var fill = svgstyle.getPropertyValue("fill");
svgstyle.setProperty("stroke","#69F");
svgstyle.removeProperty("stroke-width");
}

K hodnotßm atribut∙ uvnit° struktury SVG-DOM se m∙₧eme dostat alternativn∞ takΘ nßsledujφcφm zßpisem:

  • svgobj.attributes.getNamedItem("nazev_atr").value

ZvlßÜt∞ v p°φpad∞ animacφ jsou Φasto pou₧itelnΘ obecnΘ funkce JavaScriptu pro prßci s p°eruÜenφm a Φasovßnφm:

  • var casovac = window.setTimeout("nejaka_funkce()", 50)
  • window.clearTimeout(casovac)

Obsluha udßlostφ

DalÜφ oblφbenou Φinnostφ, kterou jist∞ budete chtφt provozovat takΘ, je obsluha udßlostφ u₧ivatelskΘho rozhranφ - tu velmi Φasto vyu₧ijete p°i vytvß°enφ interaktivnφch grafick²ch prezentacφ. Dovolφm si shrnout nejd∙le₧it∞jÜφ praktickΘ informace, kterΘ k tomu budete pot°ebovat.

SVG p°i obsluze udßlostφ pou₧φvß model shodn² s dob°e znßmou normou DOM2-Events, pou₧φvan² v prohlφ₧eΦφch Netscape a Mozilla (MSIE se trochu odchyluje). Ka₧dß obslu₧nß rutina toti₧ dostane jako parametr specißlnφ objekt event, kter² nese informace pot°ebnΘ k reakci na konkrΘtnφ udßlost. Pozor, zßvazn² nßzev tohoto specißlnφho objektu v ASV je evt (na rozdφl od klasick²ch WWW browser∙)!

JednotlivΘ polo₧ky ve struktu°e objektu evt pak jsou ji₧ shodnΘ. Ty nejzajφmav∞jÜφ si nynφ vyjmenujeme:

  • target - zdrojov² objekt udßlosti
  • currentTarget - aktußlnφ objekt, ke kterΘmu je p°ipojen obslu₧n² skript (event listener)
  • screenX - X v sou°adnicovΘm systΘmu obrazovky
  • screenY - Y v sou°adnicovΘm systΘmu obrazovky
  • clientX - X relativn∞ vzhledem k oknu (rßmu) SVG grafiky
  • clientY - Y relativn∞ vzhledem k oknu (rßmu) SVG grafiky
  • ctrlKey
  • shiftKey
  • altKey
  • metaKey
  • button
  • keyCode
  • charCode

Animace s vyu₧itφm DOM a JavaScriptu

A vzh∙ru do praxe...

Fyzikßlnφ pokus - koule a pru₧iny

Nynφ si vyzkouÜφme realizaci znßmΘho fyzikßlnφho pokusu, kdy koule, zav∞Üenß na pru₧in∞, po jejφm napnutφ a uvoln∞nφ kmitß s klesajφcφ amplitudou okolo rovnovß₧nΘ polohy.

Fyzikßlnφ pokus - koule a pru₧iny
Fyzikßlnφ pokus - koule a pru₧iny (originßlnφ SVG, cca 5 kB)

V prvnφ fßzi jsem si v Illustratoru nakreslil jednoduchΘ ztvßrn∞nφ pru₧iny (skupina s id="spring") a koule (skupina s id="sphere"). Dovnit° ka₧dΘ skupiny jsem pak dodal animaΦnφ prvky. Musφ b²t dva, proto₧e v p°φpad∞ pru₧iny pot°ebujeme animovat smrÜ¥ovßnφ, naproti tomu koule jen m∞nφ polohu...

<g id="spring">
  ...
  <!-- anim. pruziny -->
  <animateTransform attributeName="transform"
    type="scale" values="1 1;1 0.32;1 1" dur="10s"
    additive="sum" repeatCount="indefinite" />
</g>
<g id="sphere">
  ...
  <!-- anim. koule -->
  <animateTransform attributeName="transform"
    type="translate" values="0 0;0 -100;0 0" dur="10s"
    additive="sum" repeatCount="indefinite" />
</g>

Definice pohybu pomocφ values ovÜem ve v²chozφm (lineßrnφm) interpolaΦnφm re₧imu vede k fyzikßln∞ nesprßvnΘmu ΦasovΘmu °φzenφ animovan²ch hodnot. Abych dosßhl realistickΘ zm∞ny zrychlenφ, kterß p°i tomto fyzikßlnφm procesu probφhß, nastavil jsem v²poΦetnφ re₧im na calcMode="spline" a p°idal dv∞ °φdicφ k°ivky do atributu keySplines=".5 0 .5 1;.5 0 .5 1". Navφc byly v druhΘ fßzi koule a pru₧ina definovßny jako symboly, abychom je mohli "rozmno₧it":

<use x="50" xlink:href="#spring">
  <!-- anim. -->
  <animateTransform
    attributeName="transform" type="scale"
    values="1 1;1 0.32;1 1" dur="10s"
    keySplines=".5 0 .5 1;.5 0 .5 1" calcMode="spline"
    additive="sum" repeatCount="indefinite" />
</use>
<use x="50" xlink:href="#sphere">
  <!-- anim. -->
  <animateTransform
    attributeName="transform" type="translate"
    values="0 0;0 -100;0 0" dur="10s"
    keySplines=".5 0 .5 1;.5 0 .5 1" calcMode="spline"
    additive="sum" repeatCount="indefinite" />
</use>

Stßle ale z∙stßvß opominut jeden fyzikßlnφ aspekt - v reßlnΘm sv∞t∞ bude v₧dy dochßzet ke ztrßt∞ energie kmitajφcφ soustavy a kmity se budou utlumovat. Mohli bychom to ud∞lat zp∙sobem, kter² pou₧il v podobnΘm p°φkladu s kostkami Antoine Quint, ale ten je nep°esn² a nßroΦn² na vypisovßnφ mno₧stvφ polohov²ch ·daj∙.

Proto si nynφ ukß₧eme p°φm² v²poΦet animaΦnφch fßzφ pomocφ JavaScriptu. Prosφm ct∞nΘ Φtenß°e, nekamenujte mne za nep°esnosti a zjednoduÜovßnφ ve fyzikßlnφ strßnce v∞ci, st°edem zßjmu stßle z∙stßvß vektorovß grafika:

//global variables
var amp=50, scale=0.34, time=0, to=-1;
//perform fading animation
function fade() {
  //get pointer to animated objects
  var obj1 = document.getElementById('sphere1');
  var obj2 = document.getElementById('spring1');
  var s = y = Math.cos(time/1000);
  //window.status="time = "+time/1000+" s";
  //multiply COS t with amplitude
  y *= amp;
  //shift sphere to base position
  y -= 50;
  //scale spring
  s *= scale;
  //set base position
  s += 0.34 + 0.32;
  time += 50;
  //amplitude and scale decay
  amp = amp*999/1000;
  scale = scale*999/1000;
  //modify SVG graphics
  obj1.setAttribute( "transform", "translate(0,"+y+")" );
  obj2.setAttribute( "transform", "scale(1,"+s+")" );
  //start timer
  to = window.setTimeout("fade()", 50);
}

Uveden² k≤d vykonßvß zhruba nßsledujφcφ. Ihned potΘ, co zjistφ ukazatele na animovanΘ objekty, pou₧ije funkci cos() k v²poΦtu animovan²ch hodnot: y - aktußlnφ poloha koule, s - aktußlnφ nata₧enφ pru₧iny. Jeliko₧ byla pru₧ina nakreslena v pln∞ nata₧enΘ poloze, byl jsem nßsledn∞ donucen do v²poΦtu p°idat mo₧nß pon∞kud zßhadnΘ konstanty (50, 0.34, 0.32). Pak se posuneme po ΦasovΘ ose zv²Üenφm prom∞nnΘ time, utlumφme amplitudu a aplikujeme vypoΦtenΘ hodnoty na SVG objekty (setAttribute).

Nakonec nastavφme ΦasovaΦ, kter² rutinu fade() spustφ znovu po 50 ms.

Äivot brouka

Tato animace op∞t vychßzφ z p°φkladu firmy Macromedia, ve kterΘm je beruÜka ovlßdßna virtußlnφm joystickem.

Op∞t jsem si trochu ulehΦil prßci, o°ezal jsem p°φklad a₧ na holΘ jßdro a vypustil n∞kterΘ vlastnosti originßlu. Pokud jste poctiv∞ doΦetli a₧ sem, mßte vÜechny pot°ebnΘ znalosti, kterΘ vßm umo₧nφ napsat JavaScriptovou rutinu kterß by nap°φklad stejn∞ jako v SWF p°edloze pohybovala °φdicφ pßkou (n∞co velmi podobnΘho obsahuje i p°φklad s animacφ masky obrßzku).

Hned prvnφ varianta SVG p°φkladu naznaΦuje mo₧nosti °eÜenφ tΘto interaktivnφ animace bez pou₧itφ programovßnφ. Bohu₧el, ovlßdßnφ beruÜky pomocφ sm∞rovΘho k°φ₧e takto nelze stoprocentn∞ realizovat - neexistuje toti₧ mo₧nost, aby animaΦnφ prvek po ukonΦenφ a p°i novΘm startu p°iΦφtal rostoucφ hodnoty sou°adnic k poloze, ve kterΘ byla p°edtφm animace ukonΦena (beruÜka zastavena), proΦe₧ pohyb zaΦφnß v₧dy znovu od poΦßteΦnφch sou°adnic danΘho animaΦnφho prvku.

Pozn. aut.: Tak₧e asi podßme nßvrh na rozÜφ°enφ normy SVG o pam∞¥ov² efekt animaΦnφch element∙ - navrhuji atribut "memory" s mo₧n²mi hodnotami "replace" a "sum" kv∙li konzistentnosti s atributy "additive" a "accumulate".

Prozatφm vßm nabφzφm °eÜenφ pomocφ JavaScriptu v druhΘ verzi p°φkladu. SVG k≤d je pro vaÜe pohodlφ pom∞rn∞ podrobn∞ okomentovßn.

Tento kousek SVG je zobrazenφm ovlßdacφho k°φ₧e s p°ipojenou rutinou onmouseover="beetleMania(evt)", kterß je potom aktivovßna kdykoli se ukazatel dostane nad zobrazenφ Üipek. P°i pozornΘm Φtenφ k≤du zjistφte, ₧e ve skuteΦnosti je kresba neviditelnß. D∙vod? P∙vodnφ sm∞rov² k°φ₧ byl toti₧ nakreslen jako jedna spojitß vektorovß cesta - to by ale neumo₧nilo jednoduchΘ rozpoznßnφ sm∞ru... Aby prvky v∙bec reagovaly na udßlosti, musφ b²t vykresleny, a jeliko₧ souΦasn∞ chceme vid∞t p∙vodnφ kresbu, nastavil jsem jim prost∞ stoprocentnφ pr∙hlednost pomocφ opacity="0".

<g id="control" opacity="0" onmouseover="beetleMania(evt)">
  <path id="n" d="M61,31.4V20.1h5.6L55,0L43.3,20.1h6v11.2"/>
  <path id="nw" d="M41.5,34.8L33,26.2l2.8-2.8L19,18.9l4.4,16.9l2.8-2.8l8.7,8.7"/>
  <path id="ne" d="M75,41.6l8.6-8.6l2.8,2.8L91,18.9l-16.9,4.5l2.8,2.8l-8.5,8.5"/>
  <path id="e" d="M77.9,60.8h11.9v5.8l20.1-11.7L89.8,43.2V49H78.1"/>
  <path id="w" d="M31.8,49H20.2v-5.8L0,54.9l20.2,11.7v-5.8h11.9"/>
  <path id="se" d="M67.7,74.5l9.2,9.2l-2.8,2.8L91,90.9L86.5,74l-2.9,2.9l-9.1-9.1"/>
  <path id="s" d="M49.2,77.5v12.3h-6L55,109.8l11.7-20.1H61V77.4"/>
  <path id="sw" d="M35.3,67.8l-9.1,9.1l-2.8-2.8L19,91l16.9-4.5L33,83.7l9.2-9.3"/>
</g>

Podprogram beetleMania(evt) si snadno zjistφ id prvku (evt.target.id), kter² spustil udßlost, a podle n∞j nastavφ sm∞r pohybu:

//'evt' is standard name of event object
function beetleMania(evt) {
  //get 'id' of control element to determine direction
  var ctrl = evt.target.id;
  switch(ctrl) {
  case 'n': dx=0; dy=-1; mrot=0;
  break;
  case 'ne': dx=1; dy=-1; mrot=45;
  break;
  case 'e': dx=1; dy=0; mrot=90;
  break;
  case 'se': dx=1; dy=1; mrot=135;
  break;
  case 's': dx=0; dy=1; mrot=180;
  break;
  case 'sw': dx=-1; dy=1; mrot=-135;
  break;
  case 'w': dx=-1; dy=0; mrot=-90;
  break;
  case 'nw': dx=-1; dy=-1; mrot=-45;
  break;
  }
  //stop event bubbling
  evt.stopPropagation();
  return false;
}

Pokud alespo≥ trochu vlßdnete JavaScriptem, jist∞ pro vßs nebude problΘmem cviΦn∞ naprogramovat druhou variantu pohybu, kdy se beruÜka otßΦφ plynule, nikoli skokov∞.

Vlastnφ pohyb (a modifikace SVG-DOM) zajiÜ¥uje rutina beetleMove(), opakovan∞ spouÜt∞nß ΦasovaΦem:

function beetleMove(evt) {
  //get pointer to animated object
  var obj = document.getElementById('beetle');
  mx += dx; my += dy;
  if(mx < -128) mx = 128;
  else if(mx > 128) mx = -128;
  if(my < -128) my = 128;
  else if(my > 128) my = -128;
  obj.setAttribute("transform",
    "translate("+mx+","+my+") rotate("+mrot+")");
  to = window.setTimeout("beetleMove()", 22);
}

Interaktivnφ ₧elezniΦnφ mapa ╚R

V tomto p°φkladu si dovolφm troÜiΦku vylepÜit interaktivnφ SVG mapu ze serveru ╚esk²ch drah. Na okraj jeÜt∞ jednu poznßmku k ovlßdßnφ Adobe SVG prohlφ₧eΦe - zmenÜovßnφ Φi zv∞tÜovßnφ m∞°φtka lze provΘst i myÜφ, pokud podr₧φte klßvesu CTRL, respektive CTRL+SHIFT, a posuv mapy lze realizovat kombinacφ ALT+myÜ, jak je sprßvn∞ uvedeno v map∞.

Interaktivnφ ₧elezniΦnφ mapa ╚R
Interaktivnφ ₧elezniΦnφ mapa ╚R (velk² nßhled, cca 55 kB, originßlnφ SVG, cca 30 kB)

V rßmci naÜeho SVG kurzu jsem p°idal "roll-over" efekty (pomocφ animaΦnφch prvk∙ set) a souΦasn∞ "kontextovou" nßpov∞du, kterß ukazuje velkΘ Φφslo trati (JavaScript).

K mod°e zbarven²m tratφm byl cviΦn∞ pomocφ animaΦnφho prvku set dodßn zv²raz≥ovacφ efekt:

<path class="fil0 str4" d="M2833 3681l-23 106">
  <set attributeName="stroke" to="magenta"
    begin="mouseover" end="mouseout"/>
</path>

To byla hraΦka, zbytek u₧ bude troÜiΦku komplikovan∞jÜφ. Vyu₧il jsem toho, ₧e SVG ╚esk²ch drah obsahuje hyperlinky na jφzdnφ °ßdy, p°iΦem₧ Φφslo trati je v₧dy obsa₧eno v nßzvu odkazovanΘho dokumentu - prost∞ jsem je z atributu xlink:href v objektovΘ struktu°e vyextrahoval:

var trat = obj.attributes.getNamedItem("xlink:href").value;

V SVG jsem si p°edem vytvo°il textov² prvek s id="info", do kterΘho nφ₧e uvedenß rutina zapφÜe Φφslo trati a souΦasn∞ jej p°emφstφ na sprßvnΘ sou°adnice.

Program, kter² jsem vytvo°il, Üikovn∞ vyu₧φvß efektu zvanΘho event-bubbling - rutinu odchytßvajφcφ pohyb myÜi mi pak staΦilo umφstit do ko°ene objektovΘho stromu a poΦkat si, a₧ dotyΦnß udßlost probublß a₧ k nφ. Pak testuji, zda se jednß o prvek typu a (hyperlink). M∙₧e se vßm zdßt divnΘ, proΦ netestuji zdrojov² objekt udßlosti (evt.target), nybr₧ jeho rodiΦe (evt.target.parentNode). Je to proto, ₧e udßlost onmouseover m∙₧e spustit pouze viditeln² objekt - co₧ jsou Φßry znßzor≥ujφcφ jednotlivΘ trat∞, hyperlinky jsou jim v naÜem SVG souboru p°φmo nad°azeny:

<a xlink:href="../k130.pdf" target="_blank">
  <path class="fil0 str4" d="M-2472 1338l-294 -23">
  <set attributeName="stroke" to="magenta"
    begin="mouseover" end="mouseout"/>
  </path>
</a>

DalÜφ velmi zajφmavou vlastnostφ, je₧ by rozhodn∞ nem∞la z∙stat nepovÜimnuta, je zjiÜt∞nφ aktußlnφho zv∞tÜenφ a posunutφ grafiky v SVG Vieweru (nezapome≥me - vektorovou grafiku lze neomezen∞ zv∞tÜovat bez ztrßty kvality) a nßsledn² p°epoΦet sou°adnic umis¥ovanΘho objektu.

//kontextova napoveda, Martin Hejral, 2004
function napoveda(evt) {
  //evt = objekt 'event' s informacemi o udalosti
  //zjisti ukazatel na textovy informacni objekt
  var obj = document.getElementById('info');
  //zjisti jmeno tagu zdrojoveho objektu
  var tag = evt.target.parentNode.tagName.toLowerCase();
  if(tag == "a") {
    //extrahuje cislo trati z odkazu
    //na PDF soubor s jizdnim radem
    //a vlozi jej do text. prvku
    //kontextove napovedy
    obj.firstChild.nodeValue =
      evt.target.parentNode.attributes.
      getNamedItem("xlink:href").value.substring(4,7);
  }
  //nasledujici data potrebujeme abychom
  //se prizpusobili aktualnimu zvetseni
  //v prohlizeci SVG
  meritko = document.rootElement.currentScale;
  posun = document.rootElement.currentTranslate;
  //nastavi polohu textu podle polohy mysi
  obj.setAttribute("transform", "translate("
      + (evt.clientX-posun.x)/meritko + ","
      + (evt.clientY-posun.y)/meritko + ")");
  //pripadne 'bublani' muze pokracovat
  return evt;
}

To¥ vÜe. Jen za sebe dodßm, ₧e p°esn∞ zde je skrytß velkß sφla grafiky ve znaΦkovacφm jazyce SVG, zde se otevφrß spousta mo₧nostφ pro aplikace. Äiv∞ si p°edstavuji t°eba detailnφ mapu m∞sta, kde jsou vÜechny objekty podrobn∞ popsßny ve standardnφch prvcφch title a desc - skript velmi podobn² tomu zde p°edstavenΘmu pak dßvß u₧ivateli tΘto mapy mo₧nost velmi pohodln∞ tyto informace zφskat...

Kurz SVG - tvorba vektorovΘ grafiky v XML

Pokud u₧ mßte dost suchΘ teorie Scalable Vector Graphics, nenφ nic sna₧Üφho, ne₧ se vrhnout na praktickΘ testovßnφ jeho mo₧nostφ. Kurz SVG vßm usnadnφ osvojenφ zßkladnφch struktur a vlastnostφ tohoto jazyka pro prßci s vektorovou grafikou. Tato sΘrie Φlßnk∙ dosud nebyla ukonΦena!

Hejral, Martin (24. 11. 2004)