Grid.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. define("dojox/charting/plot2d/Grid", ["dojo/_base/lang", "dojo/_base/declare", "dojo/_base/connect", "dojo/_base/array",
  2. "../Element", "./common", "dojox/lang/utils", "dojox/gfx/fx"],
  3. function(lang, declare, hub, arr, Element, dc, du, fx){
  4. /*=====
  5. dojo.declare("dojox.charting.plot2d.__GridCtorArgs", dojox.charting.plot2d.__DefaultCtorArgs, {
  6. // summary:
  7. // A special keyword arguments object that is specific to a grid "plot".
  8. // hMajorLines: Boolean?
  9. // Whether to show lines at the major ticks along the horizontal axis. Default is true.
  10. hMajorLines: true,
  11. // hMinorLines: Boolean?
  12. // Whether to show lines at the minor ticks along the horizontal axis. Default is false.
  13. hMinorLines: false,
  14. // vMajorLines: Boolean?
  15. // Whether to show lines at the major ticks along the vertical axis. Default is true.
  16. vMajorLines: true,
  17. // vMinorLines: Boolean?
  18. // Whether to show lines at the major ticks along the vertical axis. Default is false.
  19. vMinorLines: false,
  20. // hStripes: String?
  21. // Whether or not to show stripes (alternating fills) along the horizontal axis. Default is "none".
  22. hStripes: "none",
  23. // vStripes: String?
  24. // Whether or not to show stripes (alternating fills) along the vertical axis. Default is "none".
  25. vStripes: "none",
  26. // enableCache: Boolean?
  27. // Whether the grid lines are cached from one rendering to another. This improves the rendering performance of
  28. // successive rendering but penalize the first rendering. Default false.
  29. enableCache: false
  30. });
  31. var Element = dojox.charting.plot2d.Element;
  32. =====*/
  33. return declare("dojox.charting.plot2d.Grid", Element, {
  34. // summary:
  35. // A "faux" plot that can be placed behind other plots to represent
  36. // a grid against which other plots can be easily measured.
  37. defaultParams: {
  38. hAxis: "x", // use a horizontal axis named "x"
  39. vAxis: "y", // use a vertical axis named "y"
  40. hMajorLines: true, // draw horizontal major lines
  41. hMinorLines: false, // draw horizontal minor lines
  42. vMajorLines: true, // draw vertical major lines
  43. vMinorLines: false, // draw vertical minor lines
  44. hStripes: "none", // TBD
  45. vStripes: "none", // TBD
  46. animate: null, // animate bars into place
  47. enableCache: false
  48. },
  49. optionalParams: {}, // no optional parameters
  50. constructor: function(chart, kwArgs){
  51. // summary:
  52. // Create the faux Grid plot.
  53. // chart: dojox.charting.Chart
  54. // The chart this plot belongs to.
  55. // kwArgs: dojox.charting.plot2d.__GridCtorArgs?
  56. // An optional keyword arguments object to help define the parameters of the underlying grid.
  57. this.opt = lang.clone(this.defaultParams);
  58. du.updateWithObject(this.opt, kwArgs);
  59. this.hAxis = this.opt.hAxis;
  60. this.vAxis = this.opt.vAxis;
  61. this.dirty = true;
  62. this.animate = this.opt.animate;
  63. this.zoom = null,
  64. this.zoomQueue = []; // zooming action task queue
  65. this.lastWindow = {vscale: 1, hscale: 1, xoffset: 0, yoffset: 0};
  66. if(this.opt.enableCache){
  67. this._lineFreePool = [];
  68. this._lineUsePool = [];
  69. }
  70. },
  71. clear: function(){
  72. // summary:
  73. // Clear out any parameters set on this plot.
  74. // returns: dojox.charting.plot2d.Grid
  75. // The reference to this plot for functional chaining.
  76. this._hAxis = null;
  77. this._vAxis = null;
  78. this.dirty = true;
  79. return this; // dojox.charting.plot2d.Grid
  80. },
  81. setAxis: function(axis){
  82. // summary:
  83. // Set an axis for this plot.
  84. // returns: dojox.charting.plot2d.Grid
  85. // The reference to this plot for functional chaining.
  86. if(axis){
  87. this[axis.vertical ? "_vAxis" : "_hAxis"] = axis;
  88. }
  89. return this; // dojox.charting.plot2d.Grid
  90. },
  91. addSeries: function(run){
  92. // summary:
  93. // Ignored but included as a dummy method.
  94. // returns: dojox.charting.plot2d.Grid
  95. // The reference to this plot for functional chaining.
  96. return this; // dojox.charting.plot2d.Grid
  97. },
  98. getSeriesStats: function(){
  99. // summary:
  100. // Returns default stats (irrelevant for this type of plot).
  101. // returns: Object
  102. // {hmin, hmax, vmin, vmax} min/max in both directions.
  103. return lang.delegate(dc.defaultStats);
  104. },
  105. initializeScalers: function(){
  106. // summary:
  107. // Does nothing (irrelevant for this type of plot).
  108. return this;
  109. },
  110. isDirty: function(){
  111. // summary:
  112. // Return whether or not this plot needs to be redrawn.
  113. // returns: Boolean
  114. // If this plot needs to be rendered, this will return true.
  115. return this.dirty || this._hAxis && this._hAxis.dirty || this._vAxis && this._vAxis.dirty; // Boolean
  116. },
  117. performZoom: function(dim, offsets){
  118. // summary:
  119. // Create/alter any zooming windows on this plot.
  120. // dim: Object
  121. // An object of the form { width, height }.
  122. // offsets: Object
  123. // An object of the form { l, r, t, b }.
  124. // returns: dojox.charting.plot2d.Grid
  125. // A reference to this plot for functional chaining.
  126. // get current zooming various
  127. var vs = this._vAxis.scale || 1,
  128. hs = this._hAxis.scale || 1,
  129. vOffset = dim.height - offsets.b,
  130. hBounds = this._hAxis.getScaler().bounds,
  131. xOffset = (hBounds.from - hBounds.lower) * hBounds.scale,
  132. vBounds = this._vAxis.getScaler().bounds,
  133. yOffset = (vBounds.from - vBounds.lower) * vBounds.scale,
  134. // get incremental zooming various
  135. rVScale = vs / this.lastWindow.vscale,
  136. rHScale = hs / this.lastWindow.hscale,
  137. rXOffset = (this.lastWindow.xoffset - xOffset)/
  138. ((this.lastWindow.hscale == 1)? hs : this.lastWindow.hscale),
  139. rYOffset = (yOffset - this.lastWindow.yoffset)/
  140. ((this.lastWindow.vscale == 1)? vs : this.lastWindow.vscale),
  141. shape = this.group,
  142. anim = fx.animateTransform(lang.delegate({
  143. shape: shape,
  144. duration: 1200,
  145. transform:[
  146. {name:"translate", start:[0, 0], end: [offsets.l * (1 - rHScale), vOffset * (1 - rVScale)]},
  147. {name:"scale", start:[1, 1], end: [rHScale, rVScale]},
  148. {name:"original"},
  149. {name:"translate", start: [0, 0], end: [rXOffset, rYOffset]}
  150. ]}, this.zoom));
  151. lang.mixin(this.lastWindow, {vscale: vs, hscale: hs, xoffset: xOffset, yoffset: yOffset});
  152. //add anim to zooming action queue,
  153. //in order to avoid several zooming action happened at the same time
  154. this.zoomQueue.push(anim);
  155. //perform each anim one by one in zoomQueue
  156. hub.connect(anim, "onEnd", this, function(){
  157. this.zoom = null;
  158. this.zoomQueue.shift();
  159. if(this.zoomQueue.length > 0){
  160. this.zoomQueue[0].play();
  161. }
  162. });
  163. if(this.zoomQueue.length == 1){
  164. this.zoomQueue[0].play();
  165. }
  166. return this; // dojox.charting.plot2d.Grid
  167. },
  168. getRequiredColors: function(){
  169. // summary:
  170. // Ignored but included as a dummy method.
  171. // returns: Number
  172. // Returns 0, since there are no series associated with this plot type.
  173. return 0; // Number
  174. },
  175. cleanGroup: function(){
  176. this.inherited(arguments);
  177. if(this.opt.enableCache){
  178. this._lineFreePool = this._lineFreePool.concat(this._lineUsePool);
  179. this._lineUsePool = [];
  180. }
  181. },
  182. createLine: function(creator, params){
  183. var line;
  184. if(this.opt.enableCache && this._lineFreePool.length > 0){
  185. line = this._lineFreePool.pop();
  186. line.setShape(params);
  187. // was cleared, add it back
  188. creator.add(line);
  189. }else{
  190. line = creator.createLine(params);
  191. }
  192. if(this.opt.enableCache){
  193. this._lineUsePool.push(line);
  194. }
  195. return line;
  196. },
  197. render: function(dim, offsets){
  198. // summary:
  199. // Render the plot on the chart.
  200. // dim: Object
  201. // An object of the form { width, height }.
  202. // offsets: Object
  203. // An object of the form { l, r, t, b }.
  204. // returns: dojox.charting.plot2d.Grid
  205. // A reference to this plot for functional chaining.
  206. if(this.zoom){
  207. return this.performZoom(dim, offsets);
  208. }
  209. this.dirty = this.isDirty();
  210. if(!this.dirty){ return this; }
  211. this.cleanGroup();
  212. var s = this.group, ta = this.chart.theme.axis;
  213. // draw horizontal stripes and lines
  214. try{
  215. var vScaler = this._vAxis.getScaler(),
  216. vt = vScaler.scaler.getTransformerFromModel(vScaler),
  217. ticks = this._vAxis.getTicks();
  218. if(ticks != null){
  219. if(this.opt.hMinorLines){
  220. arr.forEach(ticks.minor, function(tick){
  221. var y = dim.height - offsets.b - vt(tick.value);
  222. var hMinorLine = this.createLine(s, {
  223. x1: offsets.l,
  224. y1: y,
  225. x2: dim.width - offsets.r,
  226. y2: y
  227. }).setStroke(ta.minorTick);
  228. if(this.animate){
  229. this._animateGrid(hMinorLine, "h", offsets.l, offsets.r + offsets.l - dim.width);
  230. }
  231. }, this);
  232. }
  233. if(this.opt.hMajorLines){
  234. arr.forEach(ticks.major, function(tick){
  235. var y = dim.height - offsets.b - vt(tick.value);
  236. var hMajorLine = this.createLine(s, {
  237. x1: offsets.l,
  238. y1: y,
  239. x2: dim.width - offsets.r,
  240. y2: y
  241. }).setStroke(ta.majorTick);
  242. if(this.animate){
  243. this._animateGrid(hMajorLine, "h", offsets.l, offsets.r + offsets.l - dim.width);
  244. }
  245. }, this);
  246. }
  247. }
  248. }catch(e){
  249. // squelch
  250. }
  251. // draw vertical stripes and lines
  252. try{
  253. var hScaler = this._hAxis.getScaler(),
  254. ht = hScaler.scaler.getTransformerFromModel(hScaler),
  255. ticks = this._hAxis.getTicks();
  256. if(this != null){
  257. if(ticks && this.opt.vMinorLines){
  258. arr.forEach(ticks.minor, function(tick){
  259. var x = offsets.l + ht(tick.value);
  260. var vMinorLine = this.createLine(s, {
  261. x1: x,
  262. y1: offsets.t,
  263. x2: x,
  264. y2: dim.height - offsets.b
  265. }).setStroke(ta.minorTick);
  266. if(this.animate){
  267. this._animateGrid(vMinorLine, "v", dim.height - offsets.b, dim.height - offsets.b - offsets.t);
  268. }
  269. }, this);
  270. }
  271. if(ticks && this.opt.vMajorLines){
  272. arr.forEach(ticks.major, function(tick){
  273. var x = offsets.l + ht(tick.value);
  274. var vMajorLine = this.createLine(s, {
  275. x1: x,
  276. y1: offsets.t,
  277. x2: x,
  278. y2: dim.height - offsets.b
  279. }).setStroke(ta.majorTick);
  280. if(this.animate){
  281. this._animateGrid(vMajorLine, "v", dim.height - offsets.b, dim.height - offsets.b - offsets.t);
  282. }
  283. }, this);
  284. }
  285. }
  286. }catch(e){
  287. // squelch
  288. }
  289. this.dirty = false;
  290. return this; // dojox.charting.plot2d.Grid
  291. },
  292. _animateGrid: function(shape, type, offset, size){
  293. var transStart = type == "h" ? [offset, 0] : [0, offset];
  294. var scaleStart = type == "h" ? [1/size, 1] : [1, 1/size];
  295. fx.animateTransform(lang.delegate({
  296. shape: shape,
  297. duration: 1200,
  298. transform: [
  299. {name: "translate", start: transStart, end: [0, 0]},
  300. {name: "scale", start: scaleStart, end: [1, 1]},
  301. {name: "original"}
  302. ]
  303. }, this.animate)).play();
  304. }
  305. });
  306. });