As promised, I thought I'd take time to document some of the code behind my JavaScript
flags hobby project. If you look at the data file for the flags,
flagdata.js, you'll see a single
JSONP-style JavaScript call:
Flags({
AD:["Andorra",10/7,"..."],
...
BL:["Saint-Barthelemy","FR"],
...
JP:["Japan",3/2,"FwCrO+0+0+72"],
...
ZW:["Zimbabwe",2,"..."]
});
The single argument is an object with
ISO-3166 two-letter codes as keys and arrays of two or three elements as values. If the array has three elements, they are:
- The country or territory name, as a string;
- The flag's aspect ratio, as a rational floating-point number; and
- The instructions for drawing the flag, as a string (see below).
If the array has only two elements, they are:
- The country or territory name, as a string;
- The ISO-3166 code of the "parent" country whose flag this entry shares, as a two letter string.
The latter scheme allows "aliases" to be set up for flags that are shared by more than one territory:
- France
- Netherlands
- Norway
- United States of America
The instructions for drawing the flags as represented as a string. The pseudo-
BNF of these instructions is as follows:
instructions ::= instruction ...
instruction ::= command argument …
command ::= 'A'..'Z'
argument ::= number | colour
number ::= sign digit ...
sign ::= '+' | '-'
digit ::= '0'..'9'
colour ::= 'a'..'z'
It is therefore trivial to parse these instruction streams using regular expressions. For example, Japan has the following entry:
JP:["Japan",3/2,"FwCrO+0+0+72"]
The instruction stream can be split into individual instructions using:
instructions.match(/([A-Z][^A-Z]*)/g)
This produces an array:
["Fw", "Cr", "O+0+0+72"]
These three instructions can be further divided into numbers (which are always preceded with a sign) and single-letter colours:
instruction.match(/.\d*/g)
This produces an array for each instruction:
[
["F", "w"],
["C", "r"],
["O", "+0", "+0", "+72"]
]
The first element is thus always an upper-case letter and is used as the key into a map for commands. I'll discuss the meaning of each letter (command) next time. Subsequent elements in the instruction array are arguments to the command: numbers and/or colours. Colours are always lower-case letters:
a: #39F light-blue
b: #00F medium-blue
c: #009 dark-blue
g: #CCC grey
m: #630 brown
n: #000 black
o: #F60 dark-orange
p: #F90 light-orange
r: #F00 bright-red
s: #C00 medium-red
t: #900 dark-red
u: #060 dark-green
v: #090 medium-green
w: #FFF white
y: #FF0 yellow
But for now, we'll finish off the Japanese flag example by expanding the instruction arrays:
fill white
colour bright-red
circle +0 +0 +72
This would get translated by the JavaScript code in
flags.js to the following pseudo-
SVG:
svg viewbox="0 0 360 240" xmlns="http://www.w3.org/2000/svg"
g stroke="none" transform="matrix(1.5,0,0,-1,180,120)"
g
rect fill="#FFF" height="240" width="240" x="-120" y="-120" /
ellipse cx="+0" cy="+0" fill="#F00" rx="48" ry="+72" /
/g
/g
/svg
No comments:
Post a Comment