Axis.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. var zrUtil = require("zrender/lib/core/util");
  2. var numberUtil = require("../util/number");
  3. var axisHelper = require("./axisHelper");
  4. var linearMap = numberUtil.linearMap;
  5. function fixExtentWithBands(extent, nTick) {
  6. var size = extent[1] - extent[0];
  7. var len = nTick;
  8. var margin = size / len / 2;
  9. extent[0] += margin;
  10. extent[1] -= margin;
  11. }
  12. var normalizedExtent = [0, 1];
  13. /**
  14. * @name module:echarts/coord/CartesianAxis
  15. * @constructor
  16. */
  17. var Axis = function (dim, scale, extent) {
  18. /**
  19. * Axis dimension. Such as 'x', 'y', 'z', 'angle', 'radius'
  20. * @type {string}
  21. */
  22. this.dim = dim;
  23. /**
  24. * Axis scale
  25. * @type {module:echarts/coord/scale/*}
  26. */
  27. this.scale = scale;
  28. /**
  29. * @type {Array.<number>}
  30. * @private
  31. */
  32. this._extent = extent || [0, 0];
  33. /**
  34. * @type {boolean}
  35. */
  36. this.inverse = false;
  37. /**
  38. * Usually true when axis has a ordinal scale
  39. * @type {boolean}
  40. */
  41. this.onBand = false;
  42. /**
  43. * @private
  44. * @type {number}
  45. */
  46. this._labelInterval;
  47. };
  48. Axis.prototype = {
  49. constructor: Axis,
  50. /**
  51. * If axis extent contain given coord
  52. * @param {number} coord
  53. * @return {boolean}
  54. */
  55. contain: function (coord) {
  56. var extent = this._extent;
  57. var min = Math.min(extent[0], extent[1]);
  58. var max = Math.max(extent[0], extent[1]);
  59. return coord >= min && coord <= max;
  60. },
  61. /**
  62. * If axis extent contain given data
  63. * @param {number} data
  64. * @return {boolean}
  65. */
  66. containData: function (data) {
  67. return this.contain(this.dataToCoord(data));
  68. },
  69. /**
  70. * Get coord extent.
  71. * @return {Array.<number>}
  72. */
  73. getExtent: function () {
  74. return this._extent.slice();
  75. },
  76. /**
  77. * Get precision used for formatting
  78. * @param {Array.<number>} [dataExtent]
  79. * @return {number}
  80. */
  81. getPixelPrecision: function (dataExtent) {
  82. return numberUtil.getPixelPrecision(dataExtent || this.scale.getExtent(), this._extent);
  83. },
  84. /**
  85. * Set coord extent
  86. * @param {number} start
  87. * @param {number} end
  88. */
  89. setExtent: function (start, end) {
  90. var extent = this._extent;
  91. extent[0] = start;
  92. extent[1] = end;
  93. },
  94. /**
  95. * Convert data to coord. Data is the rank if it has a ordinal scale
  96. * @param {number} data
  97. * @param {boolean} clamp
  98. * @return {number}
  99. */
  100. dataToCoord: function (data, clamp) {
  101. var extent = this._extent;
  102. var scale = this.scale;
  103. data = scale.normalize(data);
  104. if (this.onBand && scale.type === 'ordinal') {
  105. extent = extent.slice();
  106. fixExtentWithBands(extent, scale.count());
  107. }
  108. return linearMap(data, normalizedExtent, extent, clamp);
  109. },
  110. /**
  111. * Convert coord to data. Data is the rank if it has a ordinal scale
  112. * @param {number} coord
  113. * @param {boolean} clamp
  114. * @return {number}
  115. */
  116. coordToData: function (coord, clamp) {
  117. var extent = this._extent;
  118. var scale = this.scale;
  119. if (this.onBand && scale.type === 'ordinal') {
  120. extent = extent.slice();
  121. fixExtentWithBands(extent, scale.count());
  122. }
  123. var t = linearMap(coord, extent, normalizedExtent, clamp);
  124. return this.scale.scale(t);
  125. },
  126. /**
  127. * Convert pixel point to data in axis
  128. * @param {Array.<number>} point
  129. * @param {boolean} clamp
  130. * @return {number} data
  131. */
  132. pointToData: function (point, clamp) {// Should be implemented in derived class if necessary.
  133. },
  134. /**
  135. * @return {Array.<number>}
  136. */
  137. getTicksCoords: function (alignWithLabel) {
  138. if (this.onBand && !alignWithLabel) {
  139. var bands = this.getBands();
  140. var coords = [];
  141. for (var i = 0; i < bands.length; i++) {
  142. coords.push(bands[i][0]);
  143. }
  144. if (bands[i - 1]) {
  145. coords.push(bands[i - 1][1]);
  146. }
  147. return coords;
  148. } else {
  149. return zrUtil.map(this.scale.getTicks(), this.dataToCoord, this);
  150. }
  151. },
  152. /**
  153. * Coords of labels are on the ticks or on the middle of bands
  154. * @return {Array.<number>}
  155. */
  156. getLabelsCoords: function () {
  157. return zrUtil.map(this.scale.getTicks(), this.dataToCoord, this);
  158. },
  159. /**
  160. * Get bands.
  161. *
  162. * If axis has labels [1, 2, 3, 4]. Bands on the axis are
  163. * |---1---|---2---|---3---|---4---|.
  164. *
  165. * @return {Array}
  166. */
  167. // FIXME Situation when labels is on ticks
  168. getBands: function () {
  169. var extent = this.getExtent();
  170. var bands = [];
  171. var len = this.scale.count();
  172. var start = extent[0];
  173. var end = extent[1];
  174. var span = end - start;
  175. for (var i = 0; i < len; i++) {
  176. bands.push([span * i / len + start, span * (i + 1) / len + start]);
  177. }
  178. return bands;
  179. },
  180. /**
  181. * Get width of band
  182. * @return {number}
  183. */
  184. getBandWidth: function () {
  185. var axisExtent = this._extent;
  186. var dataExtent = this.scale.getExtent();
  187. var len = dataExtent[1] - dataExtent[0] + (this.onBand ? 1 : 0); // Fix #2728, avoid NaN when only one data.
  188. len === 0 && (len = 1);
  189. var size = Math.abs(axisExtent[1] - axisExtent[0]);
  190. return Math.abs(size) / len;
  191. },
  192. /**
  193. * @abstract
  194. * @return {boolean} Is horizontal
  195. */
  196. isHorizontal: null,
  197. /**
  198. * @abstract
  199. * @return {number} Get axis rotate, by degree.
  200. */
  201. getRotate: null,
  202. /**
  203. * Get interval of the axis label.
  204. * To get precise result, at least one of `getRotate` and `isHorizontal`
  205. * should be implemented.
  206. * @return {number}
  207. */
  208. getLabelInterval: function () {
  209. var labelInterval = this._labelInterval;
  210. if (!labelInterval) {
  211. var axisModel = this.model;
  212. var labelModel = axisModel.getModel('axisLabel');
  213. labelInterval = labelModel.get('interval');
  214. if (this.type === 'category' && (labelInterval == null || labelInterval === 'auto')) {
  215. labelInterval = axisHelper.getAxisLabelInterval(zrUtil.map(this.scale.getTicks(), this.dataToCoord, this), axisModel.getFormattedLabels(), labelModel.getFont(), this.getRotate ? this.getRotate() : this.isHorizontal && !this.isHorizontal() ? 90 : 0, labelModel.get('rotate'));
  216. }
  217. this._labelInterval = labelInterval;
  218. }
  219. return labelInterval;
  220. }
  221. };
  222. var _default = Axis;
  223. module.exports = _default;