Base.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. define("dojox/charting/plot2d/Base", ["dojo/_base/lang", "dojo/_base/declare", "dojo/_base/connect",
  2. "../Element", "./_PlotEvents", "dojo/_base/array",
  3. "../scaler/primitive", "./common", "dojox/gfx/fx"],
  4. function(lang, declare, hub, Element, PlotEvents, arr, primitive, common, fx){
  5. /*=====
  6. var Element = dojox.charting.Element;
  7. var PlotEvents = dojox.charting.plot2d._PlotEvents;
  8. dojox.charting.plot2d.__PlotCtorArgs = function(){
  9. // summary:
  10. // The base keyword arguments object for plot constructors.
  11. // Note that the parameters for this may change based on the
  12. // specific plot type (see the corresponding plot type for
  13. // details).
  14. }
  15. =====*/
  16. return declare("dojox.charting.plot2d.Base", [Element, PlotEvents], {
  17. constructor: function(chart, kwArgs){
  18. // summary:
  19. // Create a base plot for charting.
  20. // chart: dojox.chart.Chart
  21. // The chart this plot belongs to.
  22. // kwArgs: dojox.charting.plot2d.__PlotCtorArgs?
  23. // An optional arguments object to help define the plot.
  24. this.zoom = null,
  25. this.zoomQueue = []; // zooming action task queue
  26. this.lastWindow = {vscale: 1, hscale: 1, xoffset: 0, yoffset: 0};
  27. },
  28. clear: function(){
  29. // summary:
  30. // Clear out all of the information tied to this plot.
  31. // returns: dojox.charting.plot2d.Base
  32. // A reference to this plot for functional chaining.
  33. this.series = [];
  34. this._hAxis = null;
  35. this._vAxis = null;
  36. this.dirty = true;
  37. return this; // dojox.charting.plot2d.Base
  38. },
  39. setAxis: function(axis){
  40. // summary:
  41. // Set an axis for this plot.
  42. // axis: dojox.charting.axis2d.Base
  43. // The axis to set.
  44. // returns: dojox.charting.plot2d.Base
  45. // A reference to this plot for functional chaining.
  46. if(axis){
  47. this[axis.vertical ? "_vAxis" : "_hAxis"] = axis;
  48. }
  49. return this; // dojox.charting.plot2d.Base
  50. },
  51. toPage: function(coord){
  52. // summary:
  53. // Compute page coordinates from plot axis data coordinates.
  54. // coord: Object?
  55. // The coordinates in plot axis data coordinate space. For cartesian charts that is of the following form:
  56. // `{ hAxisName: 50, vAxisName: 200 }`
  57. // If not provided return the tranform method instead of the result of the transformation.
  58. // returns: Object
  59. // The resulting page pixel coordinates. That is of the following form:
  60. // `{ x: 50, y: 200 }`
  61. var ah = this._hAxis, av = this._vAxis,
  62. sh = ah.getScaler(), sv = av.getScaler(),
  63. th = sh.scaler.getTransformerFromModel(sh),
  64. tv = sv.scaler.getTransformerFromModel(sv),
  65. c = this.chart.getCoords(),
  66. o = this.chart.offsets, dim = this.chart.dim;
  67. var t = function(coord){
  68. var r = {};
  69. r.x = th(coord[ah.name]) + c.x + o.l;
  70. r.y = c.y + dim.height - o.b - tv(coord[av.name]);
  71. return r;
  72. };
  73. // if no coord return the function so that we can capture the current transforms
  74. // and reuse them later on
  75. return coord?t(coord):t;
  76. },
  77. toData: function(coord){
  78. // summary:
  79. // Compute plot axis data coordinates from page coordinates.
  80. // coord: Object
  81. // The pixel coordinate in page coordinate space. That is of the following form:
  82. // `{ x: 50, y: 200 }`
  83. // If not provided return the tranform method instead of the result of the transformation.
  84. // returns: Object
  85. // The resulting plot axis data coordinates. For cartesian charts that is of the following form:
  86. // `{ hAxisName: 50, vAxisName: 200 }`
  87. var ah = this._hAxis, av = this._vAxis,
  88. sh = ah.getScaler(), sv = av.getScaler(),
  89. th = sh.scaler.getTransformerFromPlot(sh),
  90. tv = sv.scaler.getTransformerFromPlot(sv),
  91. c = this.chart.getCoords(),
  92. o = this.chart.offsets, dim = this.chart.dim;
  93. var t = function(coord){
  94. var r = {};
  95. r[ah.name] = th(coord.x - c.x - o.l);
  96. r[av.name] = tv(c.y + dim.height - coord.y - o.b);
  97. return r;
  98. };
  99. // if no coord return the function so that we can capture the current transforms
  100. // and reuse them later on
  101. return coord?t(coord):t;
  102. },
  103. addSeries: function(run){
  104. // summary:
  105. // Add a data series to this plot.
  106. // run: dojox.charting.Series
  107. // The series to be added.
  108. // returns: dojox.charting.plot2d.Base
  109. // A reference to this plot for functional chaining.
  110. this.series.push(run);
  111. return this; // dojox.charting.plot2d.Base
  112. },
  113. getSeriesStats: function(){
  114. // summary:
  115. // Calculate the min/max on all attached series in both directions.
  116. // returns: Object
  117. // {hmin, hmax, vmin, vmax} min/max in both directions.
  118. return common.collectSimpleStats(this.series);
  119. },
  120. calculateAxes: function(dim){
  121. // summary:
  122. // Stub function for running the axis calculations (depricated).
  123. // dim: Object
  124. // An object of the form { width, height }
  125. // returns: dojox.charting.plot2d.Base
  126. // A reference to this plot for functional chaining.
  127. this.initializeScalers(dim, this.getSeriesStats());
  128. return this; // dojox.charting.plot2d.Base
  129. },
  130. isDirty: function(){
  131. // summary:
  132. // Returns whether or not this plot needs to be rendered.
  133. // returns: Boolean
  134. // The state of the plot.
  135. return this.dirty || this._hAxis && this._hAxis.dirty || this._vAxis && this._vAxis.dirty; // Boolean
  136. },
  137. isDataDirty: function(){
  138. // summary:
  139. // Returns whether or not any of this plot's data series need to be rendered.
  140. // returns: Boolean
  141. // Flag indicating if any of this plot's series are invalid and need rendering.
  142. return arr.some(this.series, function(item){ return item.dirty; }); // Boolean
  143. },
  144. performZoom: function(dim, offsets){
  145. // summary:
  146. // Create/alter any zooming windows on this plot.
  147. // dim: Object
  148. // An object of the form { width, height }.
  149. // offsets: Object
  150. // An object of the form { l, r, t, b }.
  151. // returns: dojox.charting.plot2d.Base
  152. // A reference to this plot for functional chaining.
  153. // get current zooming various
  154. var vs = this._vAxis.scale || 1,
  155. hs = this._hAxis.scale || 1,
  156. vOffset = dim.height - offsets.b,
  157. hBounds = this._hScaler.bounds,
  158. xOffset = (hBounds.from - hBounds.lower) * hBounds.scale,
  159. vBounds = this._vScaler.bounds,
  160. yOffset = (vBounds.from - vBounds.lower) * vBounds.scale,
  161. // get incremental zooming various
  162. rVScale = vs / this.lastWindow.vscale,
  163. rHScale = hs / this.lastWindow.hscale,
  164. rXOffset = (this.lastWindow.xoffset - xOffset)/
  165. ((this.lastWindow.hscale == 1)? hs : this.lastWindow.hscale),
  166. rYOffset = (yOffset - this.lastWindow.yoffset)/
  167. ((this.lastWindow.vscale == 1)? vs : this.lastWindow.vscale),
  168. shape = this.group,
  169. anim = fx.animateTransform(lang.delegate({
  170. shape: shape,
  171. duration: 1200,
  172. transform:[
  173. {name:"translate", start:[0, 0], end: [offsets.l * (1 - rHScale), vOffset * (1 - rVScale)]},
  174. {name:"scale", start:[1, 1], end: [rHScale, rVScale]},
  175. {name:"original"},
  176. {name:"translate", start: [0, 0], end: [rXOffset, rYOffset]}
  177. ]}, this.zoom));
  178. lang.mixin(this.lastWindow, {vscale: vs, hscale: hs, xoffset: xOffset, yoffset: yOffset});
  179. //add anim to zooming action queue,
  180. //in order to avoid several zooming action happened at the same time
  181. this.zoomQueue.push(anim);
  182. //perform each anim one by one in zoomQueue
  183. hub.connect(anim, "onEnd", this, function(){
  184. this.zoom = null;
  185. this.zoomQueue.shift();
  186. if(this.zoomQueue.length > 0){
  187. this.zoomQueue[0].play();
  188. }
  189. });
  190. if(this.zoomQueue.length == 1){
  191. this.zoomQueue[0].play();
  192. }
  193. return this; // dojox.charting.plot2d.Base
  194. },
  195. render: function(dim, offsets){
  196. // summary:
  197. // Render the plot on the chart.
  198. // dim: Object
  199. // An object of the form { width, height }.
  200. // offsets: Object
  201. // An object of the form { l, r, t, b }.
  202. // returns: dojox.charting.plot2d.Base
  203. // A reference to this plot for functional chaining.
  204. return this; // dojox.charting.plot2d.Base
  205. },
  206. getRequiredColors: function(){
  207. // summary:
  208. // Get how many data series we have, so we know how many colors to use.
  209. // returns: Number
  210. // The number of colors needed.
  211. return this.series.length; // Number
  212. },
  213. initializeScalers: function(dim, stats){
  214. // summary:
  215. // Initializes scalers using attached axes.
  216. // dim: Object:
  217. // Size of a plot area in pixels as {width, height}.
  218. // stats: Object:
  219. // Min/max of data in both directions as {hmin, hmax, vmin, vmax}.
  220. // returns: dojox.charting.plot2d.Base
  221. // A reference to this plot for functional chaining.
  222. if(this._hAxis){
  223. if(!this._hAxis.initialized()){
  224. this._hAxis.calculate(stats.hmin, stats.hmax, dim.width);
  225. }
  226. this._hScaler = this._hAxis.getScaler();
  227. }else{
  228. this._hScaler = primitive.buildScaler(stats.hmin, stats.hmax, dim.width);
  229. }
  230. if(this._vAxis){
  231. if(!this._vAxis.initialized()){
  232. this._vAxis.calculate(stats.vmin, stats.vmax, dim.height);
  233. }
  234. this._vScaler = this._vAxis.getScaler();
  235. }else{
  236. this._vScaler = primitive.buildScaler(stats.vmin, stats.vmax, dim.height);
  237. }
  238. return this; // dojox.charting.plot2d.Base
  239. }
  240. });
  241. });