scaleRawExtentInfo.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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, isArray, eqNaN, isFunction } from 'zrender/lib/core/util.js';
  41. import { parsePercent } from 'zrender/lib/contain/text.js';
  42. var ScaleRawExtentInfo = /** @class */function () {
  43. function ScaleRawExtentInfo(scale, model,
  44. // Usually: data extent from all series on this axis.
  45. originalExtent) {
  46. this._prepareParams(scale, model, originalExtent);
  47. }
  48. /**
  49. * Parameters depending on outside (like model, user callback)
  50. * are prepared and fixed here.
  51. */
  52. ScaleRawExtentInfo.prototype._prepareParams = function (scale, model,
  53. // Usually: data extent from all series on this axis.
  54. dataExtent) {
  55. if (dataExtent[1] < dataExtent[0]) {
  56. dataExtent = [NaN, NaN];
  57. }
  58. this._dataMin = dataExtent[0];
  59. this._dataMax = dataExtent[1];
  60. var isOrdinal = this._isOrdinal = scale.type === 'ordinal';
  61. this._needCrossZero = scale.type === 'interval' && model.getNeedCrossZero && model.getNeedCrossZero();
  62. var axisMinValue = model.get('min', true);
  63. if (axisMinValue == null) {
  64. axisMinValue = model.get('startValue', true);
  65. }
  66. var modelMinRaw = this._modelMinRaw = axisMinValue;
  67. if (isFunction(modelMinRaw)) {
  68. // This callback always provides users the full data extent (before data is filtered).
  69. this._modelMinNum = parseAxisModelMinMax(scale, modelMinRaw({
  70. min: dataExtent[0],
  71. max: dataExtent[1]
  72. }));
  73. } else if (modelMinRaw !== 'dataMin') {
  74. this._modelMinNum = parseAxisModelMinMax(scale, modelMinRaw);
  75. }
  76. var modelMaxRaw = this._modelMaxRaw = model.get('max', true);
  77. if (isFunction(modelMaxRaw)) {
  78. // This callback always provides users the full data extent (before data is filtered).
  79. this._modelMaxNum = parseAxisModelMinMax(scale, modelMaxRaw({
  80. min: dataExtent[0],
  81. max: dataExtent[1]
  82. }));
  83. } else if (modelMaxRaw !== 'dataMax') {
  84. this._modelMaxNum = parseAxisModelMinMax(scale, modelMaxRaw);
  85. }
  86. if (isOrdinal) {
  87. // FIXME: there is a flaw here: if there is no "block" data processor like `dataZoom`,
  88. // and progressive rendering is using, here the category result might just only contain
  89. // the processed chunk rather than the entire result.
  90. this._axisDataLen = model.getCategories().length;
  91. } else {
  92. var boundaryGap = model.get('boundaryGap');
  93. var boundaryGapArr = isArray(boundaryGap) ? boundaryGap : [boundaryGap || 0, boundaryGap || 0];
  94. if (typeof boundaryGapArr[0] === 'boolean' || typeof boundaryGapArr[1] === 'boolean') {
  95. if (process.env.NODE_ENV !== 'production') {
  96. console.warn('Boolean type for boundaryGap is only ' + 'allowed for ordinal axis. Please use string in ' + 'percentage instead, e.g., "20%". Currently, ' + 'boundaryGap is set to be 0.');
  97. }
  98. this._boundaryGapInner = [0, 0];
  99. } else {
  100. this._boundaryGapInner = [parsePercent(boundaryGapArr[0], 1), parsePercent(boundaryGapArr[1], 1)];
  101. }
  102. }
  103. };
  104. /**
  105. * Calculate extent by prepared parameters.
  106. * This method has no external dependency and can be called duplicatedly,
  107. * getting the same result.
  108. * If parameters changed, should call this method to recalcuate.
  109. */
  110. ScaleRawExtentInfo.prototype.calculate = function () {
  111. // Notice: When min/max is not set (that is, when there are null/undefined,
  112. // which is the most common case), these cases should be ensured:
  113. // (1) For 'ordinal', show all axis.data.
  114. // (2) For others:
  115. // + `boundaryGap` is applied (if min/max set, boundaryGap is
  116. // disabled).
  117. // + If `needCrossZero`, min/max should be zero, otherwise, min/max should
  118. // be the result that originalExtent enlarged by boundaryGap.
  119. // (3) If no data, it should be ensured that `scale.setBlank` is set.
  120. var isOrdinal = this._isOrdinal;
  121. var dataMin = this._dataMin;
  122. var dataMax = this._dataMax;
  123. var axisDataLen = this._axisDataLen;
  124. var boundaryGapInner = this._boundaryGapInner;
  125. var span = !isOrdinal ? dataMax - dataMin || Math.abs(dataMin) : null;
  126. // Currently if a `'value'` axis model min is specified as 'dataMin'/'dataMax',
  127. // `boundaryGap` will not be used. It's the different from specifying as `null`/`undefined`.
  128. var min = this._modelMinRaw === 'dataMin' ? dataMin : this._modelMinNum;
  129. var max = this._modelMaxRaw === 'dataMax' ? dataMax : this._modelMaxNum;
  130. // If `_modelMinNum`/`_modelMaxNum` is `null`/`undefined`, should not be fixed.
  131. var minFixed = min != null;
  132. var maxFixed = max != null;
  133. if (min == null) {
  134. min = isOrdinal ? axisDataLen ? 0 : NaN : dataMin - boundaryGapInner[0] * span;
  135. }
  136. if (max == null) {
  137. max = isOrdinal ? axisDataLen ? axisDataLen - 1 : NaN : dataMax + boundaryGapInner[1] * span;
  138. }
  139. (min == null || !isFinite(min)) && (min = NaN);
  140. (max == null || !isFinite(max)) && (max = NaN);
  141. var isBlank = eqNaN(min) || eqNaN(max) || isOrdinal && !axisDataLen;
  142. // If data extent modified, need to recalculated to ensure cross zero.
  143. if (this._needCrossZero) {
  144. // Axis is over zero and min is not set
  145. if (min > 0 && max > 0 && !minFixed) {
  146. min = 0;
  147. // minFixed = true;
  148. }
  149. // Axis is under zero and max is not set
  150. if (min < 0 && max < 0 && !maxFixed) {
  151. max = 0;
  152. // maxFixed = true;
  153. }
  154. // PENDING:
  155. // When `needCrossZero` and all data is positive/negative, should it be ensured
  156. // that the results processed by boundaryGap are positive/negative?
  157. // If so, here `minFixed`/`maxFixed` need to be set.
  158. }
  159. var determinedMin = this._determinedMin;
  160. var determinedMax = this._determinedMax;
  161. if (determinedMin != null) {
  162. min = determinedMin;
  163. minFixed = true;
  164. }
  165. if (determinedMax != null) {
  166. max = determinedMax;
  167. maxFixed = true;
  168. }
  169. // Ensure min/max be finite number or NaN here. (not to be null/undefined)
  170. // `NaN` means min/max axis is blank.
  171. return {
  172. min: min,
  173. max: max,
  174. minFixed: minFixed,
  175. maxFixed: maxFixed,
  176. isBlank: isBlank
  177. };
  178. };
  179. ScaleRawExtentInfo.prototype.modifyDataMinMax = function (minMaxName, val) {
  180. if (process.env.NODE_ENV !== 'production') {
  181. assert(!this.frozen);
  182. }
  183. this[DATA_MIN_MAX_ATTR[minMaxName]] = val;
  184. };
  185. ScaleRawExtentInfo.prototype.setDeterminedMinMax = function (minMaxName, val) {
  186. var attr = DETERMINED_MIN_MAX_ATTR[minMaxName];
  187. if (process.env.NODE_ENV !== 'production') {
  188. assert(!this.frozen
  189. // Earse them usually means logic flaw.
  190. && this[attr] == null);
  191. }
  192. this[attr] = val;
  193. };
  194. ScaleRawExtentInfo.prototype.freeze = function () {
  195. // @ts-ignore
  196. this.frozen = true;
  197. };
  198. return ScaleRawExtentInfo;
  199. }();
  200. export { ScaleRawExtentInfo };
  201. var DETERMINED_MIN_MAX_ATTR = {
  202. min: '_determinedMin',
  203. max: '_determinedMax'
  204. };
  205. var DATA_MIN_MAX_ATTR = {
  206. min: '_dataMin',
  207. max: '_dataMax'
  208. };
  209. /**
  210. * Get scale min max and related info only depends on model settings.
  211. * This method can be called after coordinate system created.
  212. * For example, in data processing stage.
  213. *
  214. * Scale extent info probably be required multiple times during a workflow.
  215. * For example:
  216. * (1) `dataZoom` depends it to get the axis extent in "100%" state.
  217. * (2) `processor/extentCalculator` depends it to make sure whether axis extent is specified.
  218. * (3) `coordSys.update` use it to finally decide the scale extent.
  219. * But the callback of `min`/`max` should not be called multiple times.
  220. * The code below should not be implemented repeatedly either.
  221. * So we cache the result in the scale instance, which will be recreated at the beginning
  222. * of the workflow (because `scale` instance will be recreated each round of the workflow).
  223. */
  224. export function ensureScaleRawExtentInfo(scale, model,
  225. // Usually: data extent from all series on this axis.
  226. originalExtent) {
  227. // Do not permit to recreate.
  228. var rawExtentInfo = scale.rawExtentInfo;
  229. if (rawExtentInfo) {
  230. return rawExtentInfo;
  231. }
  232. rawExtentInfo = new ScaleRawExtentInfo(scale, model, originalExtent);
  233. // @ts-ignore
  234. scale.rawExtentInfo = rawExtentInfo;
  235. return rawExtentInfo;
  236. }
  237. export function parseAxisModelMinMax(scale, minMax) {
  238. return minMax == null ? null : eqNaN(minMax) ? NaN : scale.parse(minMax);
  239. }