Automated Marker Generation

The SVG marker element provides a facility for authors to include additional symbolic information associated with a line end or path vertex. Typical uses are arrowheads for lines and paths and polymarkers used to highlight vertices along a polyline (for example, data points in a graph). The rendering model for markers treats them as separate entities to be rendered after the rendering of the associated geometry. As separate entities, they have their own CSS properties and they do not affect the rendering of the underlying geometry.

This rendering model has some practical drawbacks. An example can be seen with simple arrowheads. A marker used to represent an arrowhead will place and orient a triangle over the rendered line such that the tip of the triangle coincides with the end of the line. The original line ending is still visible and this detracts from the intended results. The arrowhead appears dull. This effect is more noticable with thick lines. An often-used solution for this effect is to manually foreshorten (i.e. setback) the line while keeping the marker fixed by moving its reference point back by the same amount. This method has drawbacks and is only applicable to certain marker shapes. While foreshortening may be simple for horizontal or vertical lines, it is more difficult for diagonal lines and curved paths. More importantly, the semantic information of the line ending is not retained in the original geometry. Another less than ideal solution is to provide a background to the marker which matches the background of the page. This works in simple cases but leaves unwanted artifacts when the marker is placed over existing geometry.

A more robust solution is presented here. The curve is first rendered using a mask to occlude unwanted portions at its end point. The mask is created from the original curve with markers that are similar in shape to the original markers. The curve is rendered a second time, this time with the original markers but with fully transparent stroke. The resulting combination provides the desired effect in most cases.

This solution requires the generation of a lot of additional SVG. An additional marker element, a mask, and two duplicates of the original geometry are required. A set of ECMAScript functions is provided that simplifies this task. An onload="makeMarkers()" event handler is declared on the desired elements and the SVG DOM tree is populated with the necessary components. This function provides a number of other utilities including automatic reflection of end markers and paint server replication. In addition, this function can be used to create custom line ends.

The discussion concludes with a wish list for improvements to the marker element for future versions of SVG. This includes either native language constructs for the method used here, or simply the use of a setback specification for the marker itself as well as a suggestion for an extension to the orient attribute.

Bob Sabiston
#350 - 1190 Homer Street
Vancouver, BC  V6B 2X6
tel:   604-682-3404
fax:   604-682-3432