axis.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. import { deepMix, each, isFunction, mix, parsePadding, isNil } from '../../util/common';
  2. import Axis from '../../component/axis/index';
  3. import Global from '../../global';
  4. function formatTicks(ticks) {
  5. var tmp = ticks.slice(0);
  6. if (tmp.length > 0) {
  7. var first = tmp[0];
  8. var last = tmp[tmp.length - 1];
  9. if (first.value !== 0) {
  10. tmp.unshift({
  11. value: 0
  12. });
  13. }
  14. if (last.value !== 1) {
  15. tmp.push({
  16. value: 1
  17. });
  18. }
  19. }
  20. return tmp;
  21. }
  22. class AxisController {
  23. constructor(cfg) {
  24. this.axisCfg = {};
  25. this.frontPlot = null;
  26. this.backPlot = null;
  27. this.axes = {}; // store the axes's options
  28. mix(this, cfg);
  29. }
  30. _isHide(field) {
  31. var axisCfg = this.axisCfg;
  32. return !axisCfg || axisCfg[field] === false;
  33. }
  34. _getLinePosition(scale, dimType, index, transposed) {
  35. var position = '';
  36. var field = scale.field;
  37. var axisCfg = this.axisCfg;
  38. if (axisCfg[field] && axisCfg[field].position) {
  39. position = axisCfg[field].position;
  40. } else if (dimType === 'x') {
  41. position = transposed ? 'left' : 'bottom';
  42. } else if (dimType === 'y') {
  43. position = index ? 'right' : 'left';
  44. if (transposed) {
  45. position = 'bottom';
  46. }
  47. }
  48. return position;
  49. }
  50. _getLineCfg(coord, dimType, position) {
  51. var start;
  52. var end;
  53. var factor = 1; // Mark clockwise or counterclockwise
  54. if (dimType === 'x') {
  55. start = {
  56. x: 0,
  57. y: 0
  58. };
  59. end = {
  60. x: 1,
  61. y: 0
  62. };
  63. } else {
  64. if (position === 'right') {
  65. // there will be several y axes
  66. start = {
  67. x: 1,
  68. y: 0
  69. };
  70. end = {
  71. x: 1,
  72. y: 1
  73. };
  74. } else {
  75. start = {
  76. x: 0,
  77. y: 0
  78. };
  79. end = {
  80. x: 0,
  81. y: 1
  82. };
  83. factor = -1;
  84. }
  85. }
  86. if (coord.transposed) {
  87. factor *= -1;
  88. }
  89. return {
  90. offsetFactor: factor,
  91. start: coord.convertPoint(start),
  92. end: coord.convertPoint(end)
  93. };
  94. }
  95. _getCircleCfg(coord) {
  96. return {
  97. startAngle: coord.startAngle,
  98. endAngle: coord.endAngle,
  99. center: coord.center,
  100. radius: coord.circleRadius
  101. };
  102. }
  103. _getRadiusCfg(coord) {
  104. var transposed = coord.transposed;
  105. var start;
  106. var end;
  107. if (transposed) {
  108. start = {
  109. x: 0,
  110. y: 0
  111. };
  112. end = {
  113. x: 1,
  114. y: 0
  115. };
  116. } else {
  117. start = {
  118. x: 0,
  119. y: 0
  120. };
  121. end = {
  122. x: 0,
  123. y: 1
  124. };
  125. }
  126. return {
  127. offsetFactor: -1,
  128. start: coord.convertPoint(start),
  129. end: coord.convertPoint(end)
  130. };
  131. }
  132. _getAxisCfg(coord, scale, verticalScale, dimType, defaultCfg) {
  133. var _this = this;
  134. var self = this;
  135. var axisCfg = this.axisCfg;
  136. var ticks = scale.getTicks();
  137. var cfg = deepMix({
  138. ticks,
  139. frontContainer: this.frontPlot,
  140. backContainer: this.backPlot
  141. }, defaultCfg, axisCfg[scale.field]);
  142. var labels = [];
  143. var label = cfg.label;
  144. var count = ticks.length;
  145. var maxWidth = 0;
  146. var maxHeight = 0;
  147. var labelCfg = label;
  148. each(ticks, function (tick, index) {
  149. if (isFunction(label)) {
  150. var executedLabel = label(tick.text, index, count);
  151. labelCfg = executedLabel ? mix({}, Global._defaultAxis.label, executedLabel) : null;
  152. }
  153. if (labelCfg) {
  154. var textStyle = {};
  155. if (labelCfg.textAlign) {
  156. textStyle.textAlign = labelCfg.textAlign;
  157. }
  158. if (labelCfg.textBaseline) {
  159. textStyle.textBaseline = labelCfg.textBaseline;
  160. }
  161. var container = labelCfg.top ? _this.frontPlot : _this.backPlot;
  162. var axisLabel = container.addShape('text', {
  163. className: 'axis-label',
  164. aria: false,
  165. attrs: mix({
  166. x: 0,
  167. y: 0,
  168. text: tick.text,
  169. fontFamily: self.chart.get('canvas').get('fontFamily')
  170. }, labelCfg),
  171. value: tick.value,
  172. textStyle,
  173. top: labelCfg.top,
  174. context: self.chart.get('canvas').get('context')
  175. });
  176. labels.push(axisLabel);
  177. var {
  178. width,
  179. height
  180. } = axisLabel.getBBox();
  181. maxWidth = Math.max(maxWidth, width);
  182. maxHeight = Math.max(maxHeight, height);
  183. }
  184. });
  185. cfg.labels = labels;
  186. cfg.maxWidth = maxWidth;
  187. cfg.maxHeight = maxHeight;
  188. return cfg;
  189. }
  190. _createAxis(coord, scale, verticalScale, dimType) {
  191. var index = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : '';
  192. var self = this;
  193. var coordType = coord.type;
  194. var transposed = coord.transposed;
  195. var type;
  196. var key;
  197. var defaultCfg;
  198. if (coordType === 'cartesian' || coordType === 'rect') {
  199. var position = self._getLinePosition(scale, dimType, index, transposed);
  200. defaultCfg = Global.axis[position];
  201. defaultCfg.position = position;
  202. type = 'Line';
  203. key = position;
  204. } else {
  205. if (dimType === 'x' && !transposed || dimType === 'y' && transposed) {
  206. defaultCfg = Global.axis.circle;
  207. type = 'Circle';
  208. key = 'circle';
  209. } else {
  210. defaultCfg = Global.axis.radius;
  211. type = 'Line';
  212. key = 'radius';
  213. }
  214. }
  215. var cfg = self._getAxisCfg(coord, scale, verticalScale, dimType, defaultCfg);
  216. cfg.type = type;
  217. cfg.dimType = dimType;
  218. cfg.verticalScale = verticalScale;
  219. cfg.index = index;
  220. this.axes[key] = cfg;
  221. }
  222. createAxis(coord, xScale, yScales) {
  223. var self = this;
  224. if (xScale && !self._isHide(xScale.field)) {
  225. self._createAxis(coord, xScale, yScales[0], 'x');
  226. }
  227. each(yScales, function (yScale, index) {
  228. if (!self._isHide(yScale.field)) {
  229. self._createAxis(coord, yScale, xScale, 'y', index);
  230. }
  231. });
  232. var axes = this.axes;
  233. var chart = self.chart;
  234. if (chart._isAutoPadding()) {
  235. var userPadding = parsePadding(chart.get('padding'));
  236. var appendPadding = parsePadding(chart.get('appendPadding'));
  237. var legendRange = chart.get('legendRange') || {
  238. top: 0,
  239. right: 0,
  240. bottom: 0,
  241. left: 0
  242. };
  243. var padding = [userPadding[0] === 'auto' ? legendRange.top + appendPadding[0] * 2 : userPadding[0], userPadding[1] === 'auto' ? legendRange.right + appendPadding[1] : userPadding[1], userPadding[2] === 'auto' ? legendRange.bottom + appendPadding[2] : userPadding[2], userPadding[3] === 'auto' ? legendRange.left + appendPadding[3] : userPadding[3]];
  244. if (coord.isPolar) {
  245. var circleAxis = axes.circle;
  246. if (circleAxis) {
  247. var {
  248. maxHeight,
  249. maxWidth,
  250. labelOffset
  251. } = circleAxis;
  252. padding[0] += maxHeight + labelOffset;
  253. padding[1] += maxWidth + labelOffset;
  254. padding[2] += maxHeight + labelOffset;
  255. padding[3] += maxWidth + labelOffset;
  256. }
  257. } else {
  258. if (axes.right && userPadding[1] === 'auto') {
  259. var {
  260. maxWidth: _maxWidth,
  261. labelOffset: _labelOffset
  262. } = axes.right;
  263. padding[1] += _maxWidth + _labelOffset;
  264. }
  265. if (axes.left && userPadding[3] === 'auto') {
  266. var {
  267. maxWidth: _maxWidth2,
  268. labelOffset: _labelOffset2
  269. } = axes.left;
  270. padding[3] += _maxWidth2 + _labelOffset2;
  271. }
  272. if (axes.bottom && userPadding[2] === 'auto') {
  273. var {
  274. maxHeight: _maxHeight,
  275. labelOffset: _labelOffset3
  276. } = axes.bottom;
  277. padding[2] += _maxHeight + _labelOffset3;
  278. }
  279. }
  280. chart.set('_padding', padding);
  281. chart._updateLayout(padding);
  282. }
  283. each(axes, function (axis) {
  284. var {
  285. type,
  286. grid,
  287. verticalScale,
  288. ticks,
  289. dimType,
  290. position,
  291. index
  292. } = axis;
  293. var appendCfg;
  294. if (coord.isPolar) {
  295. if (type === 'Line') {
  296. appendCfg = self._getRadiusCfg(coord);
  297. } else if (type === 'Circle') {
  298. appendCfg = self._getCircleCfg(coord);
  299. }
  300. } else {
  301. appendCfg = self._getLineCfg(coord, dimType, position);
  302. }
  303. if (grid && verticalScale) {
  304. var gridPoints = [];
  305. var verticalTicks = formatTicks(verticalScale.getTicks());
  306. each(ticks, function (tick) {
  307. var subPoints = [];
  308. each(verticalTicks, function (verticalTick) {
  309. var x = dimType === 'x' ? tick.value : verticalTick.value;
  310. var y = dimType === 'x' ? verticalTick.value : tick.value;
  311. if (x >= 0 && x <= 1 && y >= 0 && y <= 1) {
  312. var point = coord.convertPoint({
  313. x,
  314. y
  315. });
  316. subPoints.push(point);
  317. }
  318. });
  319. gridPoints.push({
  320. points: subPoints,
  321. _id: 'axis-' + dimType + index + '-grid-' + tick.tickValue
  322. });
  323. });
  324. axis.gridPoints = gridPoints;
  325. if (coord.isPolar) {
  326. axis.center = coord.center;
  327. axis.startAngle = coord.startAngle;
  328. axis.endAngle = coord.endAngle;
  329. }
  330. }
  331. appendCfg._id = 'axis-' + dimType;
  332. if (!isNil(index)) {
  333. appendCfg._id = 'axis-' + dimType + index;
  334. }
  335. new Axis[type](mix(axis, appendCfg));
  336. });
  337. }
  338. clear() {
  339. this.axes = {};
  340. this.frontPlot.clear();
  341. this.backPlot.clear();
  342. }
  343. }
  344. export default AxisController;