Playing SVG Darts: Target Practice
This is the first part out of three showing how to create a game of darts using SVG. In this part I will show how to draw a dart board, including using 'iron wire' SVG Fonts for numbers. In the two following parts I will show how to make the game work, using some easy SVG scripting, and the advantages of using SVG filters for statistics, photorealism, and accessibility.
The colored sections
In SVG everything is rendered in order of the document, so when two things overlap the second will be on top. This is a principle heavily used in this example. Imagine looking through a circular hole in the ceiling straight down onto a sort of wedding-cake on a big black table. There are 6 cake layers from bottom to top: red/green, black/white, again red/green, and finally a black/white one topped off with green icing and a red cherry.
I'll define one SLICE (technically a circular sector) and use that 20 times alternating in color for every size of SLICE: "inner","triple","outer" and "double" to make up the dartboard.
<defs> <path id="SLICE" d="M 0 0 L 15.643 98.769 A 100 100 0 0 1 -15.643 98.769 Z" stroke-width="0" /> <use id="double" xlink:href="#SLICE" transform="scale(1.695)" /> <use id="outer" xlink:href="#SLICE" transform="scale(1.605)" /> <use id="triple" xlink:href="#SLICE" transform="scale(1.065)" /> <use id="inner" xlink:href="#SLICE" transform="scale(0.975)" /> </defs>
View the source code
The separating wires
A dartboard is of course not complete without iron wires to be able to unambiguously determine the score, 20 lines and 6 circles. I don't define the wires as stroke of the SLICE, because for scoring i need to be able to distinguish them from the area they surround. Plus as stroke-width scales along with the area it would limit re-use.
Then I added the 20 silver-colored numbers around the target and the blue score (initially 0). I coded them as SVG Fonts so that no matter how funky or unreadable they are, you can still copy them to other applications just like plain text, and search engines like Google can read them too. With some highschool mathematics I modeled the digits as pieces of iron wire, just using straight lines, and circular arcs of 2 different radii. Here are the defined numbers in use:
<g id="numbers"> <text font-family="dartdigits" text-anchor="middle" fill="Silver" font-size="100" transform="rotate(-270) translate(0,-205)" >6</text> <text font-family="dartdigits" text-anchor="middle" fill="Silver" font-size="100" transform="rotate(-288) translate(0,-205)">13</text> <i>[17 more numbers successively rotated 18° around the target]</i> <text font-family="dartdigits" text-anchor="middle" fill="Silver" font-size="100" transform="rotate(-252) translate(0,-205) rotate(180)">10</text> </g> <text font-family="dartdigits" id="scoreboard" x="245" y="-205" font-size="325" stroke="blue" text-anchor="end" fill="blue">0</text>
As you see in this illustration the upright numbers are aligned with the upside-down versions, which is not the case for many common fonts. This is needed for aligning the numbers 11 up to 6 and 8 up to 10 all on one circle through rotation, and is accomplished by centering the glyphs on y=0. As I had the glyph definitions also centered on x=0, where SVG takes the left edge as 0, I had to change all (absolute) x-values. A little task that will be a lot simpler as soon as the horiz-origin-x attribute is implemented.
With some rotate and translate (which are applied in the order of reading from right to left) and text-anchor="middle" I correctly position, orient, and center the numbers next to the corresponding slices.
The scoreboard at the upper right corner is updated through the
onmouseover="showScore(..) function. I declare that hitting a wire always results in a "bounce-out," something that in reality only rarely happens. Another imperfection, this time not in my code but in Opera 9 is that the score is not always properly updated, probably through mouseover not always firing when it should.
- Because the Opera 9 implementation of glyphs (the definition of how the characters look) was limited, I had to convert mystroked path for the numbers to a non-stroked outline of the same shape. I used Inkscape's "stroke to path" function for this purpose.
- While developing this example i looked a lot at what Opera 9 implements of SVG, and used attributes instead of style declarations.
- Possible improvements of this example are more realistic 'bouncing wires', smaller filesize, better code readability and anything you can come up with.
- I love Inkscape, but i don't like that it changes SVG that I didn't call any actions on into code that is quite different of which the rendering is sometimes not the same, though very, very similar.
This article is licensed under a Creative Commons Attribution, Non Commercial - Share Alike 2.5 license.