XAML.cz Magazín moderních technologií založených na XAML

Silverlight preloader

Napsáno pro Silverlight od Jarda Jirava  [12.10.2010]

Nyní už víme, jakým způsobem zpřístupnit Silverlight aplikaci uživateli a také, jak mu dopřát uživatelský zažitek před tím, než si nainstaluje Silverlight plugin. Co bych rád popsal v dnešním článku je, jak uživateli zpříjemnit chvíle před tím, než se mu naše Silverlight aplikace nahraje do prohližeče.

Představte si, že jste vytvořili Silverlight aplikaci, která je co do velikosti výsledného souboru větší než jste předpokládali. A přitom se nechcete smířit s tím, že se spokojíte s výchozím preloaderem, který ukazuje průběh v podobě načítání procent, okolo kterého běhají zvětšující se a zmenšující kolečka.

výchozí preloader

Samozřejmě i nyní máte možnost upravit si tento Silverlight preloader, u desktopových aplikací by se spíše řeklo splash screen, a vytvořit si vlastní, který se zobrazí uživateli. Tento preloader by samozřejmě měl být pokud možno malý, aby nezabral další čas na stažení a musí splňovat ještě jednu podmínku a to, být napsán jako single xaml stránka využívající Silverlight 1.0.

Na internetu možná najdete i další možnosti, jak takový preloader napsat a to v podobě klasického .xap souboru vytvořeného v příslušné verzi Silverlightu, který má jediný úkol a to zobrazit pohlednou animaci a zároveň započít stahování hlavní Silverlight aplikace přes objekt Downloader. I tento přístup je možný, ale osobně se mi příliš nelíbí, a tak popíšu onen standardní přístup s využitím Silverlight 1.0 a snad vám nabídnu dostatečné argumenty k tomu, abyste se taktéž přiklonili k tomuto přístupu.

Představte si tedy jednoduchou modelovou situaci, kdy jste vytvořili Silverlight aplikaci a nabídli ji uživatelům k používání. Tato aplikace se však u uživatele nahrává přibližně 8 vteřin, dle rychlosti jeho připojení a po dobu stahování aplikace mu chcete dát najevo, že dochází ke stahování vaší aplikace a zároveň mu chcete poskytnout malou ochutnávku toho, na co se může těšit. Určitě budete tyto situace znát třeba z Flash aplikací, které mají velice povedené preloadery.

Já jsem si pro tento příklad připravil velice jednoduchý preloader, který na zvolenou plochu, kde bude později zobrazena Silverlight aplikace umístí mřízku se 100 čtverečky. Každý čtvereček, se pak při stažení dalšího procenta aplikace zprůhlední a odkryje tak podkladový obrázek, kde může být třeba výchozí obrazovka vaší Silverlight aplikace. Tato animace je po stažení hlavní aplikace automaticky vyměněna za běžící aplikaci a tak uživatel plynule přejde od pouhého obrázku k běžící aplikaci.

vlastní preloader

Uživateli tak vlastně nabídnete postupné odhalování aplikace a tak mu můžete opět nabídnout uživatelský zážitek z použití vaší aplikace ještě dříve, než se dotkne prvních ovládacích prvků. Samozřejmě se meze vaší představivosti nekladou a jistě přijdete i na další možnosti, jak demonstrovat uživateli průběh stahování aplikace než je pouhý progress bar.

Silverlight 1.0

Jak jsem již zmínil, Silverlight plugin využívá k zobrazení preloaderu první verze Silverlightu, kdy jste omezeni skupinou zobrazovacích prvků a zároveň k rozpohybování a interakci s těmito prvky využíváte JavaScript. Co je tedy potřebné je znát několik málo metod pro manipulaci s prvky uvnitř a to pomocí JavaScriptu. Jak jsem již zmínil, v tomto preloaderu je třeba vytvořit celkem 100 čtverců – prvků Rectangle, které budou postupně měnit svojí vlastnost Opacity. Než abych měl těchto 100 prvků zadaných přímo v xaml souboru, bude snazší je generovat automaticky a poskládat je jak potřebuji – je to i z toho důvodu, že v Silverlight 1.0 nemůžete využít pokročilých panelů, a je třeba využít pouze Canvasu. Což v důsledku znamená pohrát si s vlastnostmi Canvas.Left a Canvas.Top.

Samotný xaml soubor bude tedy velice jednoduchý, obsahuje dvě deklarace pro Canvas a umístění podkladového obrázku. V hlavním elementu Canvasu pak vidíte vyvolání přiřazené obsluhy pro událost Loaded, která volá příslušnou metodu v JavaScriptu.

<Canvas 
    xmlns="http://schemas.microsoft.com/client/2007" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="mainCanvas" 
    Loaded="mainCanvasLoaded">
    <Canvas x:Name="rootCanvas" Width="303" Height="303">
        <Canvas.Background>
            <ImageBrush ImageSource="/res/cubi4.jpg" Stretch="UniformToFill" />
        </Canvas.Background>

    </Canvas>
</Canvas>

Na následující ukázce vidíte obslužnou metodu, která je zavolána právě po nahrání Canvasu:

function mainCanvasLoaded(s) {
    main = s.findName("mainCanvas")
    plugin = s.getHost()
    root = main.findName('rootCanvas');
    if (root != null) {
        try {
            var x = 0;
            var xaml_str = '';
            for (var i = 0; i < 100; i++) {
                var y = i % 10;
                x = parseInt(i / 10);
                var posx = (x * 30) + 1;
                var posy = (y * 30) + 1;
                var hldr = i;
                xaml_str = '<Canvas Name="hldr_' + hldr + '" Canvas.Left="' + posx + '" Canvas.Top="' + posy + '">'
                xaml_str += '  <Rectangle Name="rec_' + hldr + '" Canvas.Top="1" Canvas.Left="1" Fill="#00f" Height="29" Width="29" Opacity="1"></Rectangle>'
                xaml_str += '</Canvas>'
                var xamlEl = plugin.content.createFromXaml(xaml_str);
                root.children.add(xamlEl);
            }
        } catch (e) {
            alert('chyba' + e);
        }
    }
}

kde se nejdříve naplní globální proměnné pro přístup k samotným prvkům uvnitř Canvasu a získá se přístup k hostitelskému pluginu. Dále se pak postupně vytvoří pomocí skládání textu příslušné "čtverečky" a pomocí tohoto řádku kódu

var xamlEl = plugin.content.createFromXaml(xaml_str);

dojde k jejich převedení na Silverlight objekt, který je vložen do kolekce prvků a tím jsou umístěny na Canvas.

Všimněte si, že jsem zde využil vnořený Canvas, do kterého jsem poté skládal jednotlivé prvky, je to z toho důvodu, že z nějakého důvodu – nedokáži nyní říct z jakého – vede při manipulaci s hlavním Canvasem k chybě javascriptu.

Zobrazení preloaderu

Poslední část, kterou je třeba udělat je, říci jaký má být použit preloader a také obsloužit události, které jsou generovány v průběhu stahování hlavní Silverlight aplikace. Taktéž nesmíme zapomenout vložit odkaz na náš obsluhující JavaScript, pokud jsme kód zapisovali do samostatného souboru.

Odkaz na xaml soubor předáme opět pomocí properties a to přes vlastnost SplashScreenSource, kde uvedeme cestu na xaml soubor. Tato cesta musí být na stejné doméně, ze které pochází HTML stránka a taktéž ze stejné domény, jako pochází hlavní aplikace. A nezapomeňte, že se jedná o relativní cesty vůči právě zobrazené HTML stránce.

Dále je třeba předat odkazy na funkce, které oznamují vývoj stahování hlavní aplikace. Název této funkce je OnSourceDownloadProgressChanged a zde tedy ošetříme zobrazování, resp. odkrávání jednotlivých čtverců. Mějte na paměti, že tato funkce se vyvolá vždy po stažení části dat a to nepravidelně a tak případně nezapomínejte ošetřit i hodnoty od minulého stažení, kdy se může stáhnout více, jak 1% dat vaší aplikace.

function progressChanged(sender, args) {
    step = args.progress;
    var hldr = parseInt(step * 100);
    var k = parseFloat(step * 100);
    var o = parseFloat(k - hldr);
    var rec = root.findName('rec_' + hldr);
    if (rec) {
        rec['Opacity'] = 1-o;
    }
    for (var i = 0; i < hldr; i++) {
        rec = root.findName('rec_' + i);
        if (rec) {
            rec['Opacity'] = 0;
        }
    }
}

Poslední funkcí je pak OnSourceDownloadComplete, kterou v tomto případě nevyužijeme. Funkce je volána v okamžiku, kdy máme komplet nahranou hlavní aplikaci. Případy, kdy ji můžeme využít je, pokud bychom chtěli manipulovat např. se samotnou HTML stránkou.

A takto vypadá výsledné vložení Silverlight objektu do stránky i s umístěným vlastním preloaderem:

Silverlight.createObjectEx({
source: "ClientBin/MySilverlightApp.xap",
parentElement: document.getElementById("mySilverlightHost"),
id: "mySilverlightControl",
properties: {
height: "100%",
width: "100%",
background: "orange",
isWindowless: "true",
frameRate: "30",
inplaceInstallPrompt: true,
version: "4.0",
ignoreBrowserVer: "true",
enableHtmlAccess: "true",
splashScreenSource: "preloader.xaml"
},
events: {
onLoad:SL_Load,
onSourceDownloadProgressChanged: progressChanged
}});

Javascript kód metody progressChanged není jakkoliv optimalizován, byť by si to samozřejmě zasloužil, ale je napsán tak, aby byl pokud možno co nejvíce srozumitelný.

Kdy dojde k zobrazení preloaderu?

K zobrazení preloaderu nemusí samozřejmě dojít a to v těch případech, kdy se naše aplikace stačí stáhnout do cca. 0.5 sekundy od požadavku na zobrazení. Nezapomínejte také na to, že i samotný preloader je třeba nejdříve nahrát na cílový prohlížeč a tak by tento neměl být příliš velký nebo obsahovat příliš velké množství dodatečných resources – především se jedná o obrázky.

A jak si takový preloader otestovat? Asi nejjednodušší způsob je tento. Do Silverlight projektu přidat nějaké velké video, kterému nastavíte vlastnost Build Action na hodnotu Content.

Případně můžete využít podobného triku, který jsem použil já, kdy si přímo nastavíte vlastnost Source na daný xaml a v obsluze Loaded události si nastavíte voláním setInterval potřebný interval, a pak si samozřejmě nesmíte zapomenout zvolit příslušnou proměnnou pro simulaci načítání obsahu.

Závěrem

Nabídnout uživateli vhodný preloader – splash screen - během čekání na stažení Silverlight aplikace může být zajímavým zpestřením a uživateli se bude tento čas jevit kratším, než ve skutečnosti je. Tento článek měl nasměrovat a ukázat jednu z možností, jak se odlišit od výchozího preloaderu a nabídnout uživateli něco víc, než na co je standardně zvyklí.

Komentáře

ukládám komentář, vyčkejte prosím..
  1. David Beinhauer

    Pěkný článek! Ono použití Splash Screenu a jiných věcí není radno podceňovat. Někdy to rozhoduje, zda-li uživatel zůstane či po prvním načtení pár procent aplikaci zavře.

    12.10.2010 @ 18:02

@xamlcz

  • RT @jvanrhyn: XAML, It's a bit like olives. Takes a while to get used to. But once you're used to it. It is actually pretty good. <3 XAML
  • RT @moser_christian: WPF Inspector 0.9.7 is released. It supports .NET 3.5 and 4.0 The project is now open source and available on CodeP ...
  • Jeff Handley oznámil vydání WCF RIA Services v.1.0 SP1 RTM http://bit.ly/gOgckn ke stažení na http://bit.ly/gVAXdK
  • jedna výzva pro Brno. Byl někdo z vás na přednášce o RIA v MS Akvárku? Dejte o sobě vědět. Děkuji
  • také jste uvažovali o tom, že zkusíte na projekt použít Caliburn Micro nebo naopak Prism 4? A co tak obojí, šlo by to nebo ne? Již brzy