Budoucnost vektorové grafiky na webu, 2. část

Proč bychom měli kvůli vektorové grafice studovat hromadu nových nestandardních technik a postupů? Proč dělat věci dvojím způsobem? Proč ta schizofrenie, když nám stačí ty znalosti, které už máme dnes!

Skutečná síla spojení SVG+XHTML

Existuje standardní mechanismus, který dovoluje webdesignerům umístit do jednoho jediného XML souboru data v několika různých nářečích jazyka XML - jedná se o tzv. jmenné prostory XML ("name space").

Nepočítám-li Amayu, tak jsou Opera 9 a Mozilla Firefox 1.5 prvními dostupnými webovými prohlížeči, které dokážou kombinaci XHTML+SVG vykreslit.

Klepněte pro větší obrázek

Tento známý příklad pro Mozillu Firefox používá CSS pseudo-třídy ":hover" k vytvoření "roll-over" efektu (ukázka)

Aktualizováno: Demonstrační kód pocházel ve své originální podobě ze stránek Mozilla SVG. Původně jsem jej převzal, aniž by mne napadlo v něm hledat nějaké chyby. V tomto XML kódu se ale bohužel nacházelo několik věcí ne úplně splňujících podmínky normy SVG - a ty způsobily problémy prohlížeči Opera 9. Nyní je XHTML+SVG zcela ve shodě se standardem (a funkční v Opeře 9, Firefoxu 1.5, Safari 2 + SVG).

Nyní bych ctěné čtenáře rád upozornil speciálně na způsoby CSS formátování v ukázkách. Možnosti stylování grafických (!) prvků jsou velice rozsáhlé a přitom v podstatě identické (!) s postupy běžnými u textových dokumentů HTML.

<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:svg="http://www.w3.org/2000/svg" >
<head>
  <style>
    circle:hover {fill-opacity:0.9;}
  </style>
</head>
<body>
  <svg:svg>
    <svg:g style="fill-opacity:0.7;">
      <svg:circle cx="6cm" cy="2cm" r="100"
        style="fill:red; stroke:black; stroke-width:0.1cm"
        transform="translate(0,50)" />
      <svg:circle cx="6cm" cy="2cm" r="100"
        style="fill:blue; stroke:black; stroke-width:0.1cm"
        transform="translate(70,150)" />
      <svg:circle cx="6cm" cy="2cm" r="100"
        style="fill:green; stroke:black; stroke-width:0.1cm"
        transform="translate(-70,150)"/>
    </svg:g>
  </svg:svg>
</body>
</html>

Prvek SVG se chová jako blokový prvek CSS. Vtipnou demonstraci reálných výhod standardní vektorové grafiky představuje i následující ukázka, ve které jsem nadefinoval rozměry SVG bloku s id="vector2" pomocí relativních CSS souřadnic "em". Pokud si v prohlížeči změníte měřítko zobrazení, změní se potom spolu s velikostí písma i rozměry takto vložených SVG grafik. A tyto obrázky budou v libovolném zvětšení absolutně ostré, nerozmazané, nekostičkované!

Klepněte pro větší obrázek

Měňte si velikost okna prohlížeče jak chcete, ale SVG písmo na pozadí bude stále vyplňovat celou plochu a stále bude stejně hladké. Červeno-modrý vektorový tvar se zvětšuje spolu s textem (ukázka)

Praktická poznámka: Vykreslování písem - zvláště ve FF - není zatím zcela přesné. Vývojová verze DeerPark v současnosti vykresluje písma v tomto příkladu zcela špatně - použijte proto FF 1.5. Obzvláště zde, na rozhraní mezi HTML a SVG, vývojáři kráčí nevyšlapanou cestičkou... Bude asi ještě chvíli trvat než se vše 100% odladí - definice velikosti SVG bloku není bohužel ještě zcela spolehlivá a stejně funkční ve všech SVG prohlížečích. Opera 9 ovšem jednoznačně vede.

Povšimněte si jak přirozeně můžete pomocí CSS třídy nastavit kupříkladu parametry SVG prvku stop, definujícího bod na přechodu barev (viz druhý SVG blok s id="vector1"):

<?xml version="1.0" encoding="utf-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>SVG + XHTML + CSS</title>
  <style>
    html,body {
      font-family:`Helvetica CE`,Helvetica,sans-serif;
      border:0; margin:0; padding:0;
      position:absolute; z-index:0; left:0%; top:0%; width:100%; height:100%;
    }
    h1,p {
      padding:0px 16px;
    }
    <!-- následují styly pro SVG elementy -->
    text.tx0 {
      font-family:`Helvetica CE`,Helvetica,sans-serif;
      font-size:55px; fill:blue; fill-opacity:.2
    }
    stop.begin { stop-color:#dff; }
    stop.end { stop-color:#7af; }
  </style>
</head>
<body>

<h1>Příklad SVG + XHTML + CSS</h1>
<p>Tento XML dokument obsahuje data ve formátech XHTML a SVG.</p>
<p>Pozadí je vektorové a definuje jej SVG element s id=`vector1`.</p>
<p>
  <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="vector2"
    viewBox="0 0 100 100" width="3em" height="3em">
    <linearGradient id="gradient2">
      <stop stop-color="red" offset="0%"/>
      <stop stop-color="blue" offset="100%"/>
    </linearGradient>
    <polygon points="0,0 0,100 100,00"
             fill="url(#gradient2)"/>
    <circle cx="100" cy="100" r="71"
      fill="url(#gradient2)"
      transform="rotate(135,100,100)"/>
  </svg>
Na počátku tohoto odstavce je jako součást "tekoucího" textu vložen další SVG prvek s id=`vector2` a nastylován tak, aby se jeho velikost měnila spolu s textem.
</p>
<p>A to vše je jen jedna malá součást revoluce, kterou přináší nativní implementace SVG do světa webu!
</p>
  <svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="vector1"
    viewBox="0 0 100 100" preserveAspectRatio="none"
    style="position:absolute; top:0; left:0; width:100%; height:100%; z-index:-1;">
    <linearGradient id="gradient">
      <stop class="begin" offset="0%"/>
      <stop class="end" offset="100%"/>
    </linearGradient>
    <rect x="0" y="0" width="100" height="100" style="fill:url(#gradient)" />
    <text x="0" y="77" class="tx0" >SVG</text>
    <text x="9" y="66" class="tx0" >SVG</text>
    <text x="3" y="60" class="tx0" >SVG</text>
  </svg>
</body>
</html>

Kombinace různých druhů XML dat

SVG standard 1.1 vyžaduje od prohlížeče schopnost pracovat s prvky v cizím jmenném prostoru. Jinými slovy, pokud do SVG souboru vložíte data v jiném XML "name space", tato se stanou součástí objektového stromu DOM a je s nimi možno následně manipulovat využitím skriptovacího jazyka. Tím nám vypadává ze hry Opera 8, jelikož implementovaná SVG Tiny 1.1 neobsahuje podporu skriptování. Opera 9 za to už věc zvládá na jedničku.

Klepněte pro větší obrázek

Grafika vygenerovaná JavaScriptem z tabulkových dat vložených uvnitř SVG souboru (ukázka)

Obecná XML data vložená v SVG vypadají následovně:

 <data:polozka>
   <data:popis>výsledek</data:popis>
   <data:hodnota>7</data:hodnota>
 </data:polozka>

Tento příklad opět není v podstatě nikterak odlišný od "obyčejného" DHTML. Jen při hledání objektů navíc specifikujeme i konkrétní jmenný prostor ("name space"):

// ziska seznam s daty
seznamPopisu = doc.getElementsByTagNameNS(data_ns, "popis");
seznamHodnot = doc.getElementsByTagNameNS(data_ns, "hodnota");

To stejné při vytváření prvků pomocí funkcí DOM:

pathElement = doc.createElementNS(svg_ns, "path");

Jediné co je odlišné od HTML jsou jména prvků, se kterými pracujeme. Pro plné pochopení algoritmu je potřebné znát mj. význam atributu `d` v prvku path. (Zmíněný atribut obsahuje příkazy definující tvar křivek a čar.) V následující ukázce jsem odstranil některé méně zajímavé části:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" viewBox="0 0 1000 700" onload="onLoad(evt)">
<title>Generování SVG obrazu z dat v jiném XML "namespace"</title>

<defs>
<script type="text/ecmascript"><![CDATA[
var svg_ns = "http://www.w3.org/2000/svg";
var bd_ns = "http://example.org/Example";

function onLoad(evt){
  // ukazatel na objektovy model SVG dokumentu
  var svgElement = evt.target;
  var doc = svgElement.ownerDocument;

  // ukazatel na zdrojova XML data
  var resultsElement = doc.getElementById(`vysledky`);
  var gElement = doc.getElementById(`graf`);

  // spocita pocet polozek
  RegionNodeList = doc.getElementsByTagNameNS(bd_ns, "polozka");
  pocetPolozek = RegionNodeList.length;

  // ziska seznam s daty
  seznamPopisu = doc.getElementsByTagNameNS(bd_ns, "popis");
  seznamHodnot = doc.getElementsByTagNameNS(bd_ns, "hodnota");

  // zjisti maxHodn. hodnotu v grafu
  var maxHodn = 0, h;
  for (ix = 0; ix < pocetPolozek; ix++) {
    h = Number(seznamHodnot.item(ix).firstChild.nodeValue);
    if(h>maxHodn) maxHodn = h;
  }

  // generovani grafu
  for (ix = 0; ix < pocetPolozek; ix++) {
    popis = seznamPopisu.item(ix).firstChild.nodeValue;
    hodnota = Number(seznamHodnot.item(ix).firstChild.nodeValue);
    x = ix*1000/pocetPolozek + 70;
    y = 600 - hodnota*500/maxHodn;
    sirka = 1000/pocetPolozek/2.8;

    // textovy popis osy X
    textElement = doc.createElementNS(svg_ns, "text");
    textNode = doc.createTextNode(popis);
    textElement.appendChild(textNode);
    textElement.setAttributeNS(null, "x", x);
    textElement.setAttributeNS(null, "y", 640 );
    gElement.appendChild(textElement);

    ...

    // generovani elementu "path" pro sloupec
    pathElement = doc.createElementNS(svg_ns, "path");
    dAttribute = `M` + (x-sirka) + `,600 L`;
    dAttribute = dAttribute + (x-sirka) +  `,` + y + ` L`;
    dAttribute = dAttribute + (x+sirka) + `,` + y + ` L`;
    dAttribute = dAttribute + (x+sirka) + `,600 Z`;
    gray =  Math.round(Number(255 * (ix+2)) / (pocetPolozek+2));
    pathElement.setAttributeNS(null, "d", dAttribute);
    pathElement.setAttributeNS(null, "fill", "rgb("+gray+","+gray+","+gray+")");
    pathElement.setAttributeNS(null, "stroke", "black");
    pathElement.setAttributeNS(null, "stroke-width", "2");
    gElement.appendChild(pathElement);
  } /* ix */
} /* onLoad() */
]]></script>
</defs>

<g xmlns:data="http://example.org/Example">
<data:vysledky id="results">
 <data:polozka>
   <data:popis>výsledek</data:popis>
   <data:hodnota>7</data:hodnota>
 </data:polozka>
 <data:polozka>
   <data:popis>aa</data:popis>
   <data:hodnota>5</data:hodnota>
 </data:polozka>
 ...
</data:vysledky>
</g>

<text x="500" y="32" font-family="Helvetica" font-size="32" text-anchor="middle">
SVG graf automaticky vygenerovaný z obecných XML dat
</text>

<g id="graf" font-family="Helvetica" text-anchor="middle" font-size="24">
<desc>Na toto misto skript pripoji elementy grafu</desc>
</g>

<rect x="1" y="1" width="999" height="699" fill="none" stroke="blue"/>
</svg>

XSLT transformace

Další úžasné možnosti nativního SVG se otevírají při nasazení XSLT. Touto technologií můžeme konvertovat XML data do podoby vektorové grafiky jen za pomoci sofistikovaných stylopisů - bez jakýchkoli doplňkových programů či skriptů. Zdrojem může být databáze a cílem HTML nebo stejně tak dobře SVG.

V pokračování tohoto textu bych si rád posvítítil na použití XSLT transformací podrobněji tak, abyste je byli schopni sami použít např. k vytvoření grafu z číselných dat ve formátu XML (viz ukázka SVG grafiky o kousek níže).

Uvědomte si také, že navzdory poměrně malému využívání v současnosti - díky konzervativnímu přístupu dnešních webdesignerů - je XSLT velmi dobře zavedená technogie, která byla v prohlížečích IE a Mozilla Firefox implementována již před relativně dlouhou dobou a dnes tudíž už je spolehlivá a stabilní. Navíc současné verze zbývajících browserů Opera, Safari / Konqueror už její implementací disponují rovněž. (Nemluvě o existujících implementacích na straně serveru.) Takže: Zpět do budoucnosti!

Jdeme na věc, nastal čas

Nebojte se, buďte v pohodě. Vše co potřebujete je skutečně jen XML, skripty ponechte v minulosti! V následující ukázce vidíte útržek souboru ve standardním formátu tabulkového kalkulátoru Excel, vyexportovaný z Open Office verze 2:

<ss:Worksheet ss:Name="Tabulkový list 1">
  <Table ss:StyleID="ta1">
    <Column ss:StyleID="Default" ss:Span="1" ss:Width="64.2614"/>
    <Row ss:Height="12.8409">
      <Cell>
        <Data ss:Type="Number">
          0
        </Data>
      </Cell>
      <Cell ss:Formula="=SIN(RC[-1])*COS(RC[-1])">
        <Data ss:Type="Number">
          0
        </Data>
      </Cell>
    </Row>

  ...

  </Table>
  <x:WorksheetOptions/>
</ss:Worksheet>

Jediné co je třeba udělat pro získání regulérní webové stránky je přidání odkazu na transformační styl XSLT do hlavičky XML dat:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="table2svg.xsl" media="screen"?>

<?mso-application progid="Excel.Sheet"?>
<Workbook ...>
...
</Workbook>

Dotyčný XML soubor nyní můžete směle předhodit libovolnému modernímu prohlížeči (Mozilla Firefox 1.5, Opera 9, Safari 2 s SVG podporou) a voi-la - tak jednoduché to je!

Klepněte pro větší obrázek

Graf ve formátu SVG vygenerovaný automaticky mechanismem XSLT z tabulkových dat exportovaných z běžné aplikace typu Office (ukázka)

Webové služby atd.

A nakonec zmíním potenciální možnost využití pro vizualizaci (opět XML) dat získaných pomocí tzv. "webových služeb". Mozilla Firefox standardně obsahuje podporu pro SOAP i WSDL, takže v cestě nestojí absolutně nic.

Stručný přehled SVG standardu a jeho podpory v Mozille Firefoxu 1.5

  1. vektorové tvary - ANO
  2. jednobarevné výplně - ANO
  3. přechody barev - ANO
  4. textury - NE
  5. text + tspan - ANO
  6. tref (text odkazem) - NE
  7. text na křivce - NE
  8. SVG písma - NE
  9. transformace - ANO
  10. ořezávání (clipping) - ANO
  11. maskování (masking) - NE
  12. bitmapové filtry - NE
  13. animace SMIL - NE
  14. skriptování - ANO

Implementace SVG v Mozille Firefoxu 1.6 (DeerPark)

  1. vektorové tvary - ANO
  2. jednobarevné výplně - ANO
  3. přechody barev - ANO
  4. textury - ANO
  5. text + tspan - ANO
  6. tref (text odkazem) - NE
  7. text na křivce - ANO
  8. SVG písma - NE
  9. transformace - ANO
  10. ořezávání (clipping) - ANO
  11. maskování (masking) - NE
  12. bitmapové filtry - cca 25%
  13. animace SMIL - cca 15%
  14. skriptování - ANO

Témata článku: Software, Budoucnost, Programování, Firefox, Opera, Libovolný bod, Gradient, Grafika, FF, Translate, Smile, Head, Ostré písmo, Cell, Grafik, Pseudo, Stop, Graf, Transform

Určitě si přečtěte

Tesla chce změnit nákladní dopravu. Její elektrický náklaďák má ohromující parametry

Tesla chce změnit nákladní dopravu. Její elektrický náklaďák má ohromující parametry

** Tesla představila elektrický kamion ** Má obdivuhodný výkon i dojezd ** Prodávat by se měl už za dva roky

17.  11.  2017 | Vojtěch Malý | 226

Elektronika, která nepotřebuje kabel ani baterii. Živí se rádiovým šumem

Elektronika, která nepotřebuje kabel ani baterii. Živí se rádiovým šumem

** Každá elektrická krabička má konektor pro napájení nebo baterii ** Jenže pozor, jednou by to tak nemuselo být ** Drobná elektronika se může živit rádiovými vlnami

14.  11.  2017 | Jakub Čížek | 15

Nejlepší notebooky do 10 tisíc, které si teď můžete koupit

Nejlepší notebooky do 10 tisíc, které si teď můžete koupit

** I pod hranicí desíti tisíc korun existují dobře použitelné notebooky ** Mohou plnit roli pracovního stroje i zařízení pro zábavu ** Nejlevnější použitelný notebook koupíte za pět a půl tisíce

16.  11.  2017 | Stanislav Janů | 53


Aktuální číslo časopisu Computer

Otestovali jsme 5 HDR 4K televizorů

Jak natáčet video zrcadlovkou

Vytvořte si chytrou domácnost

Radíme s koupí počítačového zdroje