d3

SVG Paths

28 May 2014

すべての形を作るためのもの

SVG Pathは、 rectangles, circles, ellipses, polylines, polygons, straight lines, と curves を描けます。

W3 は SVG Paths を下記のように定義しています:

* SVG Paths represent the outline of a shape that can be stroked, filled, used as a clipping path, or any combination of all three.

W3 は、下記のように、大まかにペンと紙に似たものとして規定してもいます:

  1. Imagine that a pen is put on a piece of paper.
  2. The pen will touch the paper in only one point.
  3. The pen is now moved to another point.
  4. The path between the two points can be a straight line or a curve.
  5. The curve can be an arc, a cubic Bézier curve or a quadratic Bézier curve.

つまり、SVG Pahtは、どのタイプの形をも描くことができます。

SVG Pathの例

SVG Path 要素は、1つの属性: d で定義されます。

この属性 dは, SVG Path Mini-Languageの中に コマンドと引数の連続したデータが入っています。

コマンドと引数は、いかに「紙の上でペンを動かすのか」という連続する命令です。

定義されている命令

三角形の例

<svg width="100" height="100">
            <path d=" M 10 25
                      L 10 75 
                      L 60 75
                      L 10 25"
                      stroke="red" stroke-width="2" fill="none" />
</svg>          

d=" M 10 25 ... " は、SVGペンに与える命令の集合です。

この場合には、最初にx座標、次にy座標を示しています。

つまり、SVG Pathに対して、ペンを置いて、三角形の左辺を描き、底辺を描き、斜辺を描けと命令しているのです。

残りのコマンド(stroke, stroke-width, fill)は、線の外観を指定しています。

大文字の(M, L)は、SVGビューウィンドウ上の絶対位置座標を使うことを意味しています。

小文字の場合は、相対位置を使う意味になります。

SVG Path Mini-Language

Mini-Languageの定義

Command Parameters Repeatable Explanation
Pen Command
M ( m ) x, y Yes moveto
Move the pen to a new location. No line is drawn. All path data must begin with a 'moveto' command.
Line Commands
L ( l ) x, y Yes lineto
Draw a line from the current point to the point (x,y).
H ( h ) x Yes horizontal lineto
Draw a horizontal line from the current point to x.
V ( v ) y Yes vertical lineto
Draw a horizontal line from the current point to y.
Cubic Bezier Curve Commands
C ( c ) x1 y1 x2 y2 x y Yes curveto
Draw a cubic Bézier curve from the current point to the point (x,y) using (x1,y1) as the control point at the beginning of the curve and (x2,y2) as the control point at the end of the curve.
S ( s ) x2 y2 x y Yes shorthand/smooth curveto
Draw a cubic Bézier curve from the current point to (x,y). The first control point is assumed to be the reflection of the last control point on the previous command relative to the current point. (x2,y2) is the second control point (i.e., the control point at the end of the curve).
Quadratic Bezier Curve Commands
Q ( q ) x1 y1 x y Yes quadratic Bézier curveto
Draw a quadratic Bézier curve from the current point to (x,y) using (x1,y1) as the control point.
T ( t ) x y Yes Shorthand/smooth quadratic Bézier curveto
Draw a quadratic Bézier curve from the current point to (x,y). The control point is assumed to be the reflection of the control point on the previous command relative to the current point.
Elliptical Arc Curve Command
A ( a ) rx ry x-axis-rotation large-arc-flag sweep-flag x y Yes elliptical arc
Draws an elliptical arc from the current point to (x, y). The size and orientation of the ellipse are defined by two radii (rx, ry) and an x-axis-rotation, which indicate how the ellipse as a whole is rotated relative to the current SVG coordinate system. The center (cx, cy) of the ellipse is calculated automatically to satisfy the constraints imposed by the other parameters. large-arc-flag and sweep-flag contribute to the automatic calculations and help determine how the arc is drawn.
End Path Command
Z ( z ) none No closepath
Closes the path. A line is drawn from the last point to the first point drawn.

Path データ・ジェネレータ Line

D3.js は、SVG Path 命令を生成するヘルパー・クラスがあります。

すべての D3.js Path Data Generatorに触れる前に, まず line path data generatorの例を見てみましょう。

線グラフの、一組の点(x,y)があります。

一組の点(x,y)は、1本の線を表します。

そこで、データを受け取り、それをSVG Path Mini-Languageに変換してくれる関数が必要です。

D3.jsは lineのためのPath Data Generatorを提供しています。

d3.svg.line()

このPath Data Generator関数は、データを受け取り必要なSVG Path コマンドを生成します

SVG Pathコマンドへデータを変換するために、データのx,y座標にアクセスする方法を line Path Data Generatorに伝える必要があります。

データのx,y座標を返すアクセサ関数を提供することで行います。

Pathデータを作成するために、path generatorが使うアクセサ関数を定義します。 

var lineFunction = d3.svg.line()
                          .x(function(d) { return d.x; })
                          .y(function(d) { return d.y; })
                          .interpolate("linear");

このアクセサ関数は、 D3.jsに渡されたデータ配列を取り込み、x,y座標の塊に分解します。

それは、各点の間を直線で補間するのです。

その結果は、d属性としてSVG Pathに返されます。

//The data for our line
var lineData = [ { "x": 1,   "y": 5},  { "x": 20,  "y": 20},
                 { "x": 40,  "y": 10}, { "x": 60,  "y": 40},
                 { "x": 80,  "y": 5},  { "x": 100, "y": 60}];

//This is the accessor function we talked about above
var lineFunction = d3.svg.line()
                         .x(function(d) { return d.x; })
                         .y(function(d) { return d.y; })
                         .interpolate("linear");

//The SVG Container
var svg01 = d3.select("#ins01").append("svg")
                               .attr("width", 200)
                               .attr("height", 100);

//The line SVG Path we draw
var lineGraph = svg01.append("path")
                            .attr("d", lineFunction(lineData))
                            .attr("stroke", "white")
                            .attr("stroke-width", 2)
                            .attr("fill", "none");            

ノート

上記の例では、次のデータセットを使っています。

var lineData = [ { "x": 1,   "y": 5},  { "x": 20,  "y": 20},
                 { "x": 40,  "y": 10}, { "x": 60,  "y": 40},
                 { "x": 80,  "y": 5},  { "x": 100, "y": 60}];

そのデータは、アクセサ関数を伴うd3.svg.line()関数を通じて実行されています。

そして次のSVG Pathが生成されます。

<path d="M1,5L20,20L40,10L60,40L80,5L100,60" stroke="yellow" stroke-width="2" fill="none"></path>

Path Data Generators

D3.jsには、SVG Path命令を生成するための Path Data Generatorヘルパークラスのセットを持っています。

上記の例は line Path Data Generator です。

Path Generator は、オブジェクトであり関数でもあります。

それは、関数のように呼び出すことができ、 その動作を変えるためにメソッドを追加することができるという意味です。

D3の他のクラス同様、pathジェネレータは、セッタメソッドが自分自身を返すような メソッド・チェイン形式に従っています。 

このことは、簡潔な文で、複数のセッタ関数を起動させることができます。

ジェネレータ

Path line generator Demo:Polygon

// svg空間作成 
var svg13 =  d3.select("#ins13")
               .append("svg:svg")
               .attr("height", 300)
               .attr("width","100%");

// 座標
var tree1 = [
  {"x":130,"y":240},{"x":130,"y":300},
  {"x":170,"y":300},{"x":170,"y":240}
];
var tree2 = [
  {"x":150,"y":100},{"x":100,"y":150},{"x":130,"y":150},
  {"x": 80,"y":200},{"x":130,"y":200},{"x": 50,"y":250},
  {"x":250,"y":250},{"x":170,"y":200},{"x":220,"y":200},
  {"x":170,"y":150},{"x":200,"y":150}
];

// Path line generator 
lineF13 = d3.svg.line()
                .x(function(d) { return d.x; })
                .y(function(d) { return d.y; })
                .interpolate("linear");  
// drawing
svg13.append("path")
     .attr("d", function(d) { return lineF13(tree1) + "Z"; }) //<- Z コマンドで線を閉じる
     .attr("fill", "brown");

svg13.append("path")
     .attr("d", function(d) { return lineF13(tree2) + "Z"; })
     .attr("fill", "green");