Bar.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /**
  2. * Constructs a new bar mark with default properties. Bars 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 bar: an axis-aligned rectangle that can be stroked and
  7. * filled. Bars are used for many chart types, including bar charts, histograms
  8. * and Gantt charts. Bars can also be used as decorations, for example to draw a
  9. * frame border around a panel; in fact, a panel is a special type (a subclass)
  10. * of bar.
  11. *
  12. * <p>Bars can be positioned in several ways. Most commonly, one of the four
  13. * corners is fixed using two margins, and then the width and height properties
  14. * determine the extent of the bar relative to this fixed location. For example,
  15. * using the bottom and left properties fixes the bottom-left corner; the width
  16. * then extends to the right, while the height extends to the top. As an
  17. * alternative to the four corners, a bar can be positioned exclusively using
  18. * margins; this is convenient as an inset from the containing panel, for
  19. * example. See {@link pv.Mark} for details on the prioritization of redundant
  20. * positioning properties.
  21. *
  22. * <p>See also the <a href="../../api/Bar.html">Bar guide</a>.
  23. *
  24. * @extends pv.Mark
  25. */
  26. pv.Bar = function() {
  27. pv.Mark.call(this);
  28. };
  29. pv.Bar.prototype = pv.extend(pv.Mark)
  30. .property("width")
  31. .property("height")
  32. .property("lineWidth")
  33. .property("strokeStyle")
  34. .property("fillStyle");
  35. pv.Bar.prototype.type = "bar";
  36. /**
  37. * The width of the bar, in pixels. If the left position is specified, the bar
  38. * extends rightward from the left edge; if the right position is specified, the
  39. * bar extends leftward from the right edge.
  40. *
  41. * @type number
  42. * @name pv.Bar.prototype.width
  43. */
  44. /**
  45. * The height of the bar, in pixels. If the bottom position is specified, the
  46. * bar extends upward from the bottom edge; if the top position is specified,
  47. * the bar extends downward from the top edge.
  48. *
  49. * @type number
  50. * @name pv.Bar.prototype.height
  51. */
  52. /**
  53. * The width of stroked lines, in pixels; used in conjunction with
  54. * <tt>strokeStyle</tt> to stroke the bar's border.
  55. *
  56. * @type number
  57. * @name pv.Bar.prototype.lineWidth
  58. */
  59. /**
  60. * The style of stroked lines; used in conjunction with <tt>lineWidth</tt> to
  61. * stroke the bar's border. The default value of this property is null, meaning
  62. * bars are not stroked by default.
  63. *
  64. * @type string
  65. * @name pv.Bar.prototype.strokeStyle
  66. * @see pv.color
  67. */
  68. /**
  69. * The bar fill style; if non-null, the interior of the bar is filled with the
  70. * specified color. The default value of this property is a categorical color.
  71. *
  72. * @type string
  73. * @name pv.Bar.prototype.fillStyle
  74. * @see pv.color
  75. */
  76. /**
  77. * Default properties for bars. By default, there is no stroke and the fill
  78. * style is a categorical color.
  79. *
  80. * @type pv.Bar
  81. */
  82. pv.Bar.prototype.defaults = new pv.Bar()
  83. .extend(pv.Mark.prototype.defaults)
  84. .lineWidth(1.5)
  85. .fillStyle(defaultFillStyle);
  86. /**
  87. * Constructs a new bar anchor with default properties. Bars support five
  88. * different anchors:<ul>
  89. *
  90. * <li>top
  91. * <li>left
  92. * <li>center
  93. * <li>bottom
  94. * <li>right
  95. *
  96. * </ul>In addition to positioning properties (left, right, top bottom), the
  97. * anchors support text rendering properties (text-align, text-baseline). Text
  98. * is rendered to appear inside the bar.
  99. *
  100. * <p>To facilitate stacking of bars, the anchors are defined in terms of their
  101. * opposite edge. For example, the top anchor defines the bottom property, such
  102. * that the bar grows upwards; the bottom anchor instead defines the top
  103. * property, such that the bar grows downwards. Of course, in general it is more
  104. * robust to use panels and the cousin accessor to define stacked bars; see
  105. * {@link pv.Mark#scene} for an example.
  106. *
  107. * <p>Bar anchors also "smartly" specify position properties based on whether
  108. * the derived mark type supports the width and height properties. If the
  109. * derived mark type does not support these properties (e.g., dots), the
  110. * position will be centered on the corresponding edge. Otherwise (e.g., bars),
  111. * the position will be in the opposite side.
  112. *
  113. * @param {string} name the anchor name; either a string or a property function.
  114. * @returns {pv.Anchor}
  115. */
  116. pv.Bar.prototype.anchor = function(name) {
  117. var bar = this;
  118. return pv.Mark.prototype.anchor.call(this, name)
  119. .left(function() {
  120. switch (this.name()) {
  121. case "bottom":
  122. case "top":
  123. case "center": return bar.left() + (this.properties.width ? 0 : (bar.width() / 2));
  124. case "right": return bar.left() + bar.width();
  125. }
  126. return null;
  127. })
  128. .right(function() {
  129. switch (this.name()) {
  130. case "bottom":
  131. case "top":
  132. case "center": return bar.right() + (this.properties.width ? 0 : (bar.width() / 2));
  133. case "left": return bar.right() + bar.width();
  134. }
  135. return null;
  136. })
  137. .top(function() {
  138. switch (this.name()) {
  139. case "left":
  140. case "right":
  141. case "center": return bar.top() + (this.properties.height ? 0 : (bar.height() / 2));
  142. case "bottom": return bar.top() + bar.height();
  143. }
  144. return null;
  145. })
  146. .bottom(function() {
  147. switch (this.name()) {
  148. case "left":
  149. case "right":
  150. case "center": return bar.bottom() + (this.properties.height ? 0 : (bar.height() / 2));
  151. case "top": return bar.bottom() + bar.height();
  152. }
  153. return null;
  154. })
  155. .textAlign(function() {
  156. switch (this.name()) {
  157. case "bottom":
  158. case "top":
  159. case "center": return "center";
  160. case "right": return "right";
  161. }
  162. return "left";
  163. })
  164. .textBaseline(function() {
  165. switch (this.name()) {
  166. case "right":
  167. case "left":
  168. case "center": return "middle";
  169. case "top": return "top";
  170. }
  171. return "bottom";
  172. });
  173. };