SVG Essentials/Basic Shapes

(Difference between revisions)
 Revision as of 22:52, 6 March 2008 (edit)m (1 revision(s))← Previous diff Revision as of 23:33, 6 March 2008 (edit) (undo) (Initial conversion from Docbook)Next diff →

Revision as of 23:33, 6 March 2008

Once a coordinate system is established in the <svg> tag, you are ready to begin drawing. In this chapter, we will show the basic shapes you can use to create the major elements of most drawings: lines, rectangles, polygons, circles, and ellipses.

Lines

SVG lets you draw a straight line with the <line> element. Just specify the x- and y-coordinates of the line's endpoints. Coordinates may be specified without units, in which case they are considered to be user coordinates, or with units such as em, in, etc. as described in Chapter 2, in Section 2.1. The SVG in Example 3-1 draws several lines; the reference grid in Figure 3-1 is not part of the SVG that you see here.

```<line x1="start-x" y1="start-y"
x2="end-x" y2="end-y">
```

Example 3-1. Basic lines

```<svg width="200px" height="200px" viewBox="0 0 200 200">
<!-- horizontal line -->
<line x1="40" y1="20" x2="80" y2="20" style="stroke: black;"/>
<!-- vertical line -->
<line x1="0.7cm" y1="1cm" x2="0.7cm" y2="2.0cm" style="stroke: black;"/>
<!-- diagonal line -->
<line x1="30" y1="30" x2="85" y2="85" style="stroke: black;"/>
</svg>
```

Figure 3-1. Basic lines

Stroke Characteristics

Lines are considered to be strokes of a pen that draws on the canvas. The size, color, and style of the pen stroke are part of the line's presentation. Thus, these characteristics will go into the style attribute.

stroke-width

As mentioned in Chapter 2, the canvas grid lines are infinitely thin. Where, then, does a line or stroke fall in relation to the grid line? The answer is that the grid line falls in the center of a stroke. Example 3-2 draws some lines where the stroke width has been set to ten user coordinates to make the effect obvious. The result, in Figure 3-2, has the grid lines drawn in so you can see the effect clearly.

Example 3-2. Demonstration of stroke-width

```<svg width="200px" height="200px" viewBox="0 0 200 200">
<!-- horizontal line -->
<line x1="30" y1="10" x2="80" y2="10"
style="stroke-width: 10; stroke: black;"/>
<!-- vertical line -->
<line x1="10" y1="30" x2="10" y2="80"
style="stroke-width: 10; stroke: black;"/>
<!-- diagonal line -->
<line x1="25" y1="25" x2="75" y2="75"
style="stroke-width: 10; stroke: black;"/>
</svg>
```

Figure 3-2. Demonstration of stroke-width

stroke Color

You can specify the stroke color in a variety of ways:

• One of the color keyword names: aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, purple, red, silver, teal, white, and yellow.
• A six-digit hexadecimal specifier in the form # rr gg bb, where rr is the red component, gg is the green component, and bb is the blue component in the range 0-ff.
• A three-digit hexadecimal specifier in the form # r g b, where r is the red component, g is the green component, and b is the blue component in the range 0-f. This is a shorthand form of the previous method of specifying color. To produce the six-digit equivalent, each digit of the short form is duplicated; thus #d6e is the same as #dd66ee.
• An rgb specifier in the form rgb( red-value , green-value , blue-value ), where each value is in the range 0-255 or a percentage in the range 0% to 100%. Example 3-3 uses all of these methods, with the colorful results of Figure 3-3.

Example 3-3. Demonstration of stroke color

```<svg width="200px" height="200px" viewBox="0 0 200 200">
<!-- red -->
<line x1="10" y1="10" x2="50" y2="10"
style="stroke: red; stroke-width: 5;"/>

<!-- light green -->
<line x1="10" y1="20" x2="50" y2="20"
style="stroke: #9f9; stroke-width: 5;"/>

<!-- light blue -->
<line x1="10" y1="30" x2="50" y2="30"
style="stroke: #9999ff; stroke-width: 5;"/>

<!-- medium orange -->
<line x1="10" y1="40" x2="50" y2="40"
style="stroke: rgb(255, 128, 64); stroke-width: 5;"/>

<!-- deep purple -->
<line x1="10" y1="50" x2="50" y2="50"
style="stroke: rgb(60%, 20%, 60%); stroke-width: 5;"/>
</svg>
```

Figure 3-3. Demonstration of stroke color

stroke-opacity

Up to this point, all the lines in the example have been solid, obscuring anything beneath them. You control the opacity (which is the opposite of transparency) of a line by giving the stroke-opacity a value from 0.0 to 1.0, where zero is completely transparent and one is completely opaque. A value less than zero will be changed to zero; a value greater than one will be changed to one. Example 3-4 varies the opacity from 0.2 to 1 in steps of 0.2, with the result in Figure 3-4.

Example 3-4. Demonstration of stroke-opacity

```<svg width="200px" height="200px" viewBox="0 0 200 200">
<line x1="10" y1="10" x2="50" y2="10"
style="stroke-opacity: 0.2; stroke: black; stroke-width: 5;"/>
<line x1="10" y1="20" x2="50" y2="20"
style="stroke-opacity: 0.4; stroke: black; stroke-width: 5;"/>
<line x1="10" y1="30" x2="50" y2="30"
style="stroke-opacity: 0.6; stroke: black; stroke-width: 5;"/>
<line x1="10" y1="40" x2="50" y2="40"
style="stroke-opacity: 0.8; stroke: black; stroke-width: 5;"/>
<line x1="10" y1="50" x2="50" y2="50"
style="stroke-opacity: 1.0; stroke: black; stroke-width: 5;"/>
</svg>
```

Figure 3-4. Demonstration of stroke-opacity

stroke-dasharray attribute

If you need dotted or dashed lines, use the stroke-dasharray attribute, whose value consists of a list of numbers, separated by commas or white- space, specifying dash length and gaps. The list should have an even number of entries, but if you give an odd number of entries, SVG will repeat the list so the total number of entries is even. (See the last instance in Example 3-5.)

Example 3-5. Demonstration of stroke-dasharray

```<svg width="200px" height="200px" viewBox="0 0 200 200">
<!-- nine-pixel dash, five-pixel gap -->
<line x1="10" y1="10" x2="100" y2="10"
style="stroke-dasharray: 9, 5;
stroke: black; stroke-width: 2;"/>

<!-- five-pixel dash, three-pixel gap, nine-pixel dash, two-pixel gap -->
<line x1="10" y1="20" x2="100" y2="20"
style="stroke-dasharray: 5, 3, 9, 2;
stroke: black; stroke-width: 2;"/>

<!-- Odd number of entries is duplicated; this is equivalent to:
nine-pixel dash, three-pixel gap,  five-pixel dash,
nine-pixel gap,  three-pixel dash, five-pixel gap -->
<line x1="10" y1="30" x2="100" y2="30"
style="stroke-dasharray: 9, 3, 5;
stroke: black; stroke-width: 2;"/>
</svg>
```

Figure 3-5 shows the results, zoomed in for clarity.

Figure 3-5. Demonstration of stroke-dasharray

Rectangles

The rectangle is the simplest of the basic shapes. You specify the x- and y-coordinates of the upper left corner of the rectangle,[1] its width, and its height. The interior of the rectangle is filled with the fill color you specify. If you do not specify a fill color, the interior of the shape is filled with black. The fill color may be specified in any of the ways described in Section 3.2.2, or it may take the value none to leave the interior unfilled and thus transparent. You may also specify a fill-opacity in the same format as you did in Section 3.2.3. Both fill and fill-opacity are presentation properties, and belong in the style attribute.

After the interior is filled (if necessary), the outline of the rectangle is drawn with strokes, whose characteristics you may specify as you did for lines. If you do not specify a stroke, the value none is presumed, and no outline is drawn. Example 3-6 draws several variations of the <rect> element. Figure 3-6 shows the result, with a grid for reference.

Example 3-6. Demonstration of the rectangle element

```<svg width="200px" height="200px" viewBox="0 0 200 200">
<!-- black interior, no outline -->
<rect x="10" y="10" width="30" height="50"/>

<!-- no interior, black outline -->
<rect x="50" y="10" width="20" height="40"
style="fill: none; stroke: black;"/>

<!-- blue interior, thick semi-transparent red outline -->
<rect x="10" y="70" width="25" height="30"
style="fill: #0000ff;
stroke: red; stroke-width: 7; stroke-opacity: 0.5;"/>

<!-- semi-transparent yellow interior, dashed green outline -->
<rect x="50" y="70" width="35" height="20"
style="fill: yellow; fill-opacity: 0.5;
stroke: green; stroke-width: 2; stroke-dasharray: 5 2"/>
</svg>
```

Figure 3-6. Demonstration of the rect element

Note

Since the strokes that form the outline "straddle" the abstract grid lines, the strokes will be half inside the shape and half outside the shape. Figure 3-7, a closeup of the semi-transparent red outline drawn in Example 3-6, shows this clearly.

Figure 3-7. Closeup of transparent border

If you do not specify a starting x or y value, it is presumed to be zero. If you specify a width or height of zero, then the rectangle is not displayed. It is an error to provide negative values for either width or height.

Rounded Rectangles

If you wish to have rectangles with rounded corners, specify the x- and y-radius of the corner curvature. The maximum number you may specify for rx (the x-radius) is one-half the width of the rectangle; the maximum value of ry (the y-radius) is one-half the height of the rectangle. If you specify only one of rx or ry, they are presumed to be equal. Example 3-7 shows various combinations of rx and ry.

Example 3-7. Demonstration of rounded rectangles

```<svg width="200px" height="200px" viewBox="0 0 200 200">
<!-- rx and ry equal, increasing -->
<rect x="10" y="10" width="20" height="40" rx="2" ry="2"
style="stroke: black; fill: none;"/>

<rect x="40" y="10" width="20" height="40" rx="5"
style="stroke: black; fill: none;"/>

<rect x="70" y="10" width="20" height="40" ry="10"
style="stroke: black; fill: none;"/>

<!-- rx and ry unequal -->
<rect x="10" y="60" width="20" height="40" rx="10" ry="5"
style="stroke: black; fill: none;"/>

<rect x="40" y="60" width="20" height="40" rx="5" ry="10"
style="stroke: black; fill: none;"/>
</svg>
```

Figure 3-8 shows the result, with a grid in the background for reference.

Figure 3-8. Demonstration of rounded rectangles

Circles and Ellipses

To draw a circle, use the <circle> element and specify the center x-coordinate, center y-coordinate, and radius with the cx, cy, and r attributes. As with a rectangle, the default is to fill the circle with black and draw no outline unless you specify some other combination of fill and stroke.

An ellipse also needs an x-radius and a y-radius in addition to a center x- and y-coordinate. The attributes for these radii are named rx and ry.

In both circles and ellipses, if the cx or cy is omitted, it is presumed to be zero. If the radius is zero, no shape will be displayed; it is an error to provide a negative radius. Example 3-8 draws some circles and ellipses which are shown in Figure 3-9.

Example 3-8. Demonstration of circles and ellipses

```<svg width="200px" height="200px" viewBox="0 0 200 200">
<circle cx="30" cy="30" r="20" style="stroke: black; fill: none;"/>
<circle cx="80" cy="30" r="20"
style="stroke-width: 5; stroke: black; fill: none;"/>

<ellipse cx="30" cy="80" rx="10" ry="20"
style="stroke: black; fill: none;"/>
<ellipse cx="80" cy="80" rx="20" ry="10"
style="stroke: black; fill: none;"/>
</svg>
```

Figure 3-9. Demonstration of circle and ellipse elements

The polygon Element

In addition to rectangles, circles, and ellipses, you may want to draw hexagons, octagons, stars, or arbitrary closed shapes. The <polygon> element lets you specify a series of points that describe a geometric area to be filled and outlined as described earlier. The points attribute consists of a series of x- and y-coordinate pairs separated by commas or whitespace. You must give an even number of entries in the series of numbers. You don't have to return to the starting point; the shape will automatically be closed. Example 3-9 uses the <polygon> element to draw a parallelogram, a star, and an irregular shape.

Example 3-9. Demonstration of the polygon element

```<svg width="200px" height="200px" viewBox="0 0 200 200">
<!-- parallelogram -->
<polygon points="15,10  55, 10  45, 20  5, 20"
style="fill: red; stroke: black;"/>

<!-- star -->
<polygon
points="35,37.5  37.9,46.1 46.9,46.1  39.7,51.5
42.3,60.1  35,55  27.7,60.1  30.3,51.5
23.1,46.1  32.1,46.1"
style="fill: #ccffcc; stroke: green;"/>

<!-- weird shape -->
<polygon
points="60 60,  65 72,  80 60,  90 90, 72 80, 72 85, 50 95"
style="fill: yellow; fill-opacity: 0.5; stroke: black;
stroke-width: 2;"/>
</svg>
```

The results, with a grid in the background for reference, are displayed in Figure 3-10.

Figure 3-10. Demonstration of the polygon element

Filling Polygons That Have Intersecting Lines

For the polygons shown so far, it's been easy to fill the shape. Since none of the lines forming the polygon cross over one another, the interior is easily distinguished from the exterior of the shape. However, when lines cross over one another, the determination of what is inside the polygon is not as easy. The SVG in Example 3-10 draws such a polygon. In Figure 3-11, is the middle section of the star considered to be inside or outside?

Example 3-10. Unfilled polygon with intersecting lines

```<svg width="200px" height="200px" viewBox="0 0 200 200">

<polygon  points="48,16  16,96  96,48  0,48  80,96"
style="stroke: black; fill: none;"/>

</svg>
```

Figure 3-11. Unfilled polygon with intersecting lines

SVG has two different rules for determining whether a point is inside a polygon or outside it. The fill-rule (which is part of presentation) has a value of either nonzero or evenodd. Depending on the rule you choose, you get a different effect. Example 3-11 uses the rules to fill two diagrams of the star, as shown in Figure 3-12.

Example 3-11. Effect of different fill-rules

```<svg width="200px" height="200px" viewBox="0 0 200 200">

<polygon style="fill-rule: nonzero; fill: yellow; stroke: black;"
points="48,16  16,96  96,48  0,48  80,96" />

<polygon style="fill-rule: evenodd;  fill: #00ff00; stroke: black;"
points="148,16  116,96  196,48  100,48  180,96" />

</svg>
```

Figure 3-12. Effect of different fill-rules

The polyline Element

Finally, to round out our discussion of basic shapes, we'll return to straight lines. Sometimes you want a series of lines that does not make a closed shape. You can use multiple <line> elements, but if there are many lines it might be easier to use the <polyline> element. It has the same attributes as <polygon>, except that the shape is not closed. Example 3-12 draws the symbol for an electrical resistor, shown in Figure 3-13.

Example 3-12. Example of the polyline element

```<svg width="200px" height="200px" viewBox="0 0 200 200">

<polyline
points="5 20, 20 20, 25 10, 35 30, 45 10,
55 30, 65 10, 75 30, 80 20, 95 20"
style="stroke: black; stroke-width: 3; fill: none;"/>

</svg>
```

Figure 3-13. Example of the polyline element

Warning

It's best to set the fill property to none when using <polyline>; otherwise, the SVG viewer attempts to fill the shape, sometimes with startling results like those in Figure 3-14.

Figure 3-14. Example of filled polyline

Line Caps and Joins

When drawing a <line> or <polyline>, you may specify the shape of the endpoints of the lines by setting the stroke-linecap style property to one of the values butt, round, or square. Example 3-13 shows these three values, with gray guide lines showing the actual endpoints of the lines. You can see in Figure 3-15 that round and square extend beyond the end coordinates; butt, the default, ends exactly at the specified endpoint.

Example 3-13. Values of the stroke-linecap property

```<line x1="10" y1="15" x2="50" y2="15"
style="stroke-linecap: butt; stroke-width: 15;"/>

<line x1="10" y1="45" x2="50" y2="45"
style="stroke-linecap: round; stroke-width: 15;"/>

<line x1="10" y1="75" x2="50" y2="75"
style="stroke-linecap: square; stroke-width: 15;"/>

<!-- guide lines -->
<line x1="10" y1="0" x2="10" y2="100" style="stroke: #999;"/>
<line x1="50" y1="0" x2="50" y2="100" style="stroke: #999;"/>
```

Figure 3-15. Values of the stroke-linecap attribute

You may specify the way lines connect at the corners of a shape with the stroke-linejoin style property, which may have the values miter (pointed), round (round -- what did you expect?), or bevel (flat). Example 3-14 produces the result shown in Figure 3-16.

Example 3-14. Values of the stroke-linejoin attribute

```<polyline
style="stroke-linejoin: miter; stroke: black; stroke-width: 12;
fill: none;"
points="30 30, 45 15, 60 30"/>

<polyline
style="stroke-linejoin: round; stroke: black; stroke-width: 12;
fill: none;"
points="90 30, 105 15, 120 30"/>

<polyline
style="stroke-linejoin: bevel; stroke-width: 12; stroke: black;
fill: none;"
points="150 30, 165 15, 180 30"/>
```

Figure 3-16. Values of the stroke-linejoin attribute

Note

If your lines meet at a sharp angle and have a mitered join, it's possible for the pointed part to extend beyond the lines' thickness. You may set the ratio of the miter to the thickness of the lines being joined with the stroke-miterlimit style property; its default value is 4.

Basic Shapes Reference Summary

The following tables summarize the basic shapes and presentation styles in SVG.

Shape Elements

Table 3-1 summarizes the basic shapes available in SVG.

Table 3-1. Table of shape elements

Shape Description
<line x1="start-x" y1="start-y" x2="end-x" y2="end-y"/> Draws a line from the starting point at coordinates (start-x, start-y) to the ending point at coordinates (end-x, end-y).
<rect x="left-x" y="top-y" width="width" height="height"/> Draws a rectangle whose upper left corner is at (left-x, top-y) with the given width and height.
<circle cx="center-x" cy="center-y" r="radius"/> Draws a circle with the given radius, centered at (center-x, center-y).
<polygon points="points-specifications"/> Draws an arbitrary closed polygon whose outline is described by the points-specification. The points are specified as pairs of x- and y-coordinates. These are user coordinates only; you may not add a length unit specifier.
<polyline points="points-specifications"/> Draws an arbitrary series of connected lines as described by the points-specification. The points are specified as pairs of x- and y-coordinates. These are user coordinates only; you may not add a length unit specifier.

In all but the last two elements of Table 3-1, you may specify the attributes as simple numbers, in which case they will be presumed to be measured in user coordinates, or you may add a length unit specifier such as mm, pt, etc. For example:

```<line x1="1cm" y1="30" width="50" height="10pt"/>
```

Specifying Colors

You may specify the color for filling or outlining a shape in one of the following ways:

• none, indicating that no outline is to be drawn or that the shape is not to be filled.
• A color name, which is one of aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, purple, red, silver, teal, white, or yellow.
• Six hexadecimal digits # rrggbb, each pair describing red, green, and blue values.
• Three hexadecimal digits # rgb, describing the red, green, and blue values. This is a shorthand for the previous method; digits are replicated so that # rgb is equivalent to # rrggbb.
• rgb( r , g , b ), each value ranging from 0-255 or from 0% to 100%.

Stroke and Fill Characteristics

In order to see a line or the outline of a shape, you must specify the stroke characteristics, using the following attributes. A shape's outline is drawn after its interior is filled. All of these characteristics, summarized in Table 3-2, are presentation properties, and go in a style attribute.

Table 3-2. Stroke characteristics

Attribute Values
stroke The stroke color, as described in Section 3.8.2.
stroke-width Width of stroke; may be given as user coordinates or with a length specifier. The stroke width is centered along the abstract grid lines.
stroke-opacity A number ranging from 0.0 to 1.0; 0.0 is entirely transparent, 1.0 is entirely opaque.
stroke-dasharray A series of numbers that tell the length of dashes and gaps with which a line is to be drawn. These numbers are in user coordinates only.
stroke-linecap Shape of the ends of a line; has one of the values butt (the default), round, or square.
stroke-linejoin The shape of the corners of a polygon or series of lines; has one of the values miter (pointed; the default), round, or bevel (flat).
stroke-miterlimit Maximum ratio of length of the miter point to the width of the lines being drawn; the default value is 4.

You can control the way in which the interior of a shape is to be filled by using one of the fill attributes shown in Table 3-3. A shape is filled before its outline is drawn.

Table 3-3. Fill characteristics

Attribute Values
fill The fill color, as described in Section 3.8.2.
fill-opacity A number ranging from 0.0 to 1.0; 0.0 is entirely transparent, 1.0 is entirely opaque.
fill-rule This attribute can have the values nonzero or evenodd, which apply different rules for determining whether a point is inside or outside a shape. These rules generate different effects only when a shape has intersecting lines or "holes" in it. Details are in Section 3.5.1 earlier in this chapter.

Notes

1. Technically, the x value is the smaller of the x-coordinate values and the y is the smaller of the y-coordinate values of the rectangle's sides in the current user coordinate system. Since we are not yet using transformations, which we will cover in Chapter 5, this is the moral equivalent of the upper left corner.