a paper for the 2003 SVG Open Developers Conference.
Continued from part 2
Where we left off:
In Part 2 we took the example that loads in coordinates from an xml file, and plots a vehicle's movement over a map, and added detailed raster maps that were loaded off external servers, in realtime.
The SVG file:
example4.svg (Opens in a new window)
The color-coded source-code:
example4.html
So that works nicely.
But there is room for improvement.
When we load an image in SVG, by changing the image's xlink:href attribute, we don't really know when the image has loaded.
The 'onload' event doesn't work reliably so flashing occurs when a new image is loaded.
There is a solution though:
Using Base64 Encoding:
Base64 encoding is a way of including a binary file inside a text(xml) file. It is widely used when attaching an image to an email, for instance.
The advantage in SVG, is that we can use getURL to load a base64 encoded image, and then asign this data to an image's xlink:href attribute.
This way we have full control over showing, and hiding the image, and we can animate images without flashing.
Let's have a look at an example:
This example loads 21 gzipped and base64 encoded images, and then animates them:
The SVG file:
movie_preloaded.svg (Opens in a new window)
The color-coded source-code:
movie_preloaded.svg
The source-code of one of the base64 encoded images:
bird1.html
An aditional advantage to loading base64 encoded images in xml files, is that you can add in some meta-data, in this case: id="frame0" width="135" height="262":
<image id="frame0" width="135" height="262" xlink:href="data:;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEP ERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4e Hh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/wAARCAEGAIcDASIA ...//... SgugueXcvW3w78CWzI8PhHRQyfdJtEY/qOa6O1tra0iENrbxQRjkJGgUfkKKKpJLYm5NRRRTAKKK KAP/2Q=="/>
How do we encode the images then?:
There are various ways, one way is to attach the image to an email, send it to yourself, and view the source.
Another way is using a Perl script.
Here is an example of a Perl proxy with base64 encoding:
#!/usr/bin/perl #Base64 encoding proxy by GRI Technologies 2003. use strict; use LWP::UserAgent; use MIME::Base64; print "Content-type: text/plain/n/n"; my $content; my $ua = new LWP::UserAgent; $ua->agent("base64 proxy/0.01"); my $url_req="http://$ENV{QUERY_STRING}"; my $req = new HTTP::Request GET => $url_req ; my $res = $ua->request($req); if ($res->is_success){ $content= $res->content; print "data:;base64,".encode_base64($content); }else{ print "data:;base64,=="; }
You can test this script here for your self, pass any image in the query-string:
http://www.gritechnologies.com/cgi-bin/proxy?www.svgopen.org/2003/images/DrawingOnTheNet.png (Opens in a new window)So how do we use this encoded image?:
Again there are various ways, In the animated bird example we load xml files containing a complete SVG <image> tag, which is then appended to the main SVG's DOM.
In our mapping application we will load the base64 image as raw data, and point the <image>'s xlink:href attribute's value to it.
In our example we're going to add two functions, one that requests a new image, and one that processes the data once it has loaded.
This allows us to give the user some feedback on what we're doing. For now we'll simply write progress messages to the (window.status) statusbar:
function loadBase64(url){ //give the user some feedback: window.status="Loading map: "+url; //Talk to the server, calling loadedBase64() when the data arrives: getURL(url,loadedBase64); } function loadedBase64(obj){ //If the data loads ok: if(obj.success){ //give the user some feedback: window.status="Map loaded OK"; //Point the mapLoader image's href attribute to the data: mapLoader.setAttribute("xlink:href",obj.content); //If something went wrong: }else{ //give the user some feedback: window.status="Error while loading map"; } } //Call our loading function: loadBase64("http://www.gritechnologies.com/cgi-bin/proxy?tiger.cens ...//... ater");
Important: Due to the way browser security works, getURL() will only load data from the same computer that the SVG file is located on. So it is not possible to have the SVG locally, loading data off the server.
Let's put all that together:
If we take our tracking application from part 2, and add base64 image loading, we no longer have the flashing effect as new maps are loaded while the vehicle moves.
New maps will only be displayed when the image is fully loaded, and we can give the user some feedback on the progress.
Here is a link to the completed example - note that you need an internet connection to see it, as it has to reside on the same server as the base64 encoding proxy:
The SVG file:
http://www.gritechnologies.com/papers/gps_tracking_with_svg/examples/example6.svg (Opens in a new window)
The color-coded source-code:
example6.html
Well, that's all for part 3 - I hope you found it interesting, if you have any comments or questions don't hesitate to email us.
David Van Blankenstein
Robert Basques
Richard Bennett
richard.b@gritechnologies.com