1 /**
  2  * Constructs a new line mark with default properties. Lines are not typically
  3  * constructed directly, but by adding to a panel or an existing mark via
  4  * {@link pv.Mark#add}.
  5  *
  6  * @class Represents a series of connected line segments, or <i>polyline</i>,
  7  * that can be stroked with a configurable color and thickness. Each
  8  * articulation point in the line corresponds to a datum; for <i>n</i> points,
  9  * <i>n</i>-1 connected line segments are drawn. The point is positioned using
 10  * the box model. Arbitrary paths are also possible, allowing radar plots and
 11  * other custom visualizations.
 12  *
 13  * <p>Like areas, lines can be stroked and filled with arbitrary colors. In most
 14  * cases, lines are only stroked, but the fill style can be used to construct
 15  * arbitrary polygons.
 16  *
 17  * <p>See also the <a href="../../api/Line.html">Line guide</a>.
 18  *
 19  * @extends pv.Mark
 20  */
 21 pv.Line = function() {
 22   pv.Mark.call(this);
 23 };
 24 
 25 pv.Line.prototype = pv.extend(pv.Mark)
 26     .property("lineWidth", Number)
 27     .property("lineJoin", String)
 28     .property("strokeStyle", pv.color)
 29     .property("fillStyle", pv.color)
 30     .property("segmented", Boolean)
 31     .property("interpolate", String)
 32     .property("eccentricity", Number)
 33     .property("tension", Number);
 34 
 35 pv.Line.prototype.type = "line";
 36 
 37 /**
 38  * The width of stroked lines, in pixels; used in conjunction with
 39  * <tt>strokeStyle</tt> to stroke the line.
 40  *
 41  * @type number
 42  * @name pv.Line.prototype.lineWidth
 43  */
 44 
 45 /**
 46  * The style of stroked lines; used in conjunction with <tt>lineWidth</tt> to
 47  * stroke the line. The default value of this property is a categorical color.
 48  *
 49  * @type string
 50  * @name pv.Line.prototype.strokeStyle
 51  * @see pv.color
 52  */
 53 
 54 /**
 55  * The type of corners where two lines meet. Accepted values are "bevel",
 56  * "round" and "miter". The default value is "miter".
 57  *
 58  * <p>For segmented lines, only "miter" joins and "linear" interpolation are
 59  * currently supported. Any other value, including null, will disable joins,
 60  * producing disjoint line segments. Note that the miter joins must be computed
 61  * manually (at least in the current SVG renderer); since this calculation may
 62  * be expensive and unnecessary for small lines, specifying null can improve
 63  * performance significantly.
 64  *
 65  * <p>This property is <i>fixed</i>. See {@link pv.Mark}.
 66  *
 67  * @type string
 68  * @name pv.Line.prototype.lineJoin
 69  */
 70 
 71 /**
 72  * The line fill style; if non-null, the interior of the line is closed and
 73  * filled with the specified color. The default value of this property is a
 74  * null, meaning that lines are not filled by default.
 75  *
 76  * <p>This property is <i>fixed</i>. See {@link pv.Mark}.
 77  *
 78  * @type string
 79  * @name pv.Line.prototype.fillStyle
 80  * @see pv.color
 81  */
 82 
 83 /**
 84  * Whether the line is segmented; whether variations in stroke style, line width
 85  * and the other properties are treated as fixed. Rendering segmented lines is
 86  * noticeably slower than non-segmented lines.
 87  *
 88  * <p>This property is <i>fixed</i>. See {@link pv.Mark}.
 89  *
 90  * @type boolean
 91  * @name pv.Line.prototype.segmented
 92  */
 93 
 94 /**
 95  * How to interpolate between values. Linear interpolation ("linear") is the
 96  * default, producing a straight line between points. For piecewise constant
 97  * functions (i.e., step functions), either "step-before" or "step-after" can be
 98  * specified. To draw a clockwise circular arc between points, specify "polar";
 99  * to draw a counterclockwise circular arc between points, specify
100  * "polar-reverse". To draw open uniform b-splines, specify "basis". To draw
101  * cardinal splines, specify "cardinal"; see also {@link #tension}.
102  *
103  * <p>This property is <i>fixed</i>. See {@link pv.Mark}.
104  *
105  * @type string
106  * @name pv.Line.prototype.interpolate
107  */
108 
109 /**
110  * The eccentricity of polar line segments; used in conjunction with
111  * interpolate("polar"). The default value of 0 means that line segments are
112  * drawn as circular arcs. A value of 1 draws a straight line. A value between 0
113  * and 1 draws an elliptical arc with the given eccentricity.
114  *
115  * @type number
116  * @name pv.Line.prototype.eccentricity
117  */
118 
119 /**
120  * The tension of cardinal splines; used in conjunction with
121  * interpolate("cardinal"). A value between 0 and 1 draws cardinal splines with
122  * the given tension. In some sense, the tension can be interpreted as the
123  * "length" of the tangent; a tension of 1 will yield all zero tangents (i.e.,
124  * linear interpolation), and a tension of 0 yields a Catmull-Rom spline. The
125  * default value is 0.7.
126  *
127  * <p>This property is <i>fixed</i>. See {@link pv.Mark}.
128  *
129  * @type number
130  * @name pv.Line.prototype.tension
131  */
132 
133 /**
134  * Default properties for lines. By default, there is no fill and the stroke
135  * style is a categorical color. The default interpolation is linear.
136  *
137  * @type pv.Line
138  */
139 pv.Line.prototype.defaults = new pv.Line()
140     .extend(pv.Mark.prototype.defaults)
141     .lineJoin("miter")
142     .lineWidth(1.5)
143     .strokeStyle(pv.Colors.category10().by(pv.parent))
144     .interpolate("linear")
145     .eccentricity(0)
146     .tension(.7);
147 
148 /** @private Reuse Area's implementation for segmented bind & build. */
149 pv.Line.prototype.bind = pv.Area.prototype.bind;
150 pv.Line.prototype.buildInstance = pv.Area.prototype.buildInstance;
151 
152 /**
153  * Constructs a new line anchor with default properties. Lines support five
154  * different anchors:<ul>
155  *
156  * <li>top
157  * <li>left
158  * <li>center
159  * <li>bottom
160  * <li>right
161  *
162  * </ul>In addition to positioning properties (left, right, top bottom), the
163  * anchors support text rendering properties (text-align, text-baseline). Text is
164  * rendered to appear outside the line. Note that this behavior is different
165  * from other mark anchors, which default to rendering text <i>inside</i> the
166  * mark.
167  *
168  * <p>For consistency with the other mark types, the anchor positions are
169  * defined in terms of their opposite edge. For example, the top anchor defines
170  * the bottom property, such that a bar added to the top anchor grows upward.
171  *
172  * @param {string} name the anchor name; either a string or a property function.
173  * @returns {pv.Anchor}
174  */
175 pv.Line.prototype.anchor = function(name) {
176   return pv.Area.prototype.anchor.call(this, name)
177     .textAlign(function(d) {
178         switch (this.name()) {
179           case "left": return "right";
180           case "bottom":
181           case "top":
182           case "center": return "center";
183           case "right": return "left";
184         }
185       })
186     .textBaseline(function(d) {
187         switch (this.name()) {
188           case "right":
189           case "left":
190           case "center": return "middle";
191           case "top": return "bottom";
192           case "bottom": return "top";
193         }
194       });
195 };
196