axisNiceTicks.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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 { assert, noop } from 'zrender/lib/core/util.js';
  41. import { ensureValidSplitNumber, getIntervalPrecision, intervalScaleEnsureValidExtent, isIntervalScale, isLogScale, isTimeScale } from '../scale/helper.js';
  42. import { mathCeil, mathFloor, mathMax, nice, quantity, round } from '../util/number.js';
  43. import { updateIntervalOrLogScaleForNiceOrAligned } from './axisHelper.js';
  44. import { calcNiceForTimeScale } from '../scale/Time.js';
  45. import { adoptScaleExtentKindMapping, adoptScaleRawExtentInfoAndPrepare } from './scaleRawExtentInfo.js';
  46. import { getScaleLinearSpanEffective } from '../scale/scaleMapper.js';
  47. // ------ START: LinearIntervalScaleStub Nice ------
  48. function calcNiceForIntervalOrLogScale(scale, opt) {
  49. // [CAVEAT]: If updating this impl, need to sync it to `axisAlignTicks.ts`.
  50. var isTargetLogScale = isLogScale(scale);
  51. var intervalStub = isTargetLogScale ? scale.intervalStub : scale;
  52. var fixMinMax = opt.fixMinMax || [];
  53. var oldOutermostExtent = isTargetLogScale ? scale.getExtent() : null;
  54. var oldIntervalExtent = intervalStub.getExtent();
  55. var newIntervalExtent = intervalScaleEnsureValidExtent(oldIntervalExtent, fixMinMax, opt.rawExtentResult);
  56. intervalStub.setExtent(newIntervalExtent[0], newIntervalExtent[1]);
  57. newIntervalExtent = intervalStub.getExtent();
  58. var config = isTargetLogScale ? logScaleCalcNiceTicks(intervalStub, opt) : intervalScaleCalcNiceTicks(intervalStub, opt);
  59. var autoIntervalPrecision = config.intervalPrecision;
  60. var autoInterval = config.interval;
  61. // When auto calculated interval is not preferable, users are allowed to explicity specify
  62. // `interval`, `min`, `max` to customize the axis. A typical case is, in angle axis with angle
  63. // 0 - 360, where the internally calculated interval is not 60-based.
  64. // NOTICE:
  65. // - In `xxxAxis.type: 'log'`, ec option `xxxAxis.interval` requires a logarithm-applied
  66. // value rather than a value in the raw scale.
  67. // - Follow the historical behavior:
  68. // - even `interval` is specified, the scale extent is still expanded based on the auto-calculated
  69. // interval.
  70. // - No validation to the specified `interval`.
  71. var userInterval = opt.userInterval;
  72. if (userInterval != null) {
  73. config.interval = userInterval;
  74. config.intervalPrecision = getIntervalPrecision(userInterval);
  75. }
  76. if (!fixMinMax[0]) {
  77. newIntervalExtent[0] = round(mathFloor(newIntervalExtent[0] / autoInterval) * autoInterval, autoIntervalPrecision);
  78. }
  79. if (!fixMinMax[1]) {
  80. newIntervalExtent[1] = round(mathCeil(newIntervalExtent[1] / autoInterval) * autoInterval, autoIntervalPrecision);
  81. }
  82. if (userInterval != null) {
  83. // Historical behavior.
  84. config.niceExtent = newIntervalExtent.slice();
  85. }
  86. updateIntervalOrLogScaleForNiceOrAligned(scale, fixMinMax, oldIntervalExtent, newIntervalExtent, oldOutermostExtent, config);
  87. }
  88. // ------ END: LinearIntervalScaleStub Nice ------
  89. // ------ START: IntervalScale Nice ------
  90. function intervalScaleCalcNiceTicks(scale, opt) {
  91. var splitNumber = ensureValidSplitNumber(opt.splitNumber, 5);
  92. // Use the span in the innermost linear space to calculate nice ticks.
  93. var span = getScaleLinearSpanEffective(scale);
  94. if (process.env.NODE_ENV !== 'production') {
  95. assert(isFinite(span) && span > 0); // It should have been ensured by `intervalScaleEnsureValidExtent`.
  96. }
  97. var minInterval = opt.minInterval;
  98. var maxInterval = opt.maxInterval;
  99. var interval = nice(span / splitNumber, true);
  100. if (minInterval != null && interval < minInterval) {
  101. interval = minInterval;
  102. }
  103. if (maxInterval != null && interval > maxInterval) {
  104. interval = maxInterval;
  105. }
  106. var intervalPrecision = getIntervalPrecision(interval);
  107. var extent = scale.getExtent();
  108. // By design, the `niceExtent` is inside the original extent
  109. var niceExtent = [round(mathCeil(extent[0] / interval) * interval, intervalPrecision), round(mathFloor(extent[1] / interval) * interval, intervalPrecision)];
  110. return {
  111. interval: interval,
  112. intervalPrecision: intervalPrecision,
  113. niceExtent: niceExtent
  114. };
  115. }
  116. ;
  117. // ------ END: IntervalScale Nice ------
  118. // ------ START: LogScale Nice ------
  119. function logScaleCalcNiceTicks(intervalStub, opt) {
  120. // [CAVEAT]: If updating this impl, need to sync it to `axisAlignTicks.ts`.
  121. var splitNumber = ensureValidSplitNumber(opt.splitNumber, 10);
  122. // Find nice ticks in the "logarithmic space". Notice that "logarithmic space" is a middle space
  123. // rather than the innermost linear space when axis breaks exist.
  124. var intervalExtent = intervalStub.getExtent();
  125. // But use the span in the innermost linear space to calculate nice ticks.
  126. var span = getScaleLinearSpanEffective(intervalStub);
  127. if (process.env.NODE_ENV !== 'production') {
  128. assert(isFinite(span) && span > 0); // It should be ensured by `intervalScaleEnsureValidExtent`.
  129. }
  130. // Interval should be integer
  131. var interval = mathMax(quantity(span), 1);
  132. var err = splitNumber / span * interval;
  133. // Filter ticks to get closer to the desired count.
  134. if (err <= 0.5) {
  135. // TODO: support other bases other than 10?
  136. interval *= 10;
  137. }
  138. var intervalPrecision = getIntervalPrecision(interval);
  139. // For LogScale, we use a `niceExtent` in the "logarithmic space" rather than
  140. // the original "pow space", because it is used in `intervalStub.getTicks()` thereafter.
  141. var niceExtent = [round(mathCeil(intervalExtent[0] / interval) * interval, intervalPrecision), round(mathFloor(intervalExtent[1] / interval) * interval, intervalPrecision)];
  142. return {
  143. intervalPrecision: intervalPrecision,
  144. interval: interval,
  145. niceExtent: niceExtent
  146. };
  147. }
  148. ;
  149. /**
  150. * NOTE: See the summary of the process of extent determination in the comment of `scaleMapper.setExtent`.
  151. *
  152. * Calculate a "nice" extent and "nice" ticks configs based on the current scale extent and ec options.
  153. * scale extent will be modified, and config may be set to the scale.
  154. *
  155. * @see SCALE_EXTENT_CONSTRUCTION for the full processing flow.
  156. */
  157. export function scaleCalcNice(axisLike) {
  158. var scale = axisLike.scale;
  159. var model = axisLike.model;
  160. var axis = model.axis;
  161. var ecModel = model.ecModel;
  162. if (process.env.NODE_ENV !== 'production') {
  163. assert(axis && ecModel);
  164. }
  165. scaleCalcNice2(scale, model, axis, ecModel, null);
  166. }
  167. /**
  168. * @see SCALE_EXTENT_CONSTRUCTION for the full processing flow.
  169. */
  170. export function scaleCalcNice2(scale, model,
  171. // Some call from external source, such as echarts-gl, may have no `axis` and `ecModel`,
  172. // but has `externalDataExtent`.
  173. axis, ecModel, externalDataExtent) {
  174. var rawExtentResult = adoptScaleRawExtentInfoAndPrepare(scale, model, ecModel, axis, externalDataExtent);
  175. var isIntervalOrTime = isIntervalScale(scale) || isTimeScale(scale);
  176. scaleCalcNiceDirectly(scale, {
  177. splitNumber: model.get('splitNumber'),
  178. fixMinMax: rawExtentResult.fixMM,
  179. userInterval: model.get('interval'),
  180. minInterval: isIntervalOrTime ? model.get('minInterval') : null,
  181. maxInterval: isIntervalOrTime ? model.get('maxInterval') : null,
  182. rawExtentResult: rawExtentResult
  183. });
  184. if (axis && ecModel) {
  185. adoptScaleExtentKindMapping(axis, scale, rawExtentResult, ecModel);
  186. }
  187. if (process.env.NODE_ENV !== 'production') {
  188. scale.freeze();
  189. }
  190. }
  191. export function scaleCalcNiceDirectly(scale, opt) {
  192. scaleCalcNiceMethods[scale.type](scale, opt);
  193. }
  194. var scaleCalcNiceMethods = {
  195. interval: calcNiceForIntervalOrLogScale,
  196. log: calcNiceForIntervalOrLogScale,
  197. time: calcNiceForTimeScale,
  198. ordinal: noop
  199. };
  200. // ------ END: scaleCalcNice Entry ------