Digital humanities

Maintained by: David J. Birnbaum ( [Creative Commons BY-NC-SA 3.0 Unported License] Last modified: 2021-04-13T02:59:20+0000

SVG assignment #1 solution


Your task is to use the data from a mythical Best Stooge Ever contest to draw (by hand) an SVG bar chart of the results. In XML terms, the scores are:

    <stooge name="Curly">50</stooge>
    <stooge name="Larry">35</stooge>
    <stooge name="Moe">15</stooge>

For your bar chart, you’ll want to draw an x axis and y axis (using the SVG <line> element), three bars of different colors (using the SVG <rect> element), and labels on the axes or the bars for the stooges and the numerical values of their vote counts (using the SVG <text> element).

One solution

Here is one possible solution:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "">
<svg xmlns="" width="100%" height="100%">
    <!-- x and y axes -->
    <line x1="20" y1="205" x2="170" y2="205" stroke="black" stroke-width="2" stroke-linecap="square"/>
    <line x1="20" y1="205" x2="20" y2="0" stroke="black" stroke-width="2" stroke-linecap="square"/>
    <!-- labels for Y axis -->
    <text x="13" y="23" text-anchor="end">50</text>
    <text x="13" y="43" text-anchor="end">45</text>
    <text x="13" y="63" text-anchor="end">40</text>
    <text x="13" y="83" text-anchor="end">35</text>
    <text x="13" y="103" text-anchor="end">30</text>
    <text x="13" y="123" text-anchor="end">25</text>
    <text x="13" y="143" text-anchor="end">20</text>
    <text x="13" y="163" text-anchor="end">15</text>
    <text x="13" y="183" text-anchor="end">10</text>
    <text x="13" y="203" text-anchor="end">5</text>
    <!-- horizontal ticks on Y axis -->
    <line x1="15" x2="18" y1="18" y2="18" stroke="black" stroke-width="1"/>
    <line x1="15" x2="18" y1="38" y2="38" stroke="black" stroke-width="1"/>
    <line x1="15" x2="18" y1="58" y2="58" stroke="black" stroke-width="1"/>
    <line x1="15" x2="18" y1="78" y2="78" stroke="black" stroke-width="1"/>
    <line x1="15" x2="18" y1="98" y2="98" stroke="black" stroke-width="1"/>
    <line x1="15" x2="18" y1="118" y2="118" stroke="black" stroke-width="1"/>
    <line x1="15" x2="18" y1="138" y2="138" stroke="black" stroke-width="1"/>
    <line x1="15" x2="18" y1="158" y2="158" stroke="black" stroke-width="1"/>
    <line x1="15" x2="18" y1="178" y2="178" stroke="black" stroke-width="1"/>
    <line x1="15" x2="18" y1="198" y2="198" stroke="black" stroke-width="1"/>
    <!-- rectangular data bars, with name labels -->
    <rect x="20" y="5" width="40" height="200" fill="green" stroke="black" stroke-width="1"/>
    <text x="40" y="225" text-anchor="middle">Curly</text>
    <rect x="70" y="65" width="40" height="140" fill="blue" stroke="black" stroke-width="1"/>
    <text x="90" y="225" text-anchor="middle">Larry</text>
    <rect x="120" y="145" width="40" height="60" fill="red" stroke="black" stroke-width="1"/>
    <text x="140" y="225" text-anchor="middle">Moe</text>

Most of this is self-explanatory, but the part that might be new is the @stroke-linecap attribute on the axis <line> elements. Without that setting, the axis lines don’t meet smoothly; you can see the effect if you increase the stroke width. Adding that attribute with the value "square" fixes the problem.

We find it difficult to calculate the X and Y positions when the two axes don’t intersect at 0,0 and when the Y values increase as we move down the Y axis (since humans expect Y values to decrease as we move down). We can make the arithmetic more human-friendly by drawing the graph at 0,0 (which pushes the labels on the Y axis off the left edge, so that they have negative X values). Even better, we can make the Y values negative, so that they grow up (into the invisible upper right quadrant), and we can then shift the entire image down and to the right by using a @transform attribute with a translate() function on a <g> (= group) element that contains all of the lines and rectangles and text. Here’s how that looks (see whether you don’t also find the numbers on this version easier to understand, and to plot, than in the first version):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "">
<svg xmlns="" width="100%" height="100%">
    <g transform="translate(30, 250)">
        <line x1="0" y1="0" x2="150" y2="0" stroke="black" stroke-width="2" stroke-linecap="square"/>
        <line x1="0" y1="0" x2="0" y2="-210" stroke="black" stroke-width="2" stroke-linecap="square"/>
        <line x1="-3" x2="3" y1="-20" y2="-20" stroke="black" stroke-width="1"/>
        <line x1="-3" x2="3" y1="-40" y2="-40" stroke="black" stroke-width="1"/>
        <line x1="-3" x2="3" y1="-60" y2="-60" stroke="black" stroke-width="1"/>
        <line x1="-3" x2="3" y1="-80" y2="-80" stroke="black" stroke-width="1"/>
        <line x1="-3" x2="3" y1="-100" y2="-100" stroke="black" stroke-width="1"/>
        <line x1="-3" x2="3" y1="-120" y2="-120" stroke="black" stroke-width="1"/>
        <line x1="-3" x2="3" y1="-140" y2="-140" stroke="black" stroke-width="1"/>
        <line x1="-3" x2="3" y1="-160" y2="-160" stroke="black" stroke-width="1"/>
        <line x1="-3" x2="3" y1="-180" y2="-180" stroke="black" stroke-width="1"/>
        <line x1="-3" x2="3" y1="-200" y2="-200" stroke="black" stroke-width="1"/>
        <text x="-8" y="-15" text-anchor="end">5</text>
        <text x="-8" y="-35" text-anchor="end">10</text>
        <text x="-8" y="-55" text-anchor="end">15</text>
        <text x="-8" y="-75" text-anchor="end">20</text>
        <text x="-8" y="-95" text-anchor="end">25</text>
        <text x="-8" y="-115" text-anchor="end">30</text>
        <text x="-8" y="-135" text-anchor="end">25</text>
        <text x="-8" y="-155" text-anchor="end">40</text>
        <text x="-8" y="-175" text-anchor="end">45</text>
        <text x="-8" y="-195" text-anchor="end">50</text>
        <rect x="0" y="-200" width="40" height="200" fill="green" stroke="black" stroke-width="1"/>
        <text x="20" y="15" text-anchor="middle">Curly</text>
        <rect x="60" y="-140" width="40" height="140" fill="blue" stroke="black" stroke-width="1"/>
        <text x="80" y="15" text-anchor="middle">Larry</text>
        <rect x="120" y="-60" width="40" height="60" fill="red" stroke="black" stroke-width="1"/>
        <text x="140" y="15" text-anchor="middle">Moe</text>

The output should look something like:

5 10 15 20 25 30 35 40 45 50 Curly Larry Moe