Axis.js 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. /**
  20. * AUTO-GENERATED FILE. DO NOT MODIFY.
  21. */
  22. /*
  23. * Licensed to the Apache Software Foundation (ASF) under one
  24. * or more contributor license agreements. See the NOTICE file
  25. * distributed with this work for additional information
  26. * regarding copyright ownership. The ASF licenses this file
  27. * to you under the Apache License, Version 2.0 (the
  28. * "License"); you may not use this file except in compliance
  29. * with the License. You may obtain a copy of the License at
  30. *
  31. * http://www.apache.org/licenses/LICENSE-2.0
  32. *
  33. * Unless required by applicable law or agreed to in writing,
  34. * software distributed under the License is distributed on an
  35. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  36. * KIND, either express or implied. See the License for the
  37. * specific language governing permissions and limitations
  38. * under the License.
  39. */
  40. import { each, map } from 'zrender/lib/core/util.js';
  41. import { linearMap, getPixelPrecision, round } from '../util/number.js';
  42. import { createAxisTicks, createAxisLabels, calculateCategoryInterval } from './axisTickLabelBuilder.js';
  43. var NORMALIZED_EXTENT = [0, 1];
  44. /**
  45. * Base class of Axis.
  46. */
  47. var Axis = /** @class */function () {
  48. function Axis(dim, scale, extent) {
  49. this.onBand = false;
  50. this.inverse = false;
  51. this.dim = dim;
  52. this.scale = scale;
  53. this._extent = extent || [0, 0];
  54. }
  55. /**
  56. * If axis extent contain given coord
  57. */
  58. Axis.prototype.contain = function (coord) {
  59. var extent = this._extent;
  60. var min = Math.min(extent[0], extent[1]);
  61. var max = Math.max(extent[0], extent[1]);
  62. return coord >= min && coord <= max;
  63. };
  64. /**
  65. * If axis extent contain given data
  66. */
  67. Axis.prototype.containData = function (data) {
  68. return this.scale.contain(data);
  69. };
  70. /**
  71. * Get coord extent.
  72. */
  73. Axis.prototype.getExtent = function () {
  74. return this._extent.slice();
  75. };
  76. /**
  77. * Get precision used for formatting
  78. */
  79. Axis.prototype.getPixelPrecision = function (dataExtent) {
  80. return getPixelPrecision(dataExtent || this.scale.getExtent(), this._extent);
  81. };
  82. /**
  83. * Set coord extent
  84. */
  85. Axis.prototype.setExtent = function (start, end) {
  86. var extent = this._extent;
  87. extent[0] = start;
  88. extent[1] = end;
  89. };
  90. /**
  91. * Convert data to coord. Data is the rank if it has an ordinal scale
  92. */
  93. Axis.prototype.dataToCoord = function (data, clamp) {
  94. var extent = this._extent;
  95. var scale = this.scale;
  96. data = scale.normalize(data);
  97. if (this.onBand && scale.type === 'ordinal') {
  98. extent = extent.slice();
  99. fixExtentWithBands(extent, scale.count());
  100. }
  101. return linearMap(data, NORMALIZED_EXTENT, extent, clamp);
  102. };
  103. /**
  104. * Convert coord to data. Data is the rank if it has an ordinal scale
  105. */
  106. Axis.prototype.coordToData = function (coord, clamp) {
  107. var extent = this._extent;
  108. var scale = this.scale;
  109. if (this.onBand && scale.type === 'ordinal') {
  110. extent = extent.slice();
  111. fixExtentWithBands(extent, scale.count());
  112. }
  113. var t = linearMap(coord, extent, NORMALIZED_EXTENT, clamp);
  114. return this.scale.scale(t);
  115. };
  116. /**
  117. * Convert pixel point to data in axis
  118. */
  119. Axis.prototype.pointToData = function (point, clamp) {
  120. // Should be implemented in derived class if necessary.
  121. return;
  122. };
  123. /**
  124. * Different from `zrUtil.map(axis.getTicks(), axis.dataToCoord, axis)`,
  125. * `axis.getTicksCoords` considers `onBand`, which is used by
  126. * `boundaryGap:true` of category axis and splitLine and splitArea.
  127. * @param opt.tickModel default: axis.model.getModel('axisTick')
  128. * @param opt.clamp If `true`, the first and the last
  129. * tick must be at the axis end points. Otherwise, clip ticks
  130. * that outside the axis extent.
  131. */
  132. Axis.prototype.getTicksCoords = function (opt) {
  133. opt = opt || {};
  134. var tickModel = opt.tickModel || this.getTickModel();
  135. var result = createAxisTicks(this, tickModel);
  136. var ticks = result.ticks;
  137. var ticksCoords = map(ticks, function (tickVal) {
  138. return {
  139. coord: this.dataToCoord(this.scale.type === 'ordinal' ? this.scale.getRawOrdinalNumber(tickVal) : tickVal),
  140. tickValue: tickVal
  141. };
  142. }, this);
  143. var alignWithLabel = tickModel.get('alignWithLabel');
  144. fixOnBandTicksCoords(this, ticksCoords, alignWithLabel, opt.clamp);
  145. return ticksCoords;
  146. };
  147. Axis.prototype.getMinorTicksCoords = function () {
  148. if (this.scale.type === 'ordinal') {
  149. // Category axis doesn't support minor ticks
  150. return [];
  151. }
  152. var minorTickModel = this.model.getModel('minorTick');
  153. var splitNumber = minorTickModel.get('splitNumber');
  154. // Protection.
  155. if (!(splitNumber > 0 && splitNumber < 100)) {
  156. splitNumber = 5;
  157. }
  158. var minorTicks = this.scale.getMinorTicks(splitNumber);
  159. var minorTicksCoords = map(minorTicks, function (minorTicksGroup) {
  160. return map(minorTicksGroup, function (minorTick) {
  161. return {
  162. coord: this.dataToCoord(minorTick),
  163. tickValue: minorTick
  164. };
  165. }, this);
  166. }, this);
  167. return minorTicksCoords;
  168. };
  169. Axis.prototype.getViewLabels = function () {
  170. return createAxisLabels(this).labels;
  171. };
  172. Axis.prototype.getLabelModel = function () {
  173. return this.model.getModel('axisLabel');
  174. };
  175. /**
  176. * Notice here we only get the default tick model. For splitLine
  177. * or splitArea, we should pass the splitLineModel or splitAreaModel
  178. * manually when calling `getTicksCoords`.
  179. * In GL, this method may be overridden to:
  180. * `axisModel.getModel('axisTick', grid3DModel.getModel('axisTick'));`
  181. */
  182. Axis.prototype.getTickModel = function () {
  183. return this.model.getModel('axisTick');
  184. };
  185. /**
  186. * Get width of band
  187. */
  188. Axis.prototype.getBandWidth = function () {
  189. var axisExtent = this._extent;
  190. var dataExtent = this.scale.getExtent();
  191. var len = dataExtent[1] - dataExtent[0] + (this.onBand ? 1 : 0);
  192. // Fix #2728, avoid NaN when only one data.
  193. len === 0 && (len = 1);
  194. var size = Math.abs(axisExtent[1] - axisExtent[0]);
  195. return Math.abs(size) / len;
  196. };
  197. /**
  198. * Only be called in category axis.
  199. * Can be overridden, consider other axes like in 3D.
  200. * @return Auto interval for cateogry axis tick and label
  201. */
  202. Axis.prototype.calculateCategoryInterval = function () {
  203. return calculateCategoryInterval(this);
  204. };
  205. return Axis;
  206. }();
  207. function fixExtentWithBands(extent, nTick) {
  208. var size = extent[1] - extent[0];
  209. var len = nTick;
  210. var margin = size / len / 2;
  211. extent[0] += margin;
  212. extent[1] -= margin;
  213. }
  214. // If axis has labels [1, 2, 3, 4]. Bands on the axis are
  215. // |---1---|---2---|---3---|---4---|.
  216. // So the displayed ticks and splitLine/splitArea should between
  217. // each data item, otherwise cause misleading (e.g., split tow bars
  218. // of a single data item when there are two bar series).
  219. // Also consider if tickCategoryInterval > 0 and onBand, ticks and
  220. // splitLine/spliteArea should layout appropriately corresponding
  221. // to displayed labels. (So we should not use `getBandWidth` in this
  222. // case).
  223. function fixOnBandTicksCoords(axis, ticksCoords, alignWithLabel, clamp) {
  224. var ticksLen = ticksCoords.length;
  225. if (!axis.onBand || alignWithLabel || !ticksLen) {
  226. return;
  227. }
  228. var axisExtent = axis.getExtent();
  229. var last;
  230. var diffSize;
  231. if (ticksLen === 1) {
  232. ticksCoords[0].coord = axisExtent[0];
  233. last = ticksCoords[1] = {
  234. coord: axisExtent[1]
  235. };
  236. } else {
  237. var crossLen = ticksCoords[ticksLen - 1].tickValue - ticksCoords[0].tickValue;
  238. var shift_1 = (ticksCoords[ticksLen - 1].coord - ticksCoords[0].coord) / crossLen;
  239. each(ticksCoords, function (ticksItem) {
  240. ticksItem.coord -= shift_1 / 2;
  241. });
  242. var dataExtent = axis.scale.getExtent();
  243. diffSize = 1 + dataExtent[1] - ticksCoords[ticksLen - 1].tickValue;
  244. last = {
  245. coord: ticksCoords[ticksLen - 1].coord + shift_1 * diffSize
  246. };
  247. ticksCoords.push(last);
  248. }
  249. var inverse = axisExtent[0] > axisExtent[1];
  250. // Handling clamp.
  251. if (littleThan(ticksCoords[0].coord, axisExtent[0])) {
  252. clamp ? ticksCoords[0].coord = axisExtent[0] : ticksCoords.shift();
  253. }
  254. if (clamp && littleThan(axisExtent[0], ticksCoords[0].coord)) {
  255. ticksCoords.unshift({
  256. coord: axisExtent[0]
  257. });
  258. }
  259. if (littleThan(axisExtent[1], last.coord)) {
  260. clamp ? last.coord = axisExtent[1] : ticksCoords.pop();
  261. }
  262. if (clamp && littleThan(last.coord, axisExtent[1])) {
  263. ticksCoords.push({
  264. coord: axisExtent[1]
  265. });
  266. }
  267. function littleThan(a, b) {
  268. // Avoid rounding error cause calculated tick coord different with extent.
  269. // It may cause an extra unnecessary tick added.
  270. a = round(a);
  271. b = round(b);
  272. return inverse ? a > b : a < b;
  273. }
  274. }
  275. export default Axis;