Grid.js 9.9 KB

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