axisHelper.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  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 * as zrUtil from 'zrender/lib/core/util.js';
  41. import OrdinalScale from '../scale/Ordinal.js';
  42. import IntervalScale from '../scale/Interval.js';
  43. import Scale from '../scale/Scale.js';
  44. import TimeScale from '../scale/Time.js';
  45. import LogScale from '../scale/Log.js';
  46. import { AXIS_TYPES } from './axisCommonTypes.js';
  47. import { getStackedDimension } from '../data/helper/dataStackHelper.js';
  48. import { parseTimeAxisLabelFormatter } from '../util/time.js';
  49. import { getScaleBreakHelper } from '../scale/break.js';
  50. import { error } from '../util/log.js';
  51. import { extentDiffers, isLogScale, isOrdinalScale } from '../scale/helper.js';
  52. import { initExtentForUnion, isValidBoundsForExtent, makeInner } from '../util/model.js';
  53. import { getScaleExtentForMappingUnsafe, SCALE_EXTENT_KIND_EFFECTIVE, SCALE_MAPPER_DEPTH_OUT_OF_BREAK } from '../scale/scaleMapper.js';
  54. import ComponentModel from '../model/Component.js';
  55. var axisInner = makeInner();
  56. export function determineAxisType(model) {
  57. var type = model.get('type');
  58. if (
  59. // In ec option, `xxxAxis.type` may be undefined.
  60. type == null
  61. // PENDING: Theoretically, a customized `Scale` is probably impossible, since
  62. // the interface of `Scale` does not guarantee stability. But we still literally
  63. // support it for backward compat, though type incorrect.
  64. || !zrUtil.hasOwn(AXIS_TYPES, type) && !Scale.getClass(type)) {
  65. type = 'value';
  66. }
  67. return type;
  68. }
  69. export function createScaleByModel(model, type, coordSysSupportAxisBreaks) {
  70. var breakHelper = getScaleBreakHelper();
  71. var breakOption;
  72. if (breakHelper) {
  73. breakOption = retrieveAxisBreaksOption(model, type, coordSysSupportAxisBreaks);
  74. }
  75. switch (type) {
  76. case 'category':
  77. return new OrdinalScale({
  78. ordinalMeta: model.getOrdinalMeta ? model.getOrdinalMeta() : model.getCategories(),
  79. extent: initExtentForUnion()
  80. });
  81. case 'time':
  82. return new TimeScale({
  83. locale: model.ecModel.getLocaleModel(),
  84. useUTC: model.ecModel.get('useUTC'),
  85. breakOption: breakOption
  86. });
  87. case 'log':
  88. // See also #3749
  89. return new LogScale({
  90. logBase: model.get('logBase'),
  91. breakOption: breakOption
  92. });
  93. case 'value':
  94. return new IntervalScale({
  95. breakOption: breakOption
  96. });
  97. default:
  98. // case others.
  99. return new (Scale.getClass(type) || IntervalScale)({});
  100. }
  101. }
  102. /**
  103. * Check if the axis cross a specific value.
  104. */
  105. export function getScaleValuePositionKind(scale, value, considerMappingExtent) {
  106. var dataExtent = considerMappingExtent ? getScaleExtentForMappingUnsafe(scale, null) : scale.getExtentUnsafe(SCALE_EXTENT_KIND_EFFECTIVE, null);
  107. var min = dataExtent[0];
  108. var max = dataExtent[1];
  109. return !isValidBoundsForExtent(min, max) ? SCALE_VALUE_POSITION_KIND_OUTSIDE : min === value || max === value ? SCALE_VALUE_POSITION_KIND_EDGE : min < value && max > value ? SCALE_VALUE_POSITION_KIND_INSIDE : SCALE_VALUE_POSITION_KIND_OUTSIDE;
  110. }
  111. export var SCALE_VALUE_POSITION_KIND_INSIDE = 1;
  112. export var SCALE_VALUE_POSITION_KIND_EDGE = 2;
  113. export var SCALE_VALUE_POSITION_KIND_OUTSIDE = 3;
  114. export function discourageOnAxisZero(axis) {
  115. axisInner(axis).noOnMyZero = true;
  116. }
  117. /**
  118. * `true`: Prevent orthoganal axes from positioning at the zero point of this axis.
  119. */
  120. export function isOnAxisZeroDiscouraged(axis) {
  121. return axisInner(axis).noOnMyZero;
  122. }
  123. /**
  124. * @param axis
  125. * @return Label formatter function.
  126. * param: {number} tickValue,
  127. * param: {number} idx, the index in all ticks.
  128. * If category axis, this param is not required.
  129. * return: {string} label string.
  130. */
  131. export function makeLabelFormatter(axis) {
  132. var labelFormatter = axis.getLabelModel().get('formatter');
  133. if (axis.type === 'time') {
  134. var parsed_1 = parseTimeAxisLabelFormatter(labelFormatter);
  135. return function (tick, idx) {
  136. return axis.scale.getFormattedLabel(tick, idx, parsed_1);
  137. };
  138. } else if (zrUtil.isString(labelFormatter)) {
  139. return function (tick) {
  140. // For category axis, get raw value; for numeric axis,
  141. // get formatted label like '1,333,444'.
  142. var label = axis.scale.getLabel(tick);
  143. var text = labelFormatter.replace('{value}', label != null ? label : '');
  144. return text;
  145. };
  146. } else if (zrUtil.isFunction(labelFormatter)) {
  147. if (axis.type === 'category') {
  148. return function (tick, idx) {
  149. // The original intention of `idx` is "the index of the tick in all ticks".
  150. // But the previous implementation of category axis do not consider the
  151. // `axisLabel.interval`, which cause that, for example, the `interval` is
  152. // `1`, then the ticks "name5", "name7", "name9" are displayed, where the
  153. // corresponding `idx` are `0`, `2`, `4`, but not `0`, `1`, `2`. So we keep
  154. // the definition here for back compatibility.
  155. return labelFormatter(getAxisRawValue(axis, tick), tick.value - axis.scale.getExtent()[0], null // Using `null` just for backward compat.
  156. );
  157. };
  158. }
  159. var scaleBreakHelper_1 = getScaleBreakHelper();
  160. return function (tick, idx) {
  161. // Using `null` just for backward compat. It's been found that in the `test/axis-customTicks.html`,
  162. // there is a formatter `function (value, index, revers = true) { ... }`. Although the third param
  163. // `revers` is incorrect and always `null`, changing it might introduce a breaking change.
  164. var extra = null;
  165. if (scaleBreakHelper_1) {
  166. extra = scaleBreakHelper_1.makeAxisLabelFormatterParamBreak(extra, tick["break"]);
  167. }
  168. return labelFormatter(getAxisRawValue(axis, tick), idx, extra);
  169. };
  170. } else {
  171. return function (tick) {
  172. return axis.scale.getLabel(tick);
  173. };
  174. }
  175. }
  176. export function getAxisRawValue(axis, tick) {
  177. // In category axis with data zoom, tick is not the original
  178. // index of axis.data. So tick should not be exposed to user
  179. // in category axis.
  180. var scale = axis.scale;
  181. return isOrdinalScale(scale) ? scale.getLabel(tick) : tick.value;
  182. }
  183. /**
  184. * @param model axisLabelModel or axisTickModel
  185. */
  186. export function getOptionCategoryInterval(model) {
  187. var interval = model.get('interval');
  188. return interval == null ? 'auto' : interval;
  189. }
  190. /**
  191. * Set `categoryInterval` as 0 implicitly indicates that
  192. * show all labels regardless of overlap.
  193. * @param {Object} axis axisModel.axis
  194. */
  195. export function shouldShowAllLabels(axis) {
  196. return axis.type === 'category' && getOptionCategoryInterval(axis.getLabelModel()) === 0;
  197. }
  198. export function getDataDimensionsOnAxis(data, axisDim) {
  199. // Remove duplicated dat dimensions caused by `getStackedDimension`.
  200. var dataDimMap = {};
  201. // Currently `mapDimensionsAll` will contain stack result dimension ('__\0ecstackresult').
  202. // PENDING: is it reasonable? Do we need to remove the original dim from "coord dim" since
  203. // there has been stacked result dim?
  204. zrUtil.each(data.mapDimensionsAll(axisDim), function (dataDim) {
  205. // For example, the extent of the original dimension
  206. // is [0.1, 0.5], the extent of the `stackResultDimension`
  207. // is [7, 9], the final extent should NOT include [0.1, 0.5],
  208. // because there is no graphic corresponding to [0.1, 0.5].
  209. // See the case in `test/area-stack.html` `main1`, where area line
  210. // stack needs `yAxis` not start from 0.
  211. dataDimMap[getStackedDimension(data, dataDim)] = true;
  212. });
  213. return zrUtil.keys(dataDimMap);
  214. }
  215. export function isNameLocationCenter(nameLocation) {
  216. return nameLocation === 'middle' || nameLocation === 'center';
  217. }
  218. export function shouldAxisShow(axisModel) {
  219. return axisModel.getShallow('show');
  220. }
  221. export function retrieveAxisBreaksOption(model, axisType, coordSysSupportAxisBreaks) {
  222. var option = model.get('breaks', true);
  223. if (option != null) {
  224. if (!getScaleBreakHelper()) {
  225. if (process.env.NODE_ENV !== 'production') {
  226. error('Must `import {AxisBreak} from "echarts/features.js"; use(AxisBreak);` first if using breaks option.');
  227. }
  228. return undefined;
  229. }
  230. if (!coordSysSupportAxisBreaks || !isAxisTypeSupportAxisBreak(axisType)) {
  231. if (process.env.NODE_ENV !== 'production') {
  232. // Users have provided `breaks` in ec option but not supported.
  233. var axisInfo = model instanceof ComponentModel ? " " + model.type + "[" + model.componentIndex + "]" : '';
  234. error("Axis" + axisInfo + " does not support break.");
  235. }
  236. return undefined;
  237. }
  238. return option;
  239. }
  240. }
  241. function isAxisTypeSupportAxisBreak(axisType) {
  242. return axisType !== 'category';
  243. }
  244. export function updateIntervalOrLogScaleForNiceOrAligned(scale, fixMinMax, oldIntervalExtent, newIntervalExtent, oldOutermostExtent, cfg) {
  245. var isTargetLogScale = isLogScale(scale);
  246. var intervalStub = isTargetLogScale ? scale.intervalStub : scale;
  247. intervalStub.setExtent(newIntervalExtent[0], newIntervalExtent[1]);
  248. if (isTargetLogScale) {
  249. // Sync intervalStub extent to the outermost extent (i.e., `powStub` for `LogScale`).
  250. var powStub = scale.powStub;
  251. var opt = {
  252. depth: SCALE_MAPPER_DEPTH_OUT_OF_BREAK
  253. };
  254. var minPow = scale.transformOut(newIntervalExtent[0], opt);
  255. var maxPow = scale.transformOut(newIntervalExtent[1], opt);
  256. // Log transform is probably not inversible by rounding error, which causes min/max tick may be
  257. // displayed as `5.999999999999999` unexpectedly when min/max are required to be fixed (specified
  258. // by users or by dataZoom). Therefore we set `powStub` with respect to `oldOutermostExtent` if
  259. // interval extent is not changed. But `intervalStub` should not be inversely changed by this
  260. // handling, otherwise its monotonicity between `niceExtent` and `extent` may be broken and cause
  261. // unexpected ticks generation.
  262. var extentChanged = extentDiffers(oldIntervalExtent, newIntervalExtent);
  263. // NOTE: extent may still be changed even when min/max are required to be fixed,
  264. // e.g., by `intervalScaleEnsureValidExtent`.
  265. if (fixMinMax[0] && !extentChanged[0]) {
  266. minPow = oldOutermostExtent[0];
  267. }
  268. if (fixMinMax[1] && !extentChanged[1]) {
  269. maxPow = oldOutermostExtent[1];
  270. }
  271. powStub.setExtent(minPow, maxPow);
  272. }
  273. intervalStub.setConfig(cfg);
  274. }
  275. export function getTickValueOutermost(scale, tick) {
  276. return isOrdinalScale(scale) ? scale.getRawOrdinalNumber(tick.value) : tick.value;
  277. }
  278. export function isAxisOnBand(scale, axisModel) {
  279. return isOrdinalScale(scale) && !!axisModel.get('boundaryGap');
  280. }