tisdag 29 maj 2007

Streaming av tiles över webben

Den något kryptiska titeln på inlägget kräver en förklaring. Vad jag syftar på är den form av "streaming" av bildinnehåll som man exempelvis kan se på Google Maps eller Microsoft Live Search, där användaren panorerar runt över en till synes oändligt stor bildyta som visas genom ett "titthål". Istället för att låta användaren vänta på att en jättestor bild laddas in så skickar servern några små bitar av bilden, så kallade "tiles", i taget. Tilesen skickas allteftersom användaren panorerar, så att det normalt i princip ser ut som om man tittar på en bild som aldrig tar slut. Typiskt smart. Så vill jag också göra. Ett hobbyprojekt är påbörjat.

Som jag ser det är problematiken indelad i ett par olika delar med olika klurighetsgrader. Först och främst måste jag komma på hur jag gör ett titthål (hädanefter kallad "viewport") som man kan titta på en yta genom och som stödjer panorering med muspekaren. Detta visade sig vara helt okej enkelt. Grundprincipen är att lägga den stora ytan som man vill panorera över inuti ett element med CSS-attributet overflow: hidden (bland annat). Det betyder att även om ytan är jättestor så syns bara en så stor del som får plats i det yttre elementet. För att kunna panorera krävs även att det yttre elementet, viewporten, har position: relative och att det inre, canvasen, har position: absolute. Sedan kan man använda Javascript för att manipulera canvasens position relativt viewportens. Ganska rättframt.

De mer utmanande tankenötterna börjar rada upp sig när det kommer till att dynamiskt läsa in och visa upp tiles. En webbläsare fungerar så att den börjar ladda in en bildfil så snart som den får veta dess sökväg, exempelvis genom ett src-attribut på en img-tagg eller som värde på ett elements background-image-styleattribut. Detta innebär att bara vi vet URL:en till en given tile så tar webbläsaren hand om den "streaming" som behövs för att visa upp bilden. Mycket bekvämt.

Låt säga att vi har ett enkelt koordinatsystem där varje tile har unika koordinater. För enkelhetens skull (och det finns ju ingen anledning att inte hålla det enkelt) bestämmer jag att en tile exempelvis kan ha koordinaterna (0, 0). Motsvarande bildfil heter troligen 0-0.jpg och ligger i mappen Images/Tiles. Eftersom strukturen är känd kan klienten själv lista ut URL:en till varje tile, och samtidigt beräkna vilken position den ska ha relativt canvasen. Men hur ska den veta vilka tiles som ska vara synliga vid ett givet tillfälle?

Klienten vet hur stor viewporten är, och kan därför veta hur många tiles den motsvarar. Man skulle kunna tänka sig att först ta reda på vilken tile som är "i mitten" av viewporten och sedan ladda in ett visst antal tiles relativt denna i både X och Y-led. När användaren sedan panorerar över canvasen så ändras den mittersta tilen, vilket ger en ny bas för beräkning av vilka tiles som ska vara synliga.

Gamla tiles, sådana som inte syns längre, tas bort från dokumentträdet för att det inte ska bli för stort och klumpigt. Eftersom webbläsaren i normalfallet cachar de bilder den laddar in kommer det ändå gå mycket snabbt att visa upp tiles som tidigare tagits bort om användaren skulle panorera tillbaka.

Det finns klara begränsningar som styr vad man kan göra samtidigt som en smidig resonsivitet i GUI:t bibehålls (kom ihåg att användaren kanske panorerar omkring helt godtyckligt, då duger det inte med en massa fördröjningar och lagg). Ett s¥dant exempel är att det faktiskt tar tid att skapa noder i DOM-trädet (vilket är vad man gör när man lägger till en tile). Ju mindre tiles, desto fler ska synas samtidigt vilket betyder fler aktiva noder för varje givet tillfälle. Responsiviteten minskar. Det hela blir en avvägning - vilken är den bästa tilestorleken i förhållande till prestanda och syfte? Detta är bara en av de frågor som jag stött på under mitt experimenterande hittills.

Den approach till problemet som jag skrivit helt kort om här är såklart bara en variant, kanske läroböcker i dynamiska webbapplikationer (finns det sådana?) skulle kalla den naiv. Men det är klart att jag inte kan skriva om alla finesser och knep nu direkt, då blir det ju inget roligt! Detta är ett löpande hobbyprojekt som jag har tänkt lägga en hel del tid på. Jag kommer säkert att skriva mer om olika detaljer framöver. Till sist har jag förhoppningsvis ett schysst resultat att visa, med en grundlig teknisk "bakom kulisserna"-genomgång som bonus.

Då och då kommer jag (kanske) göra releaser av det jag åstadkommit hittills, och den senaste versionen hittar du alltid på http://koncept.fjeldstad.se. Tycker du att den ser konstig ut så beror det med stor sannolikhet på att den gör det.

4 kommentarer:

  1. Jag noterade att i din nuvarande version (01:27 svensk tid) ligger tilesen kvar när man scrollar iväg åt helsike. Du skrev att de tas bort ur trädet, men att de ligger kvar i webbläsarens cache. Då finns det ju risk för att cachen blir giganorm till slut, eftersom de flesta webläsare - mig veterligen - inte tömmer bildcachen om man inte explicit ber dem om det. Kan man lösa sånt?

    SvaraRadera
  2. Jo det där tar webbläsaren hand om utan att man behöver bry sig. Man brukar vanligen kunna ställa in hur mycket plats cachen får ta upp på hårddisken, vilket kanske defaultar till 50 Mb eller liknande. Blir den större än så antar jag att webbläsaren rensar bort de äldsta filerna, eller n¥got.

    SvaraRadera
  3. Konceptsidan fungerar inte i Safari. Dina tidigare prototyper fungerade ju alldeles utmärkt i Safari, men innan du la upp artikeln måste du ha ändrat något för det har tyvärr slutat funka. Scriptet ser ut att funka, men bilderna läses aldrig in. Funkar dock mycket fint i gecko-baserade browsers.

    SvaraRadera
  4. Okej, tack för informationen. Lurigt att testa det där utan att ha en Mac...hm. Har inte laddat upp något nytt på ett tag nu, får se när jag har tid att jobba på det. Måste försöka lägga lite energi på certifieringsträningen...suck.

    SvaraRadera