1 /**
  2  * Constructs a new dot mark with default properties. Dots 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 dot; a dot is simply a sized glyph centered at a given
  7  * point that can also be stroked and filled. The <tt>size</tt> property is
  8  * proportional to the area of the rendered glyph to encourage meaningful visual
  9  * encodings. Dots can visually encode up to eight dimensions of data, though
 10  * this may be unwise due to integrality. See {@link pv.Mark} for details on the
 11  * prioritization of redundant positioning properties.
 12  *
 13  * <p>See also the <a href="../../api/Dot.html">Dot guide</a>.
 14  *
 15  * @extends pv.Mark
 16  */
 17 pv.Dot = function() {
 18   pv.Mark.call(this);
 19 };
 20 
 21 pv.Dot.prototype = pv.extend(pv.Mark)
 22     .property("size")
 23     .property("shape")
 24     .property("angle")
 25     .property("lineWidth")
 26     .property("strokeStyle")
 27     .property("fillStyle");
 28 
 29 pv.Dot.prototype.type = "dot";
 30 
 31 /**
 32  * The size of the dot, in square pixels. Square pixels are used such that the
 33  * area of the dot is linearly proportional to the value of the size property,
 34  * facilitating representative encodings.
 35  *
 36  * @see #radius
 37  * @type number
 38  * @name pv.Dot.prototype.size
 39  */
 40 
 41 /**
 42  * The shape name. Several shapes are supported:<ul>
 43  *
 44  * <li>cross
 45  * <li>triangle
 46  * <li>diamond
 47  * <li>square
 48  * <li>tick
 49  * <li>circle
 50  *
 51  * </ul>These shapes can be further changed using the {@link #angle} property;
 52  * for instance, a cross can be turned into a plus by rotating. Similarly, the
 53  * tick, which is vertical by default, can be rotated horizontally. Note that
 54  * some shapes (cross and tick) do not have interior areas, and thus do not
 55  * support fill style meaningfully.
 56  *
 57  * <p>Note: it may be more natural to use the {@link pv.Rule} mark for
 58  * horizontal and vertical ticks. The tick shape is only necessary if angled
 59  * ticks are needed.
 60  *
 61  * @type string
 62  * @name pv.Dot.prototype.shape
 63  */
 64 
 65 /**
 66  * The rotation angle, in radians. Used to rotate shapes, such as to turn a
 67  * cross into a plus.
 68  *
 69  * @type number
 70  * @name pv.Dot.prototype.angle
 71  */
 72 
 73 /**
 74  * The width of stroked lines, in pixels; used in conjunction with
 75  * <tt>strokeStyle</tt> to stroke the dot's shape.
 76  *
 77  * @type number
 78  * @name pv.Dot.prototype.lineWidth
 79  */
 80 
 81 /**
 82  * The style of stroked lines; used in conjunction with <tt>lineWidth</tt> to
 83  * stroke the dot's shape. The default value of this property is a categorical
 84  * color.
 85  *
 86  * @type string
 87  * @name pv.Dot.prototype.strokeStyle
 88  * @see pv.color
 89  */
 90 
 91 /**
 92  * The fill style; if non-null, the interior of the dot is filled with the
 93  * specified color. The default value of this property is null, meaning dots are
 94  * not filled by default.
 95  *
 96  * @type string
 97  * @name pv.Dot.prototype.fillStyle
 98  * @see pv.color
 99  */
100 
101 /**
102  * Default properties for dots. By default, there is no fill and the stroke
103  * style is a categorical color. The default shape is "circle" with size 20.
104  *
105  * @type pv.Dot
106  */
107 pv.Dot.prototype.defaults = new pv.Dot()
108     .extend(pv.Mark.prototype.defaults)
109     .size(20)
110     .shape("circle")
111     .lineWidth(1.5)
112     .strokeStyle(defaultStrokeStyle);
113 
114 /**
115  * Constructs a new dot anchor with default properties. Dots support five
116  * different anchors:<ul>
117  *
118  * <li>top
119  * <li>left
120  * <li>center
121  * <li>bottom
122  * <li>right
123  *
124  * </ul>In addition to positioning properties (left, right, top bottom), the
125  * anchors support text rendering properties (text-align, text-baseline). Text is
126  * rendered to appear outside the dot. Note that this behavior is different from
127  * other mark anchors, which default to rendering text <i>inside</i> the mark.
128  *
129  * <p>For consistency with the other mark types, the anchor positions are
130  * defined in terms of their opposite edge. For example, the top anchor defines
131  * the bottom property, such that a bar added to the top anchor grows upward.
132  *
133  * @param {string} name the anchor name; either a string or a property function.
134  * @returns {pv.Anchor}
135  */
136 pv.Dot.prototype.anchor = function(name) {
137   var dot = this;
138   return pv.Mark.prototype.anchor.call(this, name)
139     .left(function(d) {
140         switch (this.name()) {
141           case "bottom":
142           case "top":
143           case "center": return dot.left();
144           case "right": return dot.left() + dot.radius();
145         }
146         return null;
147       })
148     .right(function(d) {
149         switch (this.name()) {
150           case "bottom":
151           case "top":
152           case "center": return dot.right();
153           case "left": return dot.right() + dot.radius();
154         }
155         return null;
156       })
157     .top(function(d) {
158         switch (this.name()) {
159           case "left":
160           case "right":
161           case "center": return dot.top();
162           case "bottom": return dot.top() + dot.radius();
163         }
164         return null;
165       })
166     .bottom(function(d) {
167         switch (this.name()) {
168           case "left":
169           case "right":
170           case "center": return dot.bottom();
171           case "top": return dot.bottom() + dot.radius();
172         }
173         return null;
174       })
175     .textAlign(function(d) {
176         switch (this.name()) {
177           case "left": return "right";
178           case "bottom":
179           case "top":
180           case "center": return "center";
181         }
182         return "left";
183       })
184     .textBaseline(function(d) {
185         switch (this.name()) {
186           case "right":
187           case "left":
188           case "center": return "middle";
189           case "bottom": return "top";
190         }
191         return "bottom";
192       });
193 };
194 
195 /**
196  * Returns the radius of the dot, which is defined to be the square root of the
197  * {@link #size} property.
198  *
199  * @returns {number} the radius.
200  */
201 pv.Dot.prototype.radius = function() {
202   return Math.sqrt(this.size());
203 };
204