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 from scratch in response to the user's actions or maybe the web page environment or saved data.

Note:
Does the purple circle grow in size?
Does the green circle move to the right?

There are a variety of ways to dynamically display graphics. You may have access to graphics packages such as GD or ImageMagick through your web hosting service. These 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, which creates a file in a format (for example GIF) which a web page can reference. 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).

We use a hosting service which supports GD and ImageMagick (and therefore we can use GD to plot our dam level), but yours may not, or you might want to create an animated picture which is not so effective with these packages, or you may not be a wizz at Perl or PHP. So, without using a server-based graphics package, what possibilties are open to developers who want dynamic graphics?

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 possible solution - chart tools - which looks flexible but we have not investigated it.

Using the img tag

We can start by looking at a relatively modest way to use HTML together with just a bit of simple Javscript to create graphics. Note that HTML in a web page is 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 as 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 horizontal rather than vertical and 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.

Before considering more general approaches to displaying dynamic graphics, we need to look at where the data to be plotted comes from. In other words, in our example above, where does Javascript find the values for v1, v2 and v3 which control the height of the orange bars?

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 can be 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)
  • data on the server accessed using AJAX

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.

Often 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. The basic approach to solve this problem is to use a CGI (Common Gateway Interface). This is a program which runs on the server and either

  • creates the HTML for the page which includes a reference to the image
  • creates an image file (for example a GIF or JPEG) which can be referenced by the HTML in a web page (as explained earlier)
  • provides data (via AJAX) to Javascript routines which can draw the image
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.

A CGI can provide powerful ways to select and organise data, but so far we have only discussed one simple and inflexible way to display the data in a web page, based on manipulating HTML using Javascript. Despite this, in some cases acceptable graphics can be created using this method, 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.

But what is available if we need more flexible client-side drawing methods?

Scalable Vector Graphics (SVG)

SVG is text-based and interpreted by the browser (possibly with the help of a plug-in) and you do not need to understand Javascript to use it. 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 saw a purple circle at the top of this page then your browser can display SVG graphics. If it repeatedly (actually, just three times 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="3"/> </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.

The Canvas tag

The official HTML5 standard, which appeared in 2009, introduced the <canvas> tag, specifically designed to allow drawing from within HTML, and the latest versions of all common browsers (and Internet Explorer versions 7 and 8 with a plug-in) support it and most of the Javascript and CSS which make it work. You could think of <canvas> as being like an empty image tag; the contents of the image are drawn onto the canvas using Javascript methods. This allows for a wide variety of graphics shapes and effects, including transparency and animation.

To provide an example for discussion, here is a complete page which consists a text header and a drawing using canvas.

<html> <head> <title>HTML5 canvas example</title> <style type="text/css"> canvas { border: 1px solid black } </style> <script type="text/javascript" src="draw1.js"></script> </head> <body onLoad="draw1()"> <h3>Example using Canvas</h3> <canvas id="example1" width="480" height="240">Missing graphic (<i>canvas</i> not supported)</canvas> </body> </html>

Here is the page:

Example using Canvas

There would be a graphic here if your browser supported the canvas tag

You can look at the Javascript code in a separate window, but before discussing the code, several features of the HTML need to be considered.

Firstly, note that the <canvas> tag must have a closing tag. Following standard HTML conventions, if the tag is not understood (for example when using an older browser) then anything within the <canvas> tags except text is ignored. The <canvas> tag is given an id attribute so that we can reference it from within Javascript, and height and width parameters to set its size (in pixels) on the page. For our example we want to see the extent of the canvas area, so we have given it a black border using CSS. The Javascript used to draw the graphic elements on the canvas is in the file draw1.js as defined in the header. Finally, note that to ensure that drawing process cannot commence before the whole page (and in particular the canvas element) has been parsed, the draw1 function is invoked using onLoad() in the <body> tag.

We can now consider the Javascript code. The first step is to get a reference to the canvas object, which we can do using its id attribute. The next line aborts the routine if the reference is not to a canvas object or is otherwise incorrect. The properties and methods used to draw on a canvas do not belong to the canvas object but to its context. In theory a canvas could have different types of context, but to date only one type (2d) is defined (a 3d context or others may be defined in the future). The getContext('2d') method returns a reference to a context which can then be used to access the procedures used to do the drawing.

Properties can be set to control the fill colour, line colour, text colour and so on, and these stay in force until they are changed. There are methods to draw rectangles, arcs (and therefore circles), lines, several types of curves, text and images read from files. Note that care must be taken to ensure that images are fully loaded before any attempt is made to display them. While there are routines to draw rectangles directly, other shapes are defined first but not displayed until a fill() or stroke() function is called. By default each drawing object is opaque and lies on top of the previous objects, but there are ways to change these behaviours.

Drawings can be animated by repeatedly erasing and redrawing all or selected parts of the canvas with the timing controlled using Javascript's setTimeOut() and/or setInterval() routines.

If you want more detailed information on HTML5 graphics and the <canvas> tag, these links should get you started:

And here are some links to high-level packages which use Javascript but provide sophisticated charting and drawing abilities:

Top
Previous
Next
Index
Home