Kaye and Geoff's web page documentation 

Introduction

This page is about the dynamic creation of graphics in web pages, in other words displaying a graphic not from a pre-existing image file but creating it in response to the user's actions or maybe the web page environment.

Those who run their own web server can do this with graphics packages (for example GD or ImageMagick) or pre-processors (for example Cold Fusion) which run on the server. The graphics packages consist of a collection of routines which can be used stand-alone or called from Perl or PHP or C or some other programming language running as a CGI. Pre-processors interpret and then strip out special instructions included in web pages before they go to the server; these instructions can include commands to access a database and to plot the returned data. In either case, a file is ultimately created in a format (for example GIF) which a web page can reference.

If you are running your own server then you can set it up as described above and you do not need the advice on this page. GD is free, includes a Perl interface, and runs on Unix servers. ImageMagick is available for Unix and Windows and has a Perl interface (PerlMagick). Cold Fusion is a commercial product.

However, most web page developers do not have their own web server. While we use the Apache web server which comes with our Mac for development on our local network, we have no desire to expose it to the world. We have come across a number of hosting services which offer GD and/or ImageMagick as one of the resources available to their clients, but many do not. So what possibilties are open to developers who want dynamic graphics but who do not have access to a server-based graphics system?

We have tried several possibilities, many of which involve writing a CGI, so you could consider this page an extension of our CGI documentation. However we will also discuss some aspects of HTML, Javascript and SVG graphics, have a passing reference to AJAX and the DOM, and even touch on HTTP protocols and MIME types. Which explains why this is a separate page - it has a bit of everything.

The information here is a summary of our current experience in dynamic plotting, so there are likely to be other techniques which we have yet to discover or explore. For example CSS may have something to offer, but our (only slightly jaundiced) view of style sheets leads us to put them at the bottom of our list at this stage. Google also offers a solution - chart tools - which looks flexible but we have not investigated it.

Using the img tag

We can start by looking at what features of HTML can be used to create (as distinct from loading) graphics. In fact, on its own HTML is limited since it is "hard-coded" and only parsed once, a line at a time, strictly in sequence. However, it does have the ability to scale a picture before displaying it, using the width and height attributes of the image tag. Together with some setting-out using tables or CSS, if we could dynamically set the values of these attributes when the page is loaded or in response to user input, then we could create (admitedly limited) graphics "on-the-fly". As we have already seen, Javascript allows us to add dynamic behaviour to HTML, so we can use it to achieve simple plotting.

The document.write() Javascript function is the basis of this technique, since it allows us to create the HTML code as the page is being parsed by the browser. For example:

<script type="text/javascript"> document.write ('<img src="redrect.gif" hspace="2" width="12" height="' + v1 + '" border="0">)'; document.write ('<img src="redrect.gif" hspace="2" width="12" height="' + v2 + '" border="0">)'; document.write ('<img src="redrect.gif" hspace="2" width="12" height="' + v3 + '" border="0">)'; </script>
If the values of v1, v2 and v3 were previously set to, say, 35, 45 and 25, then with a bit of appropriate html this can be made to appear in a web page as follows:
 
This bar chart example is very simple but is sufficient to illustrate the idea. It could be elaborated with axes and legends. We could make a scatter plot by using transparent blank GIFs to "set" the position of a small graphic symbol in a similar manner. CSS's absolute addressing, now supported by most browsers, permits us to precisely place and overlay images and thereby produce a reasonably complex picture.

Using the canvas tag

HTML5 (which was introduced in 2009 but which most browsers have been slow to implement completely) introduced the <canvas> tag, specifically designed to allow drawing from within HTML. Between the opening and closing canvas tags you can place instructions which define a drawing to be placed within the web page. While this provides a simple and reasonably powerful method of creating graphics, it does have some drawbacks. It is not supported by older browsers, and is not supported directly by Internet Explorer at all. However a number of libraries are available which provide Internet Explorer support (via Flash or by some other method).

We have not tried out this approach, since a significant proportion of our client audience is liable to still be using old browsers. If you want more information, these links might get you started:

So there are a few techniques to choose from for plotting, but where do we get the data from? In other words, in our example above, where does Javascript find the values for v1, v2 and v3?

Data sources for plotting

Javascript is not allowed, for security reasons, to access the host computer except in extremely limited ways via the browser. This is a major limitation on its effectiveness in creating dynamic plots, but depending on your application you might be able to use:

  • cookies (information passed through time or between web sites)
  • the search string part of the URL (information passed between web pages)
  • system values which Javascript can access (date and time, browser and operating system ID strings, etc.)
  • internally generated data (from within Javascript)

You can see a reasonably sophisticated example of plotting using internally generated values in our population genetics simulation. (If you are not trained in genetics then just push the "simulate" button to produce a plot. Convince yourself that it is generated dynamically by pushing the button as many times as you like). In fact this page illustrates a way of producing a plot using multiple picture substitution rather than the document.write() method described above. The complete picture is built by puting together a collection of pre-existing smaller pictures. It is not elegant but it works.

A more elegant approach is to manipulate image objects in the document object model (DOM), inserting or removing them as required to build a more complex image. Because changes to the DOM are reflected immediately on the web page, this technique allows the graphics on the screen to be animated or to respond to input from the keyboard or mouse. This is how our Numero game expands or shrinks a spread of cards on the screen - by the addition or removal of pictures of complete or partial cards - simulating the cards being overlapped on a tabletop.

The list of possible data sources above is obviously very limited; generally we have a large body of externally collected data stored on the server from which we want to select a subset to display in graphical form on a web page. Making an image file of every possible graph is too much work, and usually not practical. To solve this problem we need a CGI (Common Gateway Interface). This is a program which runs on the server and creates either the HTML for the page, or an image file (for example a GIF) which can be referenced by the HTML, or both. Writing a CGI requires programming skills - see the page referenced above for a more detailed discussion of the techniques involved - but it gives us almost unlimited freedom in accessing and manipulating the data.

Plotting using a CGI

A CGI may provide powerful ways to select and organise data, but so far we have only discussed very simple and inflexible ways to display data in a web page, based on manipulating HTML using Javascript. Despite this, in some cases acceptable graphics can be created, for example our weather plotting which uses a simple bar chart and a scatterplot on a fixed-interval X axis. Here the CGI writes an entire web page which is displayed in a pop-up window, but the plot could be included within the originating page by using AJAX and taking advantage of Javascript's ability to interact with the HTML DOM.

SVG

However to create arbitary graphics we need a generalised graphics package, and SVG (Scalable Vector Graphcs) fills the bill. To use it we are not dependent on our ISP or server administrator since it is text-based and interpreted by the browser (possibly with the help of a plug-in). SVG is an official W3C standard and is pure XML, so its structure is like HTML (well XHTML anyway). Because it is vector-based, it scales without loss of quality or appearance, but unlike most drawing formats it supports drop shadows and other features normally only available with raster image formats. It can even include animation capabilities.

The only down-side is that browsers have been very slow to provide support for SVG, so older versions will not display it, or may need a plug-in, or may only implement a subset of the complete specification. This is changing, to the extent that the latest versions of all popular browsers probably understand SVG natively. Traditionally Internet Explorer included SVG graphics in a web page using the non-standard embed tag, but the latest version allows the equivalent standard object tag. For these reasons you need to determine the nature of your audience before committing to relying on SVG graphics in your web pages.

If you see a purple circle below then your browser can display SVG graphics. If it repeatedly (actually, just five times, starting from when the page completes loading/reloading, since it soon gets annoying) grows in size then your browser also supports SMIL (Synchronized Media Integration Language) which integrates with SVG to add the ability to animate the graphical elements. If you see a green circle then your browser supports SVG with the img tag (and also supports SMIL if the circle moves from left to right).

The SVG code to create the purple picture is as follows:

<?xml version="1.0" standalone="yes"?> <svg width="70px" height="70px" version="1.1" xmlns="http://www.w3.org/2000/svg"> <circle cx="35" cy="35" r="32" style="fill:rgb(255,0,255); stroke-width:0"> <animate attributeName="r" dur="5s" from="2" to="32" repeatCount="5"/> </circle> </svg>

You can see the svg tags which surround the whole picture description, and the circle tags which define the single graphical element - a purple circle centred on cx,cy with a radius of r. The animate tag changes the value of r through time to make the circle grow. Note that following XML rules all tags must be terminated, either using a "standalone" terminating tag (for example </svg>) or with a slash before the closing > (as in the animate tag used above). Because it is just text, creating such a file either with a text editor or from a program is conceptually straight-forward. The code for the green picture is similar except that the position of the centre in the X direction is changed over time, rather than the radius.

Our experience with SVG is far too limited to attempt a detailed description of the language, but we do offer some comments below on its use in web pages. Try these links for more specific information on SVG:

  • W3schools - a graded introduction to SVG
  • W3C - the official SVG specification

SVG in the WWW environment

There are some practical considerations when using SVG graphics in a web environment. The first is the server configuration.

When you display a picture from an SVG file (for example in an iframe or with an img tag as in the examples above) the web server inserts the MIME type into the HTTP header. To do this the server needs to be told that image/svg+xml is one of the MIME types that it should recognise. This is not always the case, so if instead of seeing a picture you see your SVG code, or some other error, then before you blame the browser, check that your server has been told to recognise SVG files. Varying server configurations may also limit the animation behaviour of your SVG picture even when your browser supports the full range of animation options.

The second consideration is the method used to link the SVG to the HTML. In the example above the SVG file is displayed in an inline frame with the following HTML:

<iframe src="oval.svg" width="70" height="70" scrolling="no"></iframe>

but there are other ways to display a SVG file. As already noted, you can use an object tag, or an embed tag, depending on which browsers you think your audience might have; or preferably both, in such a way that only one is actioned:

<embed src="oval.svg" height="70" width="70"> <object data="oval.svg" type="image/svg+xml">animated oval</object> </embed>
This works because the browser ignores anything between the opening and closing embed tags if it recognises them; if it does not then it ignores them, and so sees the object tags. Note the (MIME) type of the SVG file - we will see this used in a related way later. As with other image formats, the img tag can also be used to display SVG files, or the file name can be passed directly to the browser (just like any URI) if the browser has native support for SVG.

Another consideration arises when you are using a CGI to dynamically create your SVG. Once you have the SVG code, you can either return it to the web server which will deliver it to the browser, or you can create an SVG file and return the HTML (or a reference to an HTML file in the HTTP) which can then include the SVG file using one of the methods discussed above.

If you return SVG via the web server, the HTTP header must include the content (or MIME) type. For SVG this is image/svg+xml. So your CGI needs to return:

Content-type: image/svg+xml <svg> ........ </svg>

Note that the blank line under the "Content-type" line is absolutely required - it separates the HTTP header (which here consists of just one line containing the content type) from the body (here the SVG code).

How the returned graphic is formatted on the page depends on how the CGI is invoked, but the rules are the same as for graphics files referenced from HTML in the normal way. The picture will form the entire contents of a page, or a frame, or an inline frame, if it is invoked from any of these elements. If the CGI is called from a form, the target attribute can be used to display the picture in a named frame or a new window. The CGI can also be invoked directly from an img tag, for example:

<img src="/cgi_bin/doplot.pl" border="1">
If you want your SVG picture to be saved and then displayed on a web page, you need to create an SVG file from your CGI and then ensure that the web page which is displayed on return from the CGI includes the appropriate HTML to reference it. To do this, the CGI can create the HTML, or alternatively can use the "location" HTTP directive to specify the HTML file to be displayed (in this latter case the name of the SVG file would have to be fixed).

As you can see from the examples in the CGI page, a web page returned from a CGI (in the example below including an object tag to load the SVG) has the following format:

Content-type: text/html <html> ..... <object data="sample.svg" height="200" width="200"></object> ..... </html>

To get the browser to load an HTML file called svgexample.html, the CGI needs to return:

Location: svgexample.html

In the last case there is no HTTP body, but a blank line below "Location" is still required (failing to do this is a very common source of error when creating HTTP from within a program).

After creating an SVG file, you will normally have to undertake a bit of "housekeeping". Most web servers are set up with restrictions on which directories they access. Normally there is a directory for CGIs (on Unix machines typically called cgi-bin) and another for web pages and their associated image, CSS, Javascript and similar files (sometimes called www). For security reasons the web server is usually only allowed to execute CGIs if they are in their correct directory (or one of its sub-directories), and can only serve files from the web directory (or one of its sub-directories). In particular it may not be able to serve files from the CGI directory. So we might have to arrange for the SVG file that we create to end up in the web directory, not the CGI directory. How you do this depends on what language you choose to write your CGIs, but if you are using someone else's server then you need to make sure that you can write to the web directory, and possibly also that you can control the ownership and/or permissions of the file you are writing.

Top
Previous
Index
Home