SVG Essentials/Programming Concepts

From WikiContent

< SVG Essentials(Difference between revisions)
Jump to: navigation, search
(Initial conversion from Docbook)
Current revision (13:40, 7 March 2008) (edit) (undo)
(Initial conversion from Docbook)
 
(2 intermediate revisions not shown.)

Current revision

SVG Essentials

Many graphic designers want to use the scripting capability of SVG as described in Chapter 11. If they're not familiar with programming, they tend to practice what might be called "voodoo scripting." In the popular-culture stereotype,[1] voodoo works by reciting a mysterious spell and hoping that your enemies die horribly. Voodoo scripting works by copying someone else's mysterious script into your SVG document and hoping that your document continues to live. We're under no illusion (nor even a spell) that reading this brief, purposely oversimplified summary will turn you into a master programmer. Our goal is simply to introduce enough of the elementary programming concepts to remove some of the mystery from the scripts that you copy and modify. The particular programming language that we will discuss in this appendix is called ECMA Script;[2] the concepts used in ECMA Script are common to many other programming languages.

Contents

Constants

A constant is a fancy word for a number or string of characters that never changes. Examples are 2, 2.71828, "message", and 'communication'. The last two are called string constants. In ECMA Script, you can use either single or double quotes to mark the boundaries of a string. This is good if you ever need to write things like "O'Reilly & Associates" or 'There is no "there" there.'.

You will sometimes see the two Boolean constants true and false, which are used for "yes-or-no" situations.

Variables

A variable is a block of memory reserved to hold some value that may change from time to time. You can think of it as a mailbox with a name on it; the mailbox holds a slip of paper with information written on it. Let's say you need to keep track of the current width of a rectangle and need to store a changeable message; in ECMA Script you define these variables like this:

var currentWidth;
var message;

You may visualize them as shown in Figure C-1.

Figure C-1. Two empty variables

Two empty variables

Variables defined this way have nothing in their "mailbox;" the technical term is that these variables contain the null value. Variable names must start with a letter or an underscore and can contain only letters, digits, and underscores. They are case sensitive, so width, Width, and WIDTH are names of three different variables.

Assignment and Operators

You can put a value into a variable by using an assignment statement, which starts with a variable name, an equal sign, and the value. Examples:

currentWidth = 32;
message = "I love SVG.";

You can read these as "set the value of currentWidth equal to 32" and "set the value of message equal to "I love SVG." In reality, this statement works from right to left; whatever is on the righthand side of the equal sign is placed into the variable on the lefthand side. Note that all our ECMA Script statements end with a semicolon. There are cases where you don't need one, but we'd rather have the semicolon and not need it than need it and not have it. Figure C-2 shows the "after" picture for these assignments.

Figure C-2. Two assigned variables

Two assigned variables

Actually, we told you a small lie a few sentences ago. Whatever the righthand side of the equal sign works out to goes into the variable on the lefthand side. This lets us do mathematical operations, as in the following code.

var info;     [1]
info = 7 + 2;     [2]
info = 7 * 2;     [3]
info = info + 1;     [4]
info = "door";     [5]
info = info + "bell"     [6]
         

[1] Create an empty variable named info.

[2] info will now contain the value 9 (seven plus two). You use the minus sign - for subtraction.

[3] The asterisk is used for multiplication, since the multiplication symbol is too easily confused with the letter x. info will contain 14 (seven times two). The previous value of nine will be discarded. You use the forward slash / for division.

[4] This is illegal in high school algebra, but not in ECMA Script. We start with the righthand side of the equal sign: take the current value of info, which is 14, and add one to it. The righthand side works out to 15. This result goes into the variable on the left side of the equal, which just happens to be info. At the end of this statement, info will contain the value 15.

[5] This takes the string "door" and puts it into info. In ECMA Script, a variable can hold any sort of information at any time.

[6] This takes the current value of info, which is "door", and "adds" (appends) the string constant "bell" to the end of it. The resulting value is the word "doorbell", which goes back into info on the left side of the equal sign. The plus sign is the only operator that works with strings; you can't subtract, multiply, or divide them.

You can define a variable and set its initial value all in one fell swoop. This is called initializing a variable. You can have more than one operation on the righthand side of the equal sign. In the following code, an empty variable named celsius is created, then a variable named fahrenheit with value 212, then the Fahrenheit temperature is converted to Celsius.

var celsius;
var fahrenheit = 212;
celsius = ((fahrenheit - 32) / 9 ) * 5;

Arrays

An array is an ordered collection of data, indexed by number. We compared a simple variable to a mailbox (send mail to the "Smith Residence"). An array is like a set of numbered apartment mailboxes (send mail to the "A-List Apartments, #12"). The only difference is that array index numbers start at zero rather than one.[3] Here's a declaration of an array of radius sizes for circles. This form initializes the array. The second statement sets the value of the last element of the array to 9. You access one of the "slots" of an array by putting its index number in square brackets. Figure C-3 shows the results after the code has finished.

var radiusSizes = new Array( 8.5, 6.4, 12.2, 7 );
radiusSizes[3] = 9;

Figure C-3. Depiction of an array

Depiction of an array

Comments

Comments provide a way to document your programs so that other people can figure out what you did. There are two kinds of comments in ECMA Script. If you place two forward slashes in a row (//) they and everything to the end of that line are considered to be a comment. If you want a multi-line comment, start with /* and end with */ as shown here:

var interest;   // this is accumulated on a daily basis
var rate;       // expressed as a decimal; 75% is a rate of 0.75

/* Figure out the payment amount given a principal
   of $10,000 and 180 monthly payments. */

Conditional Statements

Ordinarily, your program statements are carried out in the order in which they appear. Sometimes you may want to do different calculations depending upon some condition. You use the if statement to do this. Here's a calculation for wages that depends upon the number of hours worked. We presume that all the var statements have been set up appropriately.

if (hours <= 40)     [1]
{
    pay = hours * rate;     [2]
}
else     [3]
{
    pay = 40 * rate + (hours - 40) * rate * 1.5;     [4]
}

[1] The expression in the parentheses is called the condition. It always asks a yes-or-no question. In this case, the question is "is the value of the hours variable less than or equal to 40?" Other comparison operations are less than (<), greater than (>) greater than or equal (>=), exactly equal (==), and not equal (!=). Note that asking if two things are equal to each other requires two equal signs, not one!

[2] If the answer to the question is "yes," then the program will do everything between the opening and closing braces { and }...

[3] ...otherwise (else)...

[4] ...do everything between the other set of curly braces. The curly braces are used to signify that one or more statements should be grouped together, much in the way that XML opening and closing tags tell where content begins and end.

Repeated Actions

Sometimes you want to repeat an action a specific number of times ("fill ten two-liter containers from a large water tank"). You use a for loop to do the first sort of task. It's called a loop because, if you were to draw arrows representing the path the computer takes through your program, they would form a loop as the program repeated the actions. Here's the container-filling scenario translated into ECMA Script, with variables for the water tank and the containers presumed to be defined. The loop body, that is, the actions we want repeated, are enclosed in curly braces.

var i;              // a counter variable
for (i = 0;         // start counting at zero
     i < 10;        // up to (but not including) 10
     i++)           // add one to the count at every repetition
{
    tank[i] = 2;                // fill container number "i"
    waterTank = waterTank - 2;  // take 2 liters out of the tank
}

Other times you want to repeat an action as long as some condition is true ("keep filling two-liter containers from a large water tank as long as there is any water left"). For this, you use a while loop.

i = 0;                          // start with container number zero
while ( waterTank > 0 )         // while there is water left
{
    tank[i] = 2;                // fill container number "i"
    waterTank = waterTank - 2;  // take 2 liters out of the tank
    i = i + 1;                  // move on to the next container
}

Functions

You can accomplish some surprisingly sophisticated tasks with this small number of programming concepts. You collect sets of ECMA Script statements designed to perform a specific task into functions. Think of a function as a recipe card that gives a list of ingredients and instructions which, when followed, create a specific dish. A function starts with the keyword function followed by the function name. The name should be indicative of the task that it does, and it follows the same rules that variable names do. Following the function name, in parentheses, are the parameters of the function. A parameter is extra information that the function needs when it does its task. Consider this imaginary recipe:

Korean Kimch'i SurpriseTake 100 grams of kimch'i per serving, 25 grams of ko-ju-jang red pepper paste per serving, and 50 grams of mushrooms per serving. Mix well. Serve.

Before you can make the recipe, you have to supply some extra information — the number of servings you intend to make. Our script might look like this:

function makeKimchiSurprise( numberOfServings )
{
    var kimchi = 100 * numberOfServings;
    var kojujang = 25 * numberOfServings;
    var mushrooms = 50 * numberOfServings;
    var surprise = kimchi + kojujang + mushrooms;
}

This is only the definition of the function. It does absolutely nothing until it is invoked, or called on. (You may have hundreds of recipe cards in a file box at home. They just sit there, inactive, until someone asks you to pull one card out and perform the cooking tasks.) You will often call a function as the result of an event. In the following example a click on the blue rectangle will call the function. The number 5 in the parentheses will fill in the "extra information" required by the numberOfServings parameter.

<rect x="10" y="10" width="100" height="30" style="fill: blue;"
    onclick="makeKimchiSurprise( 5 )" />

Note

Even if the function doesn't need any parameters, you still have to put the parentheses after its name. This is how ECMA Script can tell the difference between a variable named area and a function called area().

Some functions can also call other functions. For example, a function that calculates compound interest might need to call upon another function that determines whether a year is a leap year or not. A parameter lets the interest function tell the leap year function what year it's interested in. The return statement will let the leap year function communicate its result back to the caller. This allows you to modularize a program into generally useful building blocks. In cooking terms, the makeHollandaiseSauce function can be called from the makeEggsBenedict function as well as from makeChickenFlorentine.

Objects, Properties, and Methods

Take a power supply with its on-off switch, a plastic dial, a lever with a spring, and a metal chassis with rectangular slots and coils of wire in it. Put all these parts together, and you get a toaster.

Each of these parts is an object. Some of them have characteristics that are of interest to us: The power supply has a voltage of 110 or 220 volts; the chassis has a color and a number of slots, and the dial has a minimum and maximum setting. (The lever has no interesting characteristics.)

You do actions with each of these objects: you push the lever down or pop it up, you insert bread into the slots, you turn the power supply on or off, and you turn the dial to the desired setting.

Let's take this toaster into the world of ECMA Script. Now our mailboxes don't just hold slips of paper; they can hold entire other mailboxes (just as objects have little objects inside them). We'll also let a mailbox hold recipe cards (functions) so that they can perform actions. When a variable is inside another variable, we call the inner variable a property. When a function is inside a mailbox, we call it a method. The diagram for the toaster looks like Figure C-4.

Figure C-4. The object diagram for a toaster

The object diagram for a toaster

We now have a very flexible way of modeling a toaster, but it's introduced a problem. We can't just say things like:

color = "gold";
voltage = 220;
popUp();

to set the toaster's color or voltage or to pop out the bread because the color property is nested inside the toaster variable, the voltage really belongs to the powerSupply inside the toaster, and it's the toaster's lever that does the popUp function. Instead, we must say:

toaster.color = "gold";
toaster.powerSupply.voltage = 220;
toaster.lever.popUp();

These are easy to figure out if we read them from right to left and say "of" whenever we see a period: "Put gold into the color of the toaster." "Put 220 into the voltage of the power supply of the toaster." "Call the pop up method of the lever of the toaster."[4] Think of this as the grown-up version of nested objects and methods that you learned as a child: "this is the dog that chased the cat that killed the rat that ate the malt that lay in the house that Jack built."

We have just used objects to model the behavior of a toaster; we've built a Toaster Object Model. Similarly, there is a Document Object Model (DOM) that lets ECMA Script access a document's properties and invoke its methods. Almost all of your access to an SVG document will be through methods that begin with the word set or get. For example, if you receive a mouse click event and want to find its x-coordinate, you would write evt.getClientX(). To set the radius of a <circle> element with an id of wheel, you might write svgDocument.getElementById("wheel").setAttribute("r", 3).

Note

The SVG Document Object Model is actually a superset of the XML Document Object Model; once you learn to manipulate the structure of an SVG document, you can immediately apply that knowledge to other XML documents, so the time you spend in learning the DOM will be amply repaid.

What, Not How

We've given you an overview of the what of programming, which can serve as a base for reading programs that other people have written and making sense of them (the programs, not the people). How you define a task and lay out the programming steps to solve it is another problem altogether, and far beyond the scope of this book. If you enjoy solving crossword puzzles or brain teasers, or just solving problems in general, you may well enjoy writing programs. If you would like to learn to write original programs in ECMA Script, I strongly recommend Danny Goodman's excellent JavaScript Bible, which is chock full of examples.

Notes

  1. Unlike the actual practice of Santería and voudon, which are much more complex and not inherently evil.
  2. It is the standardized version of the JavaScript language.
  3. This is not done to be contrary; it's because programs often use a mathematical formula to select the relevant item. These formulas are invariably easier when you start counting at zero.
  4. If you insist upon reading left to right, adapt the suggestion for reading path names made by Elizabeth Castro in her book, Visual Quickstart Guide to HTML for the World Wide Web: read the period as "contains." Then toaster.powerSupply.voltage = 220; is read as "the toaster contains a power supply, which contains a voltage. Set that voltage to 220."
Personal tools