[转]深入SVG路径-使用PATH

http://blog.csdn.net/xcl119xcl/article/details/5798312

http://blog.csdn.net/seacean2000/article/details/8490341

http://commons.oreilly.com/wiki/index.php/SVG_Essentials/Paths#Elliptical_Arc

SVG Essentials/Paths

SVG Essentials

All of the basic shapes described in Chapter 3 are really shorthand forms for the more general <path> element. You are well advised to use these shortcuts; they help make your SVG more readable and more structured. The <path> element is more general; it draws the outline of any arbitrary shape by specifying a series of connected lines, arcs, and curves. This outline can be filled and drawn with a stroke, just as the basic shapes are. Additionally, these paths (as well as the shorthand basic shapes) may be used to define the outline of a clipping area or a transparency mask, as you will see in Chapter 9.

All of the data describing an outline is in the <path> element’s d attribute (the d stands for data). The path data consists of one-letter commands, such as M for moveto or L for lineto, followed by the coordinate information for that particular command.

Contents

[hide]

moveto, lineto, and closepath

Every path must begin with a moveto command. The command letter is a capital M followed by an x- and y-coordinate, separated by commas or whitespace. This command sets the current location of the “pen” that’s drawing the outline.

This is followed by one or more lineto commands, denoted by a capital L, also followed by x- and y-coordinates, and separated by commas or whitespace. Example 6-1 has three paths. The first draws a single line, the second draws a right angle, and the third draws two thirty-degree angles. When you “pick up” the pen with another moveto, you are starting a new subpath. Notice that the use of commas and whitespace as separators is different, but perfectly legal, in all three paths. The result is Figure 6-1.

Example 6-1. Using moveto and lineto

<g style="stroke: black; fill: none;">
    <!-- single line -->
    <path d="M 10 10 L 100 10"/>
    
    <!-- a right angle -->
    <path d="M 10, 20  L 100, 20  L  100,50"/>
    
    <!-- two thirty-degree angles -->
    <path d="M 40 60, L 10 60, L 40 42.68,
       M 60 60, L 90 60, L 60 42.68"/>
</g>

Examining the last path more closely:

Value Action
M 40 60 Move pen to (40, 60)
L 10 60 Draw a line to (10, 60)
L 40 42.68 Draw a line to (40, 42.68)
M 60 60 Start a new subpath; move pen to (60, 60) — no line is drawn
L 90 60 Draw a line to (90, 60)
L 60 42.68 Draw a line to (60, 42.68)

Figure 6-1. Result of using moveto and lineto

Result of using moveto    and lineto

Note

You may have noticed that the path data doesn’t look very much like the typical values for XML attributes. Because the entire path data is contained in one attribute rather than an individual element for each point or line segment, a path takes up less memory when read into a Document Object Model structure by an XML parser. Additionally, a path’s compact notation allows a complex graphic to be transmitted without requiring a great deal of bandwidth.

If you want to use a <path> to draw a rectangle, you can draw all four lines, or you can draw the first three lines and then use the closepath command, denoted by a capital Z, to draw a straight line back to the beginning point of the current subpath. Example 6-2 is the SVG for Figure 6-2, which shows a rectangle drawn the hard way, a rectangle drawn with closepath, and a path that draws two triangles by opening and closing two subpaths.

Example 6-2. Using closepath

<g style="stroke: black; fill: none;">
    <!-- rectangle; all four lines -->
    <path d="M 10 10, L 40 10, L 40 30, L 10 30, L 10 10"/>
    
    <!-- rectangle with closepath -->
    <path d="M 60 10, L 90 10, L 90 30, L 60 30, Z"/>
    
    <!-- two thirty-degree triangles -->
    <path d="M 40 60, L 10 60, L 40 42.68, Z
       M 60 60, L 90 60, L 60 42.68, Z"/>
</g>

Examining the last path more closely:

Value Action
M 40 60 Move pen to (40, 50)
L 10 60 Draw a line to (10, 60)
L 40 42.68 Draw a line to (40, 42.68)
Z Close path by drawing a straight line to (40, 60), where this subpath began
M 60 60 Start a new subpath; move pen to (60, 60) — no line is drawn
L 90 60 Draw a line to (90, 60)
L 60 42.68 Draw a line to (60, 42.68)
Z Close path by drawing a straight line to (60, 60), where this subpath began

Figure 6-2. Result of using closepath

Result of using closepath

Relative moveto and lineto

The preceding commands are all represented by uppercase letters, and the coordinates are presumed to be absolute coordinates. If you use a lowercase command letter, the coordinates are interpreted as being relative to the current pen position. Thus, the following two paths are equivalent:

<path d="M 10 10 L 20 10 L 20 30  M 40 40 L 55 35"
    style="stroke: black;"/>
<path d="M 10 10 l 10  0 l  0 20  m 20 10 l 15 -5"
    style="stroke: black;"/>

If you start a path with a lowercase m (moveto), its coordinates will be interpreted as an absolute position since there’s no previous pen position from which to calculate a relative position. All the other commands in this chapter also have the same upper- and lowercase distinction. An uppercase command’s coordinates are absolute and a lowercase command’s coordinates are relative. Theclosepath command, which has no coordinates, has the same effect in both upper- and lowercase.

Path Shortcuts

If content is king and design is queen, then bandwidth efficiency is the royal courtier who keeps the palace running smoothly. Since any non-trivial drawing will have paths with many tens of coordinate pairs, the <path> element has shortcuts that allow you to represent a path in as few bytes as possible.

The Horizontal lineto and Vertical lineto Commands

Since horizontal and vertical lines are so common, a path may specify a horizontal line with an H command followed by an absolute x-coordinate or an h command followed by a relative x-coordinate. Similarly, a vertical line is specified with a V command followed by an absolute y-coordinate or a v command followed by a relative y-coordinate.

Shortcut Equivalent to Effect
H 20 L 20 current_y Draws a line to absolute location (20, current_y)
h 20 l 20 0 Draws a line to (current_x+20, current_y)
V 20 L current_x 20 Draws a line to absolute location (current_x, 20)
v 20 l current_x 20 Draws a line to location (current_x, current_y+20)

Thus, the following path draws a rectangle 15 units in width and 25 units in height, with the upper left corner at coordinates (12, 24).

<path d="M 12 24 h 15 v 25 h -15 z"/>

Notational Shortcuts for a Path

Paths can also be made shorter by applying the following two rules:

  1. You may place multiple sets of coordinates after an L or l, just as you do in the <polyline> element. The following six paths all draw the same diamond that is shown in Figure 6-3; the first three are in absolute coordinates and the last three in relative coordinates. The third and sixth paths have an interesting twist — if you place multiple pairs of coordinates after a moveto, all the pairs after the first are presumed to be preceded by a lineto.[1]

    <path d="M 30 30 L 55 5 L 80 30 L 55 55 Z"/>
    <path d="M 30 30 L 55 5 80 30 55 55 Z"/>
    <path d="M 30 30 55 5 80 30 55 55 Z"/>
    <path d="m 30 30 l 25 -25 l 25 25 l -25 25 z"/>
    <path d="m 30 30 l 25 -25 25 25 -25 25 z"/>
    <path d="m 30 30 25 -25 25 25 -25 25 z"/>
    

    Figure 6-3. Result of drawing a diamond with a path

    Result of drawing a diamond with a    path

  2. Any whitespace that is not necessary may be eliminated. You don’t need a blank after a command letter since all commands are one letter only. You don’t need a blank between a number and a command since the command letter can’t be part of the number. You don’t need a blank between a positive and a negative number since the leading minus sign of the negative number can’t be a part of the positive number. This lets you reduce the third and sixth paths in the preceding listing even further:

    <path d="M30 30 55 5 80 30 55 55Z"/>
    <path d="m30 30 25-25 25 25-25 25z"/>
    

    Another example of the whitespace elimination rule in action is shown by the example that drew a rectangle 15 units in width and 25 units in height, with the upper left corner at coordinates (12, 24):

    <path d="M 12 24 h 15 v 25 h -15 z"/> <!-- original -->
    <path d="M12 24h15v25h-15z"/> <!-- shorter -->
    

Elliptical Arc

Lines are simple; two points on a path uniquely determine the line segment between them. Since an infinite number of curves can be drawn between two points, you must give additional information to draw a curved path between them. The simplest of the curves we will examine is the elliptical arc — that is, drawing a section of an ellipse that connects two points.

Although arcs are visually the simplest curves, specifying a unique arc requires the most information. The first pieces of information you need to specify are the x– and y-radii of the ellipse on which the points lie. This narrows it down to two possible ellipses, as you can see in section (a) of Figure 6-4. The two points divide the two ellipses into four arcs. Two of them, (b) and (c), are arcs that measure less than 180 degrees. The other two, (d) and (e) are greater than 180 degrees. If you look at (b) and (c), you will notice that they are differentiated by their direction; (b) is drawn in the direction of increasing negative angle, and (c) in the direction of increasing positive angle. The same relationship holds true between (d) and (e).

But wait — we still haven’t uniquely specified the potential arcs! There’s no law that says that the ellipse has to have its x-radius parallel to the x-axis. Part (f) of Figure 6-4 shows the two points with their candidate ellipses rotated thirty degrees with respect to the x-axis.

Figure 6-4. Variations of the elliptical arc command

Variations of the elliptical arc    command

(Figure 6-4 is adapted from the one found in section 8.3.8 of the World Wide Web Consortium’s SVG specification.)

Thus, an arc command begins with the A abbreviation for absolute coordinates or a for relative coordinates, and is followed by seven parameters:

  • The x– and y-radius of the ellipse on which the points lie.
  • The x-axis-rotation of the ellipse.
  • The large-arc-flag, which is zero if the arc’s measure is less than 180 degrees, or one if the arc’s measure is greater than or equal to 180 degrees.
  • The sweep-flag, which is zero if the arc is to be drawn in the negative angle direction, or one if the arc is to be drawn in the positive angle direction.
  • The ending x– and y– coordinates of the ending point. (The starting point is determined by the last point drawn or the last moveto command.)

Here are the paths used to draw the elliptical arcs in sections (b) through (e) of Figure 6-4:

<path d="M 125,75 A100,50 0 0,0 225,125"/> <!-- b -->
<path d="M 125,75 A100,50 0 0,1 225,125"/> <!-- c -->
<path d="M 125,75 A100,50 0 1,0 225,125"/> <!-- d -->
<path d="M 125,75 A100,50 0 1,1 225,125"/> <!-- e -->

As a further example, let’s enhance the background that we started in Example 4-8 to complete the yin/yang symbol that is part of the Korean flag. Example 6-3 keeps the full ellipses as <ellipse>elements, but creates the semicircles that it needs with paths. The result is shown in Figure 6-5.

Example 6-3. Using elliptical arc

<!-- gray drop shadow -->
<ellipse cx="154" cy="154" rx="150" ry="120" style="fill: #999999;"/>

<!-- light blue ellipse -->
<ellipse cx="152" cy="152" rx="150" ry="120" style="fill: #cceeff;"/>

<!-- large light red semicircle fills upper half,
     followed by small light red semicircle that dips into
     lower left half of symbol -->
<path d="M 302 152 A 150 120, 0, 1, 0, 2 152
    A 75 60, 0, 1, 0, 152 152" style="fill: #ffcccc;"/>

<!-- light blue semicircle rises into upper right half of symbol -->
<path d="M 152 152 A 75 60, 0, 1, 1, 302 152" style="fill: #cceeff;"/>

Figure 6-5. Result of using elliptical arc

Result of using elliptical arc

Technique: Converting from Other Arc Formats

Some other vector graphics systems let you specify an arc by defining a center point for the ellipse, its x– and y-radius, the starting angle, and the extent of the angle’s arc. This is a straightforward method of specification, and is excellent for drawing arcs as single objects. This, paradoxically, is exactly why SVG instead chooses such a seemingly eccentric method to specify arcs. In SVG, an arc is not presumed to be living in lonely splendor; it is intended to be part of a connected path of lines and curves. (For example, a rounded rectangle is precisely that — a series of lines and elliptical arcs.) Thus, it makes sense to specify an arc by its endpoints.

Sometimes, though, you do want an isolated semicircle (or, more accurately, semi-ellipse). Presume that you have an ellipse specified as:

<ellipse cx="cx" cy="cy" rx="rx" ry="ry"/>

Here are the paths to draw the four possible semi-ellipses:

<!-- northern hemisphere -->
<path d="M cx-rx 
            cy A rx 
            ry 0 1 1 cx+rx 
            cy"/>
<!-- southern hemipshere -->
<path d="M cx-rx 
            cy A rx 
            ry 0 1 0 cx+rx 
            cy"/>
<!-- eastern hemisphere -->
<path d="M cx 
            cy-ry A rx 
            ry 0 1 1 cx 
            cy+ry"/>
<!-- western hemisphere -->
<path d="M cx 
            cy-ry A rx 
            ry 0 1 0 cx 
            cy+ry"/>

For the more general case, when you wish to draw an arbitrary arc that has been specified in “center-and-angles” notation and wish to convert it to SVG’s “endpoint-and-sweep” format, use the following Perl script. It prompts you for center coordinates, radii, starting angle, and angle extent. The output is a <path> tag that you can insert into your SVG files.

#!/usr/bin/perl
use Math::Trig;

#
#   Convert an elliptical arc based around a central point
#   to an elliptical arc parameterized for SVG.
#
#   Input is a list containing:
#       center x coordinate
#       center y coordinate
#       x-radius of ellipse
#       y-radius of ellipse
#       beginning angle of arc in degrees
#       arc extent in degrees
#       x-axis rotation angle in degrees
#
#   Output is a list containing:
#
#       x-coordinate of beginning of arc
#       y-coordinate of beginning of arc
#       x-radius of ellipse
#       y-radius of ellipse
#       large-arc-flag as defined in SVG specification
#       sweep-flag  as defined in SVG specification
#       x-coordinate of endpoint of arc
#       y-coordinate of endpoint of arc
#
sub convert_to_svg
{
    my ($cx, $cy, $rx, $ry, $theta1, $delta, $phi) = @_;

    my $theta2 = $delta + $theta1;
    $theta1 = deg2rad($theta1);
    $theta2 = deg2rad($theta2);
    my $phi_r = deg2rad($phi);

    #
    #   Figure out the coordinates of the beginning and
    #   ending points
    #
    my $x0 = $cx + cos($phi_r) * $rx * cos($theta1) +
        sin(-$phi_r) * $ry * sin($theta1);
    my $y0 = $cy + sin($phi_r) * $rx * cos($theta1) +
        cos($phi_r) * $ry * sin($theta1);

    my $x1 = $cx + cos($phi_r) * $rx * cos($theta2) +
        sin(-$phi_r) * $ry * sin($theta2);
    my $y1 = $cy + sin($phi_r) * $rx * cos($theta2) +
        cos($phi_r) * $ry * sin($theta2);

    my $large_arc = ($delta > 180) ? 1 : 0;
    my $sweep = ($delta > 0) ? 1 : 0;
    
    return ($x0, $y0, $rx, $ry, $phi, $large_arc, $sweep, $x1, $y1);
}

#
#   Request input
#
print "Enter center x,y coordinates > ";
$data = <>;
$data =~ s/,/ /g;
($cx, $cy) = split /\s+/, $data;

print "Enter x and y radii > ";
$data = <>;
$data =~ s/,/ /g;
($rx, $ry) = split/\s+/, $data;

print "Enter starting angle in degrees > ";
$theta = <>;
chomp $theta;

print "Enter angle extent in degrees > ";
$delta = <>;
chomp $delta;

print "Enter angle of rotation in degrees > ";
$phi = <>;
chomp $phi;

#
#   Echo original data
#
print "(cx,cy)=($cx,$cy)  rx=$rx ry=$ry ",
    "start angle=$theta extent=$delta rotate=$phi\n";

($x0, $y0, $rx, $ry, $phi, $large_arc_flag, $sweep_flag, $x1, $y1) =
    convert_to_svg( $cx, $cy, $rx, $ry, $theta, $delta, $phi);

#
#   Produce a <path> element that fits the
#   specifications
#
print "<path d=\"M $x0 $y0 ",   # Moveto initial point
    "A $rx $ry ",               # Arc command and radii,
    "$phi ",                    # angle of rotation,
    "$large_arc_flag ",         # the "large-arc" flag,
    "$sweep_flag ",             # the "sweep" flag,
    "$x1 $y1\"/>\n";            # and the endpoint

If you wish to convert from the SVG format to a “center-and-angles” format, the mathematics is considerably more complex. You can see the formulas in detail in the SVG specification. This Perl script was adapted from the code in the Apache XML Batik project.

#!/usr/bin/perl
use Math::Trig;

#
#   Convert an elliptical arc based around a central point
#   to an elliptical arc parameterized for SVG.
#
#   Input is a list containing:
#
#       x-coordinate of beginning of arc
#       y-coordinate of beginning of arc
#       x-radius of ellipse
#       y-radius of ellipse
#       large-arc-flag as defined in SVG specification
#       sweep-flag  as defined in SVG specification
#       x-coordinate of endpoint of arc
#       y-coordinate of endpoint of arc
#
#   Output is a list containing:
#       center x coordinate
#       center y coordinate
#       x-radius of ellipse
#       y-radius of ellipse
#       beginning angle of arc in degrees
#       arc extent in degrees
#       x-axis rotation angle in degrees
#

sub convert_from_svg
{
    my ($x0, $y0, $rx, $ry, $phi, $large_arc, $sweep, $x, $y) = @_;
    
    # Compute 1/2 distance between current and final point
    my $dx2 = ($x0 - $x) / 2.0;
    my $dy2 = ($y0 - $y) / 2.0;

    # Convert from degrees to radians
    $phi %= 360;
    my $phi_r = deg2rad($phi);

    # Compute (x1, y1)
    my $x1 = cos($phi_r) * $dx2 + sin($phi_r) * $dy2;
    my $y1 = -sin($phi_r) * $dx2 + cos($phi_r) * $dy2;

    # Make sure radii are large enough
    $rx = abs($rx); $ry = abs($ry);
    my $rx_sq = $rx * $rx;
    my $ry_sq = $ry * $ry;
    my $x1_sq = $x1 * $x1;
    my $y1_sq = $y1 * $y1;

    $radius_check = ($x1_sq / $rx_sq) + ($y1_sq / $ry_sq);
    if ($radius_check > 1)
    {
        $rx *= sqrt($radius_check);
        $ry *= sqrt($adius_check);
        $rx_sq = $rx * $rx;
        $ry_sq = $ry * $ry;
    }

    # Step 2: Compute (cx1, cy1)

    my $sign = ($large_arc == $sweep) ? -1 : 1;
    my $sq = (($rx_sq * $ry_sq) - ($rx_sq * $y1_sq) - ($ry_sq * $x1_sq)) /
        (($rx_sq * $y1_sq) + ($ry_sq * $x1_sq));
    $sq = ($sq < 0) ? 0 : $sq;
    my $coef = $sign * sqrt($sq);
    my $cx1 = $coef * (($rx * $y1) / $ry);
    my $cy1 = $coef * -(($ry * $x1) / $rx);

    #   Step 3: Compute (cx, cy) from (cx1, cy1)

    my $sx2 = ($x0 + $x) / 2.0;
    my $sy2 = ($y0 + $y) / 2.0;

    my $cx = $sx2 + (cos($phi_r) * $cx1 - sin($phi_r) * $cy1);
    my $cy = $sy2 + (sin($phi_r) * $cx1 + cos($phi_r) * $cy1);

    #   Step 4: Compute angle start and angle extent

    my $ux = ($x1 - $cx1) / $rx;
    my $uy = ($y1 - $cy1) / $ry;
    my $vx = (-$x1 - $cx1) / $rx;
    my $vy = (-$y1 - $cy1) / $ry;
    my $n = sqrt( ($ux * $ux) + ($uy * $uy) );
    my $p = $ux; # 1 * ux + 0 * uy
    $sign = ($uy < 0) ? -1 : 1;

    my $theta = $sign * acos( $p / $n );
    $theta = rad2deg($theta);

    $n = sqrt(($ux * $ux + $uy * $uy) * ($vx * $vx + $vy * $vy));
    $p = $ux * $vx + $uy * $vy;
    $sign = (($ux * $vy - $uy * $vx) < 0) ? -1 : 1;
    my $delta = $sign * acos( $p / $n );
    $delta = rad2deg($delta);

    if ($sweep == 0 && $delta > 0)
    {
        $delta -= 360;
    }
    elsif ($sweep == 1 && $delta < 0)
    {
        $delta += 360;
    }

    $delta %= 360;
    $theta %= 360;
    
    return ($cx, $cy, $rx, $ry, $theta, $delta, $phi);
}
     
#
#   Request input
#
print "Enter starting x,y coordinates > ";
$data = <>;
$data =~ s/,/ /g;
($x0, $y0) = split /\s+/, $data;

print "Enter ending x,y coordinates > ";
$data = <>;
$data =~ s/,/ /g;
($x, $y) = split /\s+/, $data;

print "Enter x and y radii > ";
$data = <>;
$data =~ s/,/ /g;
($rx, $ry) = split/\s+/, $data;

print "Enter rotation angle in degrees ";
$phi = <>;
chomp $phi;

print "Large arc flag (0=no, 1=yes) > ";
$large_arc = <>;
chomp $large_arc;

print "Sweep flag (0=negative, 1=positive) > ";
$sweep = <>;
chomp $sweep;

print "From ($x0,$y0) to ($x,$y) rotate $phi",
    " large arc=$large_arc sweep=$sweep\n";

($cx, $cy, $rx, $ry, $theta, $delta, $phi) =
    convert_from_svg( $x0, $y0, $rx, $ry, $phi, $large_arc, $sweep, 
       $x, $y );

print "Ellipse center = ($cx, $cy)\n";
print "Start angle = $theta\n";
print "Angle extent = $delta\n";


Bézier Curves

Arcs can be characterized as clean and functional, but one would rarely use the word “graceful” to describe them. If you want graceful, you need to use curves which are produced by graphing quadratic and cubic equations. Mathematicians have known about these curves for literally hundreds of years, but drawing them was always a computationally demanding task. This changed when Pierre Bézier, working for French car manufacturer Rénault and Paul de Casteljau, an engineer for Citroën, independently discovered a computationally convenient way to generate these curves.

If you have used graphics programs like Adobe Illustrator, you draw these Bézier curves by specifying two points and then moving a “handle” as shown in the following diagram. The end of this handle is called the control point, because it controls the shape of the curve. As you move the handle, the curve changes in a way that, to the uninitiated, is completely mystifying. Mike Woodburn, a graphic designer at Key Point Software, suggests Figure 6-6 as a way to visualize how the control point and the curve interact: imagine that the line is made of flexible metal. Inside the control point is a magnet; the closer a point is to the control point, the more strongly it is attracted.

Figure 6-6. How graphics programs draw Bézier curves

How graphics programs draw Bézier curves

Another way to visualize the role of the control point is based on the de Casteljau method of constructing the curves. We will use this approach in the following sections. For further details on the underlying mathematics, presented in a remarkably lucid fashion, see this web site: http://graphics.cs.ucdavis.edu/GraphicsNotes/Bezier-Curves/Bezier-Curves.html.

Quadratic Bézier Curves

The simplest of the Bézier curves is the quadratic curve. You specify a beginning point, an ending point, and a control point. Imagine two tent poles placed at the endpoints of the line. These tent poles meet at the control point. Stretched between the centers of the tent poles is a rubber band. The place where the curve bends is tied to the exact center of that rubber band. This situation is shown in Figure 6-7.

Figure 6-7. Visualizing a quadratic Bézier curve

Visualizing a quadratic Bézier curve

Programs like Adobe Illustrator show you only one of the “tent poles.” The next time you’re using such a program, mentally add in the second pole and the resulting curves will be far less mysterious.

That’s the concept; now for the practical matter of actually producing such a curve in SVG. You specify a quadratic curve in a <path> data with the Q or q command. The command is followed by two sets of coordinates that specify a control point and an endpoint. The uppercase command implies absolute coordinates; lowercase implies relative coordinates. The curve in Figure 6-7 was drawn from (30, 75) to (300, 120) with the control point at (240, 30), and was specified in SVG as follows:

<path d="M30 75 Q 240 30, 300 120" style="stroke: black; fill: none;"/>

You may specify several sets of coordinates after a quadratic curve command. This will generate a polybézier curve. Presume you want a <path> that draws a curve from (30, 100) to (100, 100) with a control point at (80, 30) and then continues with a curve to (200, 80) with a control point at (130, 65). Here is the SVG for this path, with control point coordinates in bold. The result is shown in the left half of Figure 6-8; the control points and lines are shown in the right half of the figure.

<path d="M30 100 Q 80 30, 100 100, 130 65, 200 80"/>

Figure 6-8. Quadratic polybézier curve

Quadratic polybézier curve

You are probably wondering, “What happened to `graceful?’ That curve is just lumpy.” This is an accurate assessment. Just because curves are connected doesn’t mean that they will look good together. That’s why SVG provides the smooth quadratic curve command, which is denoted by the letter T (or t if you want to use relative coordinates). The command is followed by the next endpoint of the curve; the control point is calculated automatically, as the specification says, by “reflection of the control point on the previous command relative to the current point.”

Note

For the mathematically inclined, the new control point x2, y2 is calculated from the curve’s starting point x, y and the previous control point x1, y1 with these formulas:

x2 = 2 * x - x1
y2 = 2 * y - y1

Here is a quadratic Bézier curve drawn from (30, 100) to (100, 100) with a control point at (80, 30) and then smoothly continued to (200, 80). The left half of Figure 6-9 shows the curve; the right half shows the control points. The reflected control point is shown with a dashed line. Gracefulness has returned!

<path d="M30 100 Q 80 30, 100 100 T 200 80"/>

Figure 6-9. Smooth quadratic polybézier curve

Smooth quadratic polybézier curve

Cubic Bézier Curves

A single quadratic Bézier curve has exactly one inflection point (the point where the curve changes direction). While these curves are more versatile than simple arcs, we can do even better by using cubic Bézier curves, which can have one or two inflection points.

The difference between the quadratic and cubic curves is that the cubic curve has two control points, one for each endpoint. The technique for generating the cubic curve is similar to that for generating the quadratic curve. You draw three lines that connect the endpoints and control points (a), and connect their midpoints. That produces two lines (b). You connect their midpoints, and that produces one line (c), whose midpoint determines one of the points on the final curve.[2] See Figure 6-10.

Figure 6-10. Visualizing a cubic Bézier curve

Visualizing a cubic Bézier curve

To specify such a cubic curve, use the C or c command. The command is followed by three sets of coordinates that specify the control point for the start point, the control point for the end point, and the end point. As with all the other path commands, an uppercase command implies absolute coordinates; lowercase implies relative coordinates. The curve in the preceding diagram was drawn from (20, 80) to (200, 120) with control points at (50, 20) and (150, 60). The SVG for the path was as follows:

<path d="M20 80 C 50 20, 150 60, 200 120"
    style="stroke: black; fill: none;"/>

There are many interesting curves you can draw, depending upon the relationship of the control points (see Figure 6-11). To make the graphic cleaner, we show only the lines from each endpoint to its control point.

Figure 6-11. Result of cubic Bézier control point combinations

Result of cubic Bézier control point combinations

As with quadratic curves, you can construct a cubic polybézier by specifying several sets of coordinates after a cubic curve command. The last point of the first curve becomes the first point of the next curve, and so on. Here is a <path> that draws a cubic curve from (30, 100) to (100, 100) with control points at (50, 50) and (70, 20); it is immediately followed by a curve that doubles back to (65, 100) with control points at (110, 130) and (45, 150). Here is the SVG for this path, with control point coordinates in bold. The result is shown in the left half of Figure 6-12; the control points and lines are shown in the right half of the diagram.

<path d="M30 100 C 50 50, 70 20, 100 100, 110, 130, 45, 150, 65, 100"/>

Figure 6-12. Cubic polybézier curve

Cubic polybézier curve

If you want to guarantee a smooth join between curves, you can use the S command (or s if you want to use relative coordinates). In a manner analogous to that of the T command for quadratic curves, the new curve will take the previous curve’s endpoint as its starting point, and the first control point will be the reflection of the previous ending control point. All you need to supply will be the control point for the next endpoint on the curve, followed by the next endpoint itself.

Here is a cubic Bézier curve drawn from (30, 100) to (100, 100) with control points at (50, 30) and (70, 50). It continues smoothly to (200, 80), using (150, 40) as its ending control point. The upper half shows the curve; the lower half shows the control points. The reflected control point is shown with a dashed line in Figure 6-13.

<path d="M30 100 C 50 30, 70 50, 100 100 S 150 40, 200 80"/>

Figure 6-13. Smooth cubic polybézier curve

Smooth cubic polybézier curve

Path Reference Summary

In Table 6-1, uppercase commands use absolute coordinates and lowercase commands use relative coordinates.

Table 6-1. Path commands

Command Arguments Effect
M
m
x y Move to given coordinates.
L
l
x y Draw a line to the given coordinates. You may supply multiple sets of coordinates to draw a polyline.
H
h
x Draw a horizontal line to the given x-coordinate.
V
v
y Draw a vertical line to the given x-coordinate.
A
a
rx ry x-axis-rotation large-arc sweep x y Draw an elliptical arc from the current point to (x, y). The points are on an ellipse with x-radius rx and y-radius ry. The ellipse is rotated x-axis-rotation degrees. If the arc is less than 180 degrees, large-arc is zero; if greater than 180 degrees, large-arc is one. If the arc is to be drawn in the positive direction, sweep is one; otherwise it is zero.
Q
q
x1 y1 x y Draw a quadratic Bézier curve from the current point to (x, y) using control point (x1, y1).
T
t
x y Draw a quadratic Bézier curve from the current point to (x, y). The control point will be the reflection of the previous Q command’s control point. If there is no previous curve, the current point will be used as the control point.
C
c
x1 y1 x2 y2 x y Draw a cubic Bézier curve from the current point to (x, y) using control point (x1, y1) as the control point for the beginning of the curve and (x2, y2) as the control point for the endpoint of the curve.
S
s
x2 y2 x y Draw a cubic Bézier curve from the current point to (x, y), using (x2, y2) as the control point for this new endpoint. The first control point will be the reflection of the previous C command’s ending control point. If there is no previous curve, the current point will be used as the first control point.

Paths and Filling

The information described in Chapter 3 in Section 3.5.1 is also applicable to paths, which can not only have intersecting lines, but can also have “holes” in them. Consider the paths in Example 6-4, both of which draw nested squares. In the first path, both squares are drawn clockwise; in the second path, the outer square is drawn clockwise and the inner square is drawn counterclockwise.

Example 6-4. Using different fill-rule values on paths

<!-- both paths clockwise -->
<path d="M 0 0, 60 0, 60 60, 0 60 Z
    M 15 15, 45 15, 45 45, 15 45Z"/>

<!-- outer path clockwise; inner path counterclockwise -->
<path d="M 0 0, 60 0, 60 60, 0 60 Z
    M 15 15, 15 45, 45 45, 45 15Z"/>

Figure 6-14 shows that there is a difference when you use a fill-rule of nonzero, which takes into account the direction of the lines when determining whether a point is inside or outside a path. Using a fill-rule of evenodd produces the same result for both paths; it uses total number of lines crossed and ignores their direction.

Figure 6-14. Result of using different fill-rule values

Result of using different     fill-rule values

The marker element

Let us presume the following path, which uses a line, an elliptical arc, and another line to draw the rounded corner in Figure 6-15:

<path d="M 10 20 100 20 A 20 30 0 0 1 120 50 L 120 110"
    style="fill: none; stroke: black;"/>

Figure 6-15. Lines and arc

Lines and arc

We’d like to mark the direction of the path by putting a circle at the beginning, a solid triangle at the end, and arrowheads at the other vertices, as shown in Figure 6-16. To achieve this effect, we will construct three <marker> elements and tell the <path> to reference them.

Figure 6-16. Lines and arc with markers

Lines and arc with markers

Let’s start with Example 6-5, which adds the circular marker. A marker is a “self-contained” graphic with its own private set of coordinates, so you have to specify its markerWidth and markerHeightheight in the starting <marker> tag. That is followed by the SVG elements required to draw the marker, and ends with a closing </marker>. A <marker> element does not display by itself, but we are putting it in a <defs> element because that’s where reusable elements belong.

Since we want the circle to be at the beginning of the path, we add a marker-start to the style in the <path>.[3] The value of this property is a URL reference to the <marker> element we’ve just created.

Example 6-5. First attempt at circular marker

<defs>
<marker id="mCircle" markerWidth="10" markerHeight="10">
    <circle cx="5" cy="5" r="4" style="fill: none; stroke: black;"/>
</marker>
</defs>

<path  d="M 10 20 100 20 A 20 30 0 0 1 120 50 L 120 110"
    style="marker-start: url(#mCircle);
    fill: none; stroke: black;"/>

The result in Figure 6-17 is not quite what we planned…

Figure 6-17. Misplaced circular marker

Misplaced circular marker

The reason the circle appears in the wrong place is that, by default, the start marker’s (0, 0) point is aligned with the beginning coordinate of the path. Example 6-6 adds refX and refY attributes that tell which coordinates (in the marker’s system) are to align with the beginning coordinate. Once these are added, the circular marker appears exactly where it is desired in Figure 6-18.

Example 6-6. Correctly placed circular marker

<marker id="mCircle" markerWidth="10" markerHeight="10" refX="5" refY="5">
    <circle cx="5" cy="5" r="4" style="fill: none; stroke: black;"/>
</marker>

Figure 6-18. Correctly placed circular marker

Correctly placed circular marker

Given this information, we can now write Example 6-7, which adds the triangular marker and references it as the marker-end for the path. Then we can add the arrowhead marker and reference it as the marker-mid. The marker-mid will be attached to every vertex except the beginning and end of the path. Notice that the refX and refY attributes have been set so the wide end of the arrowhead aligns with the intermediate vertices while the tip of the solid triangle aligns with the ending vertex. Figure 6-19 shows the result, which draws the first marker correctly but not the others.

Example 6-7. Attempt to use three markers

<defs>
    <marker id="mCircle" markerWidth="10" markerHeight="10"
        refX="5" refY="5">
        <circle cx="5" cy="5" r="4" style="fill: none; stroke: black;"/>
    </marker>

    <marker id="mArrow" markerWidth="6" markerHeight="10"
        refX="0" refY="4">
        <path d="M 0 0 4 4 0 8" style="fill: none; stroke: black;"/>
    </marker>

    <marker id="mTriangle" markerWidth="5" markerHeight="10"
        refX="5" refY="5">
        <path d="M 0 0 5 5 0 10 Z" style="fill: black;"/>
    </marker>
</defs>

<path d="M 10 20 100 20 A 20 30 0 0 1 120 50 L 120 110"
    style="marker-start: url(#mCircle);
        marker-mid: url(#mArrow);
        marker-end: url(#mTriangle);
        fill: none; stroke: black;"/>

Figure 6-19. Incorrectly oriented markers

Incorrectly oriented markers

To get the effect you want, you must explicitly set a marker’s orient attribute to auto. This makes it automatically rotate to match the direction of the path.[4] (You may also specify a number of degrees, in which case the marker will always be rotated by that amount.) Here in Example 6-8 are the markers, set to produce the effect shown in Figure 6-16. We don’t need to orient the circle; it looks the same no matter how it’s rotated.

Example 6-8. Correctly oriented markers

<defs>
    <marker id="mCircle" markerWidth="10" markerHeight="10"
        refX="5" refY="5">
        <circle cx="5" cy="5" r="4" style="fill: none; stroke: black;"/>
    </marker>

    <marker id="mArrow" markerWidth="6" markerHeight="10"
        refX="0" refY="4" orient="auto">
        <path d="M 0 0 4 4 0 8" style="fill: none; stroke: black;"/>
    </marker>

    <marker id="mTriangle" markerWidth="5" markerHeight="10"
        refX="5" refY="5" orient="auto">
        <path d="M 0 0 5 5 0 10 Z" style="fill: black;"/>
    </marker>
</defs>

<path d="M 10 20 100 20 A 20 30 0 0 1 120 50 L 120 110"
    style="marker-start: url(#mCircle);
        marker-mid: url(#mArrow);
        marker-end: url(#mTriangle);
        fill: none; stroke: black;"/>

Another useful attribute is the markerUnits attribute. If set to strokeWidth, the marker’s coordinate system is set so that one unit equals the stroke width. This makes your marker grow in proportion to the stroke width; it’s the default behavior and it’s usually what you want. If you set the attribute to userSpaceOnUse, the marker’s coordinates are presumed to be the same as the coordinate system of the object that references the marker. The marker will remain the same size irrespective of the stroke width.

Marker Miscellanea

If you want the same marker at the beginning, middle, and end of a path, you don’t need to specify all of the marker-start, marker-mid, and marker-end properties. Just use the marker property and have it reference the marker you want. Thus, if we wanted all the vertices to have a circular marker, as shown in Figure 6-20, we’d write the SVG in Example 6-9.

Example 6-9. Using a single marker for all vertices

<defs>
    <marker id="mCircle" markerWidth="10" markerHeight="10" 
        refX="5" refY="5">
        <circle cx="5" cy="5" r="4" style="fill: none; stroke: black;"/>
    </marker>
</defs>

<path d="M 10 20 100 20 A 20 30 0 0 1 120 50 L 120 110"
    style="marker: url(#mCircle); fill: none; stroke: black;"/>

Figure 6-20. Using a single marker for all vertices

Using a single marker for all vertices

It is also possible to set the viewBox and preserveAspectRatio attributes on a <marker> element to gain even more control over its display. These work exactly as described in Chapter 2, in Section 2.3and in Section 2.4.

You may reference a <marker> in a <polygon>, <polyline>, or <line> element as well as in a <path>.

The following thought may have occurred to you: “If a marker can have a path in it, can that path have a marker attached to it as well?” The answer is yes, it can, but the second marker must fit into the rectangle established by the first marker’s markerWidth and markerHeight. Please remember that just because a thing can be done does not mean that it should be done. If you need such an effect, you are probably better off to draw the secondary marker as a part of the primary marker rather than attempting to nest markers.

Notes

  1. You can also put multiple single coordinates after an horizontal lineto or vertical lineto, although it’s rather pointless to do so. H 25 35 45 is the same as H 45, and v 11 13 15 is the same as v 39.
  2. We’re dispensing with the tent analogy; it gets too unwieldy. Curves based on yurts and geodesic domes are left as exercises for the reader.
  3. Yes, markers are considered to be part of presentation rather than structure. This is one of those gray areas where you could argue either case.
  4. To be exact, the rotation is the average of the angle of the direction of the line going into the vertex and the direction of the line going out of the vertex.

 

 

W3SCHOOL的SVG教程 中 可以看出,SVG除了内建了一些基本图形矩形圆形椭圆线条多边形折线外,还支持使用<path>标签来自定义路径从而创建复杂的矢量图形 (Paths represent the outline of a shape which can be filled or stroked.)。本文将以附图及实例的方式来详细介绍SVG Path的语法结构,并在文末简要说明如何在DEGRAFA中使用支持SVG的PATH类。

 

PATH十种指令:

括号内为相应参数,详细解释见后文。


M = moveto(M X,Y)
L = lineto(L X,Y)
H = horizontal lineto(H X)
V = vertical lineto(V Y)
C = curveto(C X1,Y1,X2,Y2,ENDX,ENDY)
S = smooth curveto(S X2,Y2,ENDX,ENDY)
Q = quadratic Belzier curve(Q X,Y,ENDX,ENDY)
T = smooth quadratic Belzier curveto(T ENDX,ENDY)
A = elliptical Arc(A RX,RY,XROTATION,FLAG1,FLAG2,X,Y)
Z = closepath()
注释:
坐标轴为以(0,0)为中心,X轴水平向右,Y轴水平向下。
所有指令大小写均可。大写绝对定位,参照全局坐标系;小写相对定位,参照父容器坐标系
对于S,T指令,其X1,Y1为前一条曲线的X2,Y2的反射
指令和数据间的空格可以省略
同一指令出现多次可以只用一个

L H V指令
 M起点X,起点Y,L(直线)终点X,终点Y,H(水平线)终点X,V(垂直线)终点Y
如M10,20,L80,50,M10,20,V50,M10,20,H90

C指令——三次贝塞曲线
 C第一控制点X,第一控制点Y 第二控制点X,第二控制点Y曲线结束点X,曲线结束点Y

S指令
 S第二控制点X,第二控制点Y 结束点X,结束点Y

Q指令——二次贝塞曲线
Q控制点X,控制点Y 曲线结束点X,曲线结束点Y
如M0,25,Q12.5,37.5,25,25,M25,25,Q37.5,12.5,50,25

T指令——映射
T映射前面路径后的终点X,映射前面路径后的终点Y

A指令
Elliptical Arc,允许不闭合。可以想像成是椭圆的某一段,共七个参数。
RX,RY指所在椭圆的半轴大小
XROTATION指椭圆的X轴与水平方向顺时针方向夹角,可以想像成一个水平的椭圆绕中心点顺时针旋转XROTATION的角度。
FLAG1只有两个值,1表示大角度弧线,0为小角度弧线。
FLAG2只有两个值,确定从起点至终点的方向,1为顺时针,0为逆时针
X,Y为终点坐标
如M0,25,A12.5,12.5,0,1,1,0,25.01Z表示一个圆心在(12.5,25),半径为12.5的圆。其中起点和终点几乎重合,用Z指令将它们闭合,注意终点不能填(0,25),那样A指令是无法被解析的。

 

由以上介绍可以看出,手工绘制SVG路径是相当复杂的。对于简单的SVG图形,一般只使用M,L,Q,A,Z五种指令完成。更复杂的图形则必须要靠软件来帮助完成,比如ADOBE ILLUSTRATOR。

 

两个完整的例子:

把代码拷入记事本,保存为”**.svg”即可。如果无法运行,可能需要SVGVIEWER,详情参照SVG中国相关内容或者GOOGLE下载一个

三角形:
<?xml version=”1.0″ standalone=”no”?>
<!DOCTYPE svg PUBLIC “-//W3C//DTD SVG 1.1//EN”
“http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd”>

<svg width=”100%” height=”100%” version=”1.1″
xmlns=”http://www.w3.org/2000/svg”>

<path d=”M250 150 L150 350 L350 350 Z” />

</svg>

螺旋:
<?xml version=”1.0″ standalone=”no”?>
<!DOCTYPE svg PUBLIC “-//W3C//DTD SVG 1.1//EN”
“http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd”>

<svg width=”100%” height=”100%” version=”1.1″
xmlns=”http://www.w3.org/2000/svg”>

<path d=”M153 334
C153 334 151 334 151 334
C151 339 153 344 156 344
C164 344 171 339 171 334
C171 322 164 314 156 314
C142 314 131 322 131 334
C131 350 142 364 156 364
C175 364 191 350 191 334
C191 311 175 294 156 294
C131 294 111 311 111 334
C111 361 131 384 156 384
C186 384 211 361 211 334
C211 300 186 274 156 274″
style=”fill:white;stroke:red;stroke-width:2″/>

</svg>

参考链接: http://www.w3.org/TR/SVG/paths.html

FLEX中使用DEGRAFA的PATH类指定DATA
<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”horizontal” xmlns:degrafa=”http://www.degrafa.com/2007″>
<degrafa:Surface>
<degrafa:GeometryGroup scaleX=”2″ scaleY=”2″>
<degrafa:Path data=”M0,25,Q12.5,37.5,25,25,M25,25,Q37.5,12.5,50,25″ stroke=”{blackstroke}”/>
</degrafa:GeometryGroup>
<degrafa:strokes>
<degrafa:SolidStroke id=”blackstroke” color=”#000000″ weight=”1″>
</degrafa:SolidStroke>
</degrafa:strokes>
</degrafa:Surface>
</mx:Application>
如上,将手工绘制或者软件帮助完成的PATH字符串填入Path data=”***”即可查看效果。

一个比较著名的效果图就是SVG TIGER

SVG TIGER

 

FLEX中使用BitmapFill的source属性指定SVG类文件

<?xml version=”1.0″ encoding=”utf-8″?>
<mx:Application xmlns:mx=” http://www.adobe.com/2006/mxml ” layout=”absolute”
backgroundGradientColors=”[#333333, #222222]”
xmlns:degrafa=”com.degrafa.*”
xmlns:paint=”com.degrafa.paint.*”
xmlns:geometry=”com.degrafa.geometry.*”>
<degrafa:Surface verticalCenter=”0″ horizontalCenter=”0″>
<degrafa:fills>
<paint:BitmapFill id=”bitmapFill” source=”{svgTest}” smooth=”true”/>
</degrafa:fills>
<degrafa:GeometryGroup scaleX=”1″ scaleY=”1″>
<geometry:Circle fill=”{bitmapFill}” radius=”450″/>
</degrafa:GeometryGroup>
</degrafa:Surface>
<mx:Script>
<![CDATA[
[Embed(source=”circle.svg”)]
[Bindable]
public var svgTest:Class;
]]>
</mx:Script>
</mx:Application>
circle.svg:

<?xml version=”1.0″?>
<!DOCTYPE svg PUBLIC “-//W3C//DTD SVG 1.0//EN”
” http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd “>
<svg width=”200″ height=”200″ xmlns=” http://www.w3.org/2000/svg “>
<desc>All SVG documents should have a description</desc>
<defs>
<!– Items can be defined for later use –>
</defs>
<g>
<circle cx=”15″ cy=”15″ r=”15” fill=”red”/>
</g>
</svg>

 

 

http://blog.csdn.net/seacean2000/article/details/8490341

 

一:简介

       路径呈现一个图形的外边沿,可以被填充,可以作为笔画,可以作为裁剪路径,或者任意前面三种的组合。
       一个路径可以使用一个当前点的概念来描述。类似于在纸上画画,这个当前点可以被认为是笔的位置。笔的位置可以被改变,并且一个图形的外边沿的轨迹将会通过拖动笔画出直线或者曲线形成。
        路径会呈现一个物体的几何外边沿, 它是参照moveto,lineto,curveto,arc,closepath等元素。复合路径可以在物体上画出圆圈。
         这一章节主要讲述SVG路径的语法,表现形式和DOM接口。SVG路径的各种实现接口可以参考:‘path’element implementation notesElliptical arc implementation notes
         一个路径在SVG中是用”path”元素产生的。
 二:”path”元素
DOM接口:SVGPathElement
属性定义:
d=”path data”
       一个图形的外边沿定义。可以设置动画的。路径数据动画只有在动画规范当中每一个路径数据规范有都有准确相同的”d”属性值作为路径数据指令才有可能。如果一个动画已经被指示,但是路径数据指令不一致,那么动画指令就会发生错误。动画引擎将每个参数单独的插入到基于属性值的给定动画元素的每个路径数据动画。标记和布尔值将作为分数插入到0到1之间,并且任意的非零值将会被看做1或者true。
pathLength=”<number>”
       以用户的单位长度来估算整个路径的长度。这个值可以常来被用作校正用户代理自己的路径长度。用户代理将缩放所有的路径长度的估算通过这个原”pathLength”与用户代理自己所估算出的真实路径长度。”pathLength”可能影响路径上的文本,移动动画和边界操作等计算结果 。出现负值是错误的。可以设置动画的。
三:路径数据
1.路径数据概论
      一个路径通过引入含有moveto,line,curve,arc,closepath说明的d属性的”path”元素导入而被定义的 。
下面是一个指定三角形路径的例子:
  1. <?xml version=“1.0” standalone=“no”?>
  2. <!DOCTYPE svg PUBLIC “-//W3C//DTD SVG 1.1//EN”
  3.   “http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd”>
  4. <svg width=“4cm” height=“4cm” viewBox=“0 0 400 400”
  5.      xmlns=“http://www.w3.org/2000/svg” version=“1.1”>
  6.   <title>Example triangle01- simple example of a ‘path’</title>
  7.   <desc>A path that draws a triangle</desc>
  8.   <rect x=“1” y=“1” width=“398” height=“398”
  9.         fill=“none” stroke=“blue” />
  10.   <path d=“M 100 100 L 300 100 L 200 300 z”
  11.         fill=“red” stroke=“blue” stroke-width=“3” />
  1. <span style=“font-family:微软雅黑”></svg></span><span style=“font-family:微软雅黑”>  </span>
       路径数据可以包含换行符,因此可以拆分成多行提高可读性。由于特定工具的行长度限制,推荐SVG创建者将长路径数据分隔成每行不超过255个字符的多行数据。同时注意换行符在路径数据中仅能在特定的位置使用。自从许多的SVG文件中路径数据占主导地位之后,为了满足最小的文件大小和有效地下载,路径数据是很简洁的。许多SVG尝试压缩路径数据的大小的方法如下:
a:所有的说明可以用一个字符来解释(例如:moveto可以用M代替)
b:多余的空白处和分隔要尽可能的压缩(例如“M 100 100 L 200 200”用“M100 100L200 200”代替)
c:当在一行当中相同的指令连续出现多次的时候,可以进行合并(例如”M 100 100 L 200 200 L300 400″可以用”M 100 100 L 200 200 300 400″代替)
d:所有命令的相对版本也是有效地(大写意味着绝对坐标,小写意味着相对坐标)
e:连续的横向或者竖向的路径可以进行最优化合并
f:控制点一致的连续弧线可以进行最优化合并
       路径数据语法是一种前缀符号。唯一被允许使用的分界符号是”.”,其他的分界符号被禁止使用。(例如”13,000.56″是无效的数据,”13000.56″是正确的)
       对于相对版本的命令,从命令开始的对当前点来说,所有的坐标值都是相对的。
在下面的表格当中,下面的记号表示:
():参数组
+:要求1个或者多个给定的参数或参数组
接下来将列出所有的指令
2.”moveto”指令
     这个”moveto”指令建立了一个新的当前点。它的作用就像是把笔提起,移动到一个新的位置。一个路径片段必须以”moveto”开始。随后的”moveto”指令将会作为一个子路径的起点。
命令
名称
参数
描述
M(absolute)
m (relative)
moveto
(x y)+
从给定的(x,y)坐标开启一个新的子路径或路径。M表示后面跟随的是绝对坐标值。
m表示后面跟随的是一个相对坐标值。如果”moveto”指令后面跟随着多个坐标值,那么
这多个坐标值之间会被当做用线段连接。因此如果moveto是相对的,那么lineto也将会
是相对的,反之也成立。如果一个相对的moveto出现在path的第一个位置,那么它会
被认为是一个绝对的坐标。在这种情况下,子序列的坐标将会被当做相对的坐标,即便
它在初始化的时候是绝对坐标。
3.”closepath”指令
一个闭合指令会结束当前的子路径,并且会自动添加结束点到起始点之间的线段。如果一个闭合路径后面紧跟着一个moveto指令,那么moveto将标识起始点作为下一个路径的起始点。如果闭合路径后面立即跟着其他的指令,那么其他子路径将以起始点作为子路径的起始点。
当一个路径通过closepath来关闭的,它将与通过lineto命令手动的关闭路径的表现是不同的。在闭合路径时使用closepath,那么最后的那个路径片段会使用当前值的stroke-linejoin的方式连接到起始点。如果是手动的使用lineto指令,那么最后的片段和第一个片段之间不会连接,而是使用当前值的stroke-linecap指令进行两边的遮盖。指令最后,新的路径关键点被设置成为当前路径的起始点。
指令
名称
参数
描述
Z or
z
closepath
无参数
通过从当前点到当前路径的起始点画一条线段来关闭当前的路径。Z和z指令都没有参数,
但是它们有相同的效果。
4.lineto指令
下面不同的lineto指令都是从当前点画直线到新的点:
指令
名称
参数
描述
L(absolute)
l (relative)
lineto
(x y)+
画一条从当前点到给定的(x,y)坐标,这个给定的坐标将变为新的当前点。L表示后面
跟随的参数将是绝对坐标值;l表示后面跟随的参数将是相对坐标值。可以通过指定一系
列的坐标来描绘折线。在命令执行后,新的当前点将会被设置成被提供坐标序列的最后
一个坐标。
H(absolute)
h (relative)
horizontal lineto
x+
从(cpx,cpy)画一个水平线到(x,cpy)。H表示后面跟随的参数是绝对的坐标,h表示
后面跟随的参数是相对坐标。可以为其提供多个x值作为参数。在指令执行结束后,
最新的当前点将是参数提供的最后值(x,cpy)
V(absolute)
v (relative)
vertical lineto
y+
从当前点(cpx,cpy)到(cpx,y)画一条竖直线段。V表示后面的参数是绝对坐标
值,v表示后面跟着的参数是相对坐标值。可以供多个y值作为参数使用。在指令的最
后,根据最后的参数y值最新的当前点的坐标值是(cpx,y).
5.曲线指令
这里有三组画曲线的指令:
Cubic Bézier commands (C, c, S and s):一个含有一个起始点,一个结束点,两个控制点的立方体的贝塞尔曲线片段。
Quadratic Bézier commands (Q, q, T and t):一个含有一个起始点,一个结束点,一个控制点的二次的贝塞尔曲线片段。
Elliptical arc commands (A and a):一个椭圆的弧度曲线片段。
6.立方体的贝塞尔曲线指令
立方体的贝塞尔曲线指令如下所示:
指令
名称
参数
描述
C(absolute)
c(relative)
curveto
(x1 y1 x2 y2 x y)+
在曲线开始的时候,用(x1,y1)作为当前点(x,y)的控制点,
在曲线结束的时候,用(x2,y2)作为当前点的控制点,
画一段立方体的贝塞尔曲线。C表示后面跟随的参数是绝对坐标值;
c表示后面跟随的参数是相对坐标值。可以为贝塞尔函数提供多个参数
值。在指令执行完毕后,最后的当前点将变为在贝塞尔函数中只用的
最后的(x,y)坐标值
S(absolute)
s(relative)
shorthand/smooth curveto
(x2 y2 x y)+
从当前点(x,y)画一个立方体的贝塞尔曲线。相对于当前点,
第一个控制点被认为是前面命令的第二个控制点的反射。(如果
前面没有指令或者指令不是C, c, S 或者s,那么就认定当前点和
第一个控制点是一致的。)(x2,y2)是第二个控制点,控制
着曲线结束时的变化。S表示后面跟随的参数是绝对的坐标值。
s表示后面跟随的参数是相对的坐标值。多个值可以作为
贝塞尔函数的参数。在执行执行完后,最新的当前点是在贝塞尔函数中
使用的最后的(x,y)坐标值。
立方体的贝塞尔曲线示例:用一个简单的曲线来展示一些简单使用立方体的贝塞尔曲线指令。这个例子使用内置的CSS样式来设置样式属性。
注意S指令的控制点是通过先前C指令的控制点的反射计算出来的作为S指令的起始参数。
  1. <?xml version=“1.0” standalone=“no”?>
  2. <!DOCTYPE svg PUBLIC “-//W3C//DTD SVG 1.1//EN”
  3.   “http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd”>
  4. <svg width=“5cm” height=“4cm” viewBox=“0 0 500 400”
  5.      xmlns=“http://www.w3.org/2000/svg” version=“1.1”>
  6.   <title>Example cubic01- cubic Bézier commands in path data</title>
  7.   <desc>Picture showing a simple example of path data
  8.         using both a “C” and an “S” command,
  9.         along with annotations showing the control points
  10.         and end points</desc>
  11.   <style type=“text/css”><![CDATA[
  12.     .Border { fill:none; stroke:blue; stroke-width:1 }
  13.     .Connect { fill:none; stroke:#888888; stroke-width:2 }
  14.     .SamplePath { fill:none; stroke:red; stroke-width:5 }
  15.     .EndPoint { fill:none; stroke:#888888; stroke-width:2 }
  16.     .CtlPoint { fill:#888888; stroke:none }
  17.     .AutoCtlPoint { fill:none; stroke:blue; stroke-width:4 }
  18.     .Label { font-size:22; font-family:Verdana }
  19.   ]]></style>
  20.   <rect class=“Border” x=“1” y=“1” width=“498” height=“398” />
  21.   <polyline class=“Connect” points=“100,200 100,100” />
  22.   <polyline class=“Connect” points=“250,100 250,200” />
  23.   <polyline class=“Connect” points=“250,200 250,300” />
  24.   <polyline class=“Connect” points=“400,300 400,200” />
  25.   <path class=“SamplePath” d=”M100,200 C100,100 250,100 250,200
  26.                                        S400,300 400,200″ />
  27.   <circle class=“EndPoint” cx=“100” cy=“200” r=“10” />
  28.   <circle class=“EndPoint” cx=“250” cy=“200” r=“10” />
  29.   <circle class=“EndPoint” cx=“400” cy=“200” r=“10” />
  30.   <circle class=“CtlPoint” cx=“100” cy=“100” r=“10” />
  31.   <circle class=“CtlPoint” cx=“250” cy=“100” r=“10” />
  32.   <circle class=“CtlPoint” cx=“400” cy=“300” r=“10” />
  33.   <circle class=“AutoCtlPoint” cx=“250” cy=“300” r=“9” />
  34.   <text class=“Label” x=“25” y=“70”>M100,200 C100,100 250,100 250,200</text>
  35.   <text class=“Label” x=“325” y=“350”
  36.         style=“text-anchor:middle”>S400,300 400,200</text>
  37. </svg>
  1. 效果图像:
  1. <img src=“http://note.youdao.com/yws/public/resource/641f806bd2cfdb37f4c963fd11d663ad/253EAFC830E9478E80D0AE967AEBB356” alt=“”>
  1. <a href=“http://www.w3.org/TR/SVG11/images/paths/cubic01.svg”>用SVG查看效果图 (只能使用可以查看SVG的浏览器才可以正常查看)</a>
从效果图中可以看出,S指令的第一个控制点是前面C指令第二个控制点关于C指令当前点的反射点,这个说明S是C的简化。
下面的图像展示了贝塞尔曲线随着控制点变化发生的情况。前面五个例子图解说明了一个单独的立方体的贝塞尔曲线片段。最后一个例子展示了C指令后面S指令的情形。
  1. <img src=“http://note.youdao.com/yws/public/resource/641f806bd2cfdb37f4c963fd11d663ad/38F02235B72341DDA553656003C3F0ED” alt=“”>
  1. 7.二次贝塞尔曲线指令
  1. <span style=“font-family:’Microsoft Yahei'”><span style=“white-space:normal”>二次贝塞尔曲线指令如下所示:</span>
  2. </span>
  1. <table class=“ynote_table” border=“1” cellpadding=“2” cellspacing=“0” width=“100%”><tbody><tr><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>指令</span></div></td><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>名称</span></div></td><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>参数</span></div></td><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>描述</span></div></td></tr><tr><td valign=“top”><div><div><span style=“font-family:’Microsoft Yahei'”>Q
  2.  (absolute)</span></div><div><span style=“font-family:’Microsoft Yahei'”>q (relative)</span></div></div></td><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>quadratic Bézier curveto</span></div></td><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>(x1
  3.  y1 x y)+</span></div></td><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>从当前点(x,y)开始,以(x1,y1)为控制点,画出一个二次贝塞尔曲线。</span></div><div><span style=“font-family:’Microsoft Yahei’; font-size:14px”>Q表</span><span style=“font-family:’Microsoft Yahei'”>示后面跟随的参数是绝对坐标值,q表示后面跟随的参数是相对坐标值。</span></div><div><span style=“font-family:’Microsoft Yahei'”>可以为贝塞尔函数指定</span><span style=“font-family:’Microsoft Yahei’; font-size:14px”>多个参数值。在指令执行结束后,新的当前点是贝塞尔曲线</span><span style=“font-family:’Microsoft Yahei’; font-size:14px”>调用参数中最后一个坐标值</span><span style=“font-family:’Microsoft Yahei’; font-size:14px”>(x,y)。</span></div></td></tr><tr><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”></span><div>T
  4.  (absolute)</div><div>t (relative)</div></div></td><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>Shorthand/smooth quadratic Bézier curveto</span></div></td><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>(x y)+</span></div></td><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>画一个从当前点到(x,y)的二次贝塞尔曲线。控制点被认为是上一个</span></div><div><span style=“font-family:’Microsoft Yahei'”>指令的控制点以当前点为中心的对称点。(如果前面没有指令或者前面</span></div><div><span style=“font-family:’Microsoft Yahei'”>的指令不是Q,
  5.  q, T或者t,那么</span><span style=“font-family:’Microsoft Yahei'”>控制点被认为是当前点</span><span style=“font-family:’Microsoft Yahei’; font-size:14px”>)。T表示后面跟随</span></div><div><span style=“font-family:’Microsoft Yahei’; font-size:14px”>的参数是绝对坐标值;t表示后面跟随的参数是相对坐标值。在指令执行结束后,</span></div><div><span style=“font-family:’Microsoft Yahei’; font-size:14px”>新的当前点被认定为最后传递给贝塞尔函数的坐标值(x,y)。</span></div></td></tr></tbody></table>
  1. <span style=“font-family:微软雅黑; white-space:normal”>下面的例子展示了如何简单的使用二次贝塞尔曲线。注意T指令的控制点来源于前面Q指令控制点以T指令当前点的对称点。</span>
  1. <pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”><?xml version=“1.0” standalone=“no”?></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”><!DOCTYPE svg PUBLIC “-//W3C//DTD SVG 1.1//EN” </span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>  “http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd”></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”><svg width=“12cm” height=“6cm” viewBox=“0 0 1200 600”</span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>     xmlns=“http://www.w3.org/2000/svg” version=“1.1”></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>  <title>Example quad01 – quadratic Bézier commands in path data</title></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>  <desc>Picture showing a “Q” a “T” command,</span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>        along with annotations showing the control points</span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>        and end points</desc></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>  <rect x=“1” y=“1” width=“1198” height=“598”</span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>        fill=“none” stroke=“blue” stroke-width=“1” /></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>
  2. </span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>  <path d=“M200,300 Q400,50 600,300 T1000,300”</span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>        fill=“none” stroke=“red” stroke-width=“5”  /></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>  <!– End points –></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>  <g fill=“black” ></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>    <circle cx=“200” cy=“300” r=“10”/></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>    <circle cx=“600” cy=“300” r=“10”/></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>    <circle cx=“1000” cy=“300” r=“10”/></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>  </g></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>  <!– Control points and lines from end points to control points –></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>  <g fill=“#888888” ></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>    <circle cx=“400” cy=“50” r=“10”/></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>    <circle cx=“800” cy=“550” r=“10”/></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>  </g></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>  <path d=”M200,300 L400,50 L600,300 </span></span></pre><pre class=”xml” name=”code”><span style=”font-family:微软雅黑”><span style=“white-space:normal”>           L800,550 L1000,300″</span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>        fill=“none” stroke=“#888888” stroke-width=“2” /></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”></svg></span></span></pre><pre class=“xml” name=“code”><span style=“font-family:微软雅黑”><span style=“white-space:normal”>生成图像结果:</span></span></pre><pre class=“xml” name=“code”><img src=“http://note.youdao.com/yws/public/resource/641f806bd2cfdb37f4c963fd11d663ad/C463BB3E23A140BF9A74B9949255E645” alt=“”></pre><pre class=“xml” name=“code”><span style=“font-family:’Microsoft Yahei'”>8椭圆弧曲线指令</span></pre><pre class=“xml” name=“code”><span style=“font-family:’Microsoft Yahei'”>椭圆弧曲线指令如下所示:</span></pre><pre class=“xml” name=“code”><table class=“ynote_table” border=“1” cellpadding=“2” cellspacing=“0” width=“100%”><tbody><tr><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>指令</span></div></td><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>名称</span></div></td><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>参数</span></div></td><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>描述</span></div></td></tr><tr><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”></span><div>A
  3.  (absolute)</div><div>a (relative)</div></div></td><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>elliptical arc</span></div></td><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>(rx ry x-axis-rotation large-arc-flag sweep-flag
  4.  x y)+</span></div></td><td valign=“top”><div><span style=“font-family:’Microsoft Yahei'”>用来从当前点(x,y)来画出一个椭圆弧曲线。曲线的形状和方向通过椭圆半径(rx,ry)</span></div><div><span style=“font-family:’Microsoft Yahei'”>和一个沿X轴旋转度来指明椭圆作为一个整体在当前坐标系下旋转的情形。椭圆的中心</span></div><div><span style=“font-family:’Microsoft Yahei'”>(cx,cy)是通过满足其他参数的约束自动计算出来的。</span><span style=“text-align:left”><span style=“font-family:’Microsoft Yahei'”>large-arc-flag和sweep-flag</span></span><span style=“font-family:’Microsoft Yahei’; font-size:14px; text-align:left”>决定了计算和帮助要画的弧度大小。</span></div></td></tr></tbody></table></pre>
  1. 参数具体详解<span style=“font-family:’Microsoft Yahei’; font-size:14px”>rx ry:一个椭圆的x轴半径和y轴半径</span>
  1. <span style=“font-family:’Microsoft Yahei’; font-size:14px”>                </span><span style=“font-family:’Microsoft Yahei’; font-size:14px”>x-axis-rotation:椭圆的X轴与当前坐标系X轴之间的角度</span>
  1.  <span style=“font-family:’Microsoft Yahei’; font-size:14px”>large-arc-flag :弧线选择是大弧度的曲线还是小弧度的曲线,1标识大的弧线,0标识小的弧线</span>
  1. <span style=“font-family:’Microsoft Yahei’; font-size:14px”>              sweep-flag:从当前点到(x,y)的弧线是顺时针的还是逆时针的,逆时针为0,顺时针为1</span>
  1. <span style=“font-family:微软雅黑”>                  </span><span style=“font-family:’Microsoft Yahei’; font-size:14px”>x y:指令的目标点</span><span style=“font-family:微软雅黑”>  </span>
  1. 下面的例子展示了在一段路径中使用指令的情况:
  1. <?xml version=“1.0” standalone=“no”?>
  2. <!DOCTYPE svg PUBLIC “-//W3C//DTD SVG 1.1//EN”
  3.   “http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd”>
  4. <svg width=“12cm” height=“5.25cm” viewBox=“0 0 1200 400”
  5.      xmlns=“http://www.w3.org/2000/svg” version=“1.1”>
  6.   <title>Example arcs01 – arc commands in path data</title>
  7.   <desc>Picture of a pie chart with two pie wedges and
  8.         a picture of a line with arc blips</desc>
  9.   <rect x=“1” y=“1” width=“1198” height=“398”
  10.         fill=“none” stroke=“blue” stroke-width=“1” />
  11.   <path d=“M300,200 h-150 a150,150 0 1,0 150,-150 z”
  12.         fill=“red” stroke=“blue” stroke-width=“5” />
  13.   <path d=“M275,175 v-150 a150,150 0 0,0 -150,150 z”
  14.         fill=“yellow” stroke=“blue” stroke-width=“5” />
  15.   <path d=”M600,350 l 50,-25
  16.            a25,25 -30 0,1 50,-25 l 50,-25
  17.            a25,50 -30 0,1 50,-25 l 50,-25
  18.            a25,75 -30 0,1 50,-25 l 50,-25
  19.            a25,100 -30 0,1 50,-25 l 50,-25″
  20.         fill=“none” stroke=“red” stroke-width=“5”  />
  21. </svg>
  1. <span style=“font-family:’Microsoft Yahei'”>SVG图像的结果如下所示:</span>
  1. <img src=“http://note.youdao.com/yws/public/resource/641f806bd2cfdb37f4c963fd11d663ad/706FAF2F8DDB43619E83857561A23EDC” alt=“”>
  1. <span style=“font-family:’Microsoft Yahei'”>椭圆弧曲线需要满足下面的约束条件之后才可以画出一个椭圆的片段:</span>
  1. <span style=“font-family:’Microsoft Yahei'”>弧线从当前点开始</span>
  1. <span style=“font-family:’Microsoft Yahei'”>弧线以(x,y</span><span style=“font-family:’Microsoft Yahei'”>)为结束点</span>
  1. <span style=“font-family:’Microsoft Yahei'”>椭圆有两个半径,(rx,ry)</span>
  1. <span style=“font-family:’Microsoft Yahei'”>椭圆的x轴相对于当前坐标系的x轴通过X轴旋转度旋转</span>
  1. <span style=“font-family:’Microsoft Yahei'”>    在大多数情况下有4个不同的弧曲线会满足约束条件。large-arc-flag和 sweep-flag决定了这四个当中哪一个被画出,如下所示:</span>
  1. <span style=“font-family:’Microsoft Yahei'”>         在这四段弧线当中,两段将比其余的两段大180度或者等于180度。剩余的两段比前面的两段小180度或者等于180度。如果large-arc-flag是1,表示两个比较大的弧线被选择出来;否则如果是0,那么较小的弧线被选择出来。</span>
  1. <span style=“font-family:’Microsoft Yahei'”>         如果sweep-flag是1,那么弧线将会以一个合适的通过(椭圆公式x=cx+rx*cos(theta)和y=cy+ry*sin(theta))评测出一个当前点起始,逐步增长到(x,y)结束的角度描绘出来。值为0会导致弧线会在负角度方向被画出。(theta从当前点开始并增长到(x,y)结束弧线。)</span>
  1. <span style=“font-family:’Microsoft Yahei'”>    下面是large-arc-flag和sweep-flag的组合图解,并展示了基于四种不同结果的图形。对每个情况,可以使用下面的指令:</span>
  1. <span style=“font-family:’Microsoft Yahei'”><path d=“M 125,75 a100,50 0 ?,? 100,50” style=“fill:none; stroke:red; stroke-width:6”/></span>
  1. 当里面的”?,?”被替换为”0,0″ “0,1” “1,0” “1,1”时会形成四种可能的结果:
在这些圆弧当中,”0,0″与”1,1″会是在一个椭圆中;”0,1″与”1,0″在一个椭圆中。
具体的实现和注意事项可以参考:Elliptical arc implementation notes
9路径数据的语法
下面的记号是用在路径数据语法的巴科斯诺尔范式形式:
*:0个或者多个
+:一个或者多个
?:0个或者一个
():分组
|:可选择项的分隔
双引号围绕着文字值
下面是SVG路径的BNF范式:
svg-path:
    wsp* moveto-drawto-command-groups? wsp*
moveto-drawto-command-groups:
    moveto-drawto-command-group
    | moveto-drawto-command-group wsp* moveto-drawto-command-groups
moveto-drawto-command-group:
    moveto wsp* drawto-commands?
drawto-commands:
    drawto-command
    | drawto-command wsp* drawto-commands
drawto-command:
    closepath
    | lineto
    | horizontal-lineto
    | vertical-lineto
    | curveto
    | smooth-curveto
    | quadratic-bezier-curveto
    | smooth-quadratic-bezier-curveto
    | elliptical-arc
moveto:
    ( “M” | “m” ) wsp* moveto-argument-sequence
moveto-argument-sequence:
    coordinate-pair
    | coordinate-pair comma-wsp? lineto-argument-sequence
closepath:
    (“Z” | “z”)
lineto:
    ( “L” | “l” ) wsp* lineto-argument-sequence
lineto-argument-sequence:
    coordinate-pair
    | coordinate-pair comma-wsp? lineto-argument-sequence
horizontal-lineto:
    ( “H” | “h” ) wsp* horizontal-lineto-argument-sequence
horizontal-lineto-argument-sequence:
    coordinate
    | coordinate comma-wsp? horizontal-lineto-argument-sequence
vertical-lineto:
    ( “V” | “v” ) wsp* vertical-lineto-argument-sequence
vertical-lineto-argument-sequence:
    coordinate
    | coordinate comma-wsp? vertical-lineto-argument-sequence
curveto:
    ( “C” | “c” ) wsp* curveto-argument-sequence
curveto-argument-sequence:
    curveto-argument
    | curveto-argument comma-wsp? curveto-argument-sequence
curveto-argument:
    coordinate-pair comma-wsp? coordinate-pair comma-wsp? coordinate-pair
smooth-curveto:
    ( “S” | “s” ) wsp* smooth-curveto-argument-sequence
smooth-curveto-argument-sequence:
    smooth-curveto-argument
    | smooth-curveto-argument comma-wsp? smooth-curveto-argument-sequence
smooth-curveto-argument:
    coordinate-pair comma-wsp? coordinate-pair
quadratic-bezier-curveto:
    ( “Q” | “q” ) wsp* quadratic-bezier-curveto-argument-sequence
quadratic-bezier-curveto-argument-sequence:
    quadratic-bezier-curveto-argument
    | quadratic-bezier-curveto-argument comma-wsp?
        quadratic-bezier-curveto-argument-sequence
quadratic-bezier-curveto-argument:
    coordinate-pair comma-wsp? coordinate-pair
smooth-quadratic-bezier-curveto:
    ( “T” | “t” ) wsp* smooth-quadratic-bezier-curveto-argument-sequence
smooth-quadratic-bezier-curveto-argument-sequence:
    coordinate-pair
    | coordinate-pair comma-wsp? smooth-quadratic-bezier-curveto-argument-sequence
elliptical-arc:
    ( “A” | “a” ) wsp* elliptical-arc-argument-sequence
elliptical-arc-argument-sequence:
    elliptical-arc-argument
    | elliptical-arc-argument comma-wsp? elliptical-arc-argument-sequence
elliptical-arc-argument:
    nonnegative-number comma-wsp? nonnegative-number comma-wsp?
        number comma-wsp flag comma-wsp? flag comma-wsp? coordinate-pair
coordinate-pair:
    coordinate comma-wsp? coordinate
coordinate:
    number
nonnegative-number:
    integer-constant
    | floating-point-constant
number:
    sign? integer-constant
    | sign? floating-point-constant
flag:
    “0” | “1”
comma-wsp:
    (wsp+ comma? wsp*) | (comma wsp*)
comma:
    “,”
integer-constant:
    digit-sequence
floating-point-constant:
    fractional-constant exponent?
    | digit-sequence exponent
fractional-constant:
    digit-sequence? “.” digit-sequence
    | digit-sequence “.”
exponent:
    ( “e” | “E” ) sign? digit-sequence
sign:
    “+” | “-“
digit-sequence:
    digit
    | digit digit-sequence
digit:
    “0” | “1” | “2” | “3” | “4” | “5” | “6” | “7” | “8” | “9”
wsp:
    (#x20 | #x9 | #xD | #xA)
一个BNF的处理必须尽可能的满足一个给定的BNF产品,并在直到一个字符不满足这个产品的要求时停止。因此在字符串”M100-200″中,moveto指令被认为是100,因为因为负号不可以跟随在一个数字之后成为一个坐标值。moveto指令的第二个参数会是-200.类似的,对于字符串”M0.6.5″,第一个坐标值是0.6,解析因为遇到第二个小数点而停止,因为坐标值只允许有一个小数点。那么第二个坐标值将是”.5″。
注意:BNF范式允许路径的”d”属性是一个空值。这不会出错,但是他不能展示一个路径。
四:沿路径的长度
   各种各样的操作,例如在路径上的文本和路径动画以及各种边界操作,这些都需要用户来计算沿着一个几何图形的长度,例如”path”。
   精确地数学公式可以计算沿着路径的长度,但是这些数学公式非常的复杂并需要大量的计算。这会提示制作产品或者用户使用算法来获取尽可能精确地结果。但是,为了尽可能的兼容不同的实现和帮助计算出近似的合乎用户目的的长度结果,”pathLength”属性被用来保存用户的对整个路径长度的记过,以便于用户可以通过用户自己计算出的路径长度比率”pathLength”来缩放沿整个路径的长度。
   当一个”path”内只有moveto指令操作时,路径长度为0.只有各种lineto,curveto,arcto指令才会启动长度计算。