| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- /*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- /**
- * AUTO-GENERATED FILE. DO NOT MODIFY.
- */
- /*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- import { assert, each } from 'zrender/lib/core/util.js';
- import { isOrdinalScale } from '../scale/helper.js';
- import { isNullableNumberFinite, mathAbs, mathMax } from '../util/number.js';
- import { getAxisStat, getAxisStatBySeries, LINEAR_POSITIVE_MIN_GAP_SINGLE_VALID_VALUE } from './axisStatistics.js';
- import { getScaleLinearSpanForMapping } from '../scale/scaleMapper.js';
- // Arbitrary, leave some space to avoid overflowing when dataZoom moving.
- var FALLBACK_BAND_WIDTH_RATIO = 0.8;
- /**
- * NOTICE:
- * - Require the axis pixel extent and the scale extent as inputs. But they
- * can be not precise for approximation.
- * - Can only be called after "data processing" stage.
- *
- * PENDING:
- * Currently `bandWidth` can not be specified by users explicitly. But if we
- * allow that in future, these issues must be considered:
- * - Can only allow specifying a band width in data scale rather than pixel.
- * - LogScale needs to be considered - band width can only be specified on linear
- * (but before break) scale, similar to `axis.interval`.
- *
- * A band is required on:
- * - series group band width in bar/boxplot/candlestick/...;
- * - tooltip axisPointer type "shadow";
- * - etc.
- */
- export function calcBandWidth(axis, opt) {
- opt = opt || {};
- var out = {
- w: NaN,
- w2: NaN
- };
- var scale = axis.scale;
- var fromStat = opt.fromStat;
- var min = opt.min;
- // [BAND_WIDTH_USED_SCALE_LINEAR_SPAN]
- // - Band width should always respect to the currently specified extent, and `SCALE_EXTENT_KIND_MAPPING`
- // should be used if specified.
- // Otherwise, the result may incorrect, especially when data count is small.
- // For example, when "containShape" is calculating, no `SCALE_EXTENT_KIND_MAPPING` is set, so here only
- // `SCALE_EXTENT_KIND_EFFECTIVE` is returned, say, `[3, 5]`, based on which a `SCALE_EXTENT_KIND_MAPPING`
- // is calculated, say `[2.5, 5.5]` (expanded by `0.5`). Then when rendering, that `SCALE_EXTENT_KIND_MAPPING`
- // is returned here.
- // See AXIS_CONTAIN_SHAPE_COMMON_STRATEGY for more details.
- // - The span should be in the linear space (typically, the innermost space).
- // - We use the scale extent after being zoommed and `intervalScaleEnsureValidExtent`-ish applied and
- // "nice"/"align" applied, because:
- // - For OrdinalScale, fine;
- // - For numeric scale, `scaleLinearSpan` is normally not used for a consistent result when `dataZoom`
- // is applied, but used when none or single data item case.
- var scaleLinearSpan = getScaleLinearSpanForMapping(scale);
- if (!isNullableNumberFinite(scaleLinearSpan)) {
- // scale may be `[Infinity, -Infinity]`.
- scaleLinearSpan = NaN;
- }
- var axisExtent = axis.getExtent();
- // Always use a new pxSpan because it may be changed in `grid` contain label calculation.
- var pxSpan = mathAbs(axisExtent[1] - axisExtent[0]);
- if (isOrdinalScale(scale)) {
- calcBandWidthForCategoryAxis(out, axis, scaleLinearSpan, pxSpan);
- } else if (fromStat) {
- calcBandWidthForNumericAxis(out, axis, scaleLinearSpan, pxSpan, fromStat);
- } else if (min == null) {
- if (process.env.NODE_ENV !== 'production') {
- assert(false);
- }
- }
- if (min != null) {
- out.w = isNullableNumberFinite(out.w) ? mathMax(min, out.w) : min;
- }
- return out;
- }
- function calcBandWidthForCategoryAxis(out, axis, scaleLinearSpan, pxSpan) {
- var onBand = axis.onBand;
- var len = scaleLinearSpan + (onBand ? 1 : 0);
- // Fix #2728, avoid NaN when only one data.
- len === 0 && (len = 1);
- out.w = pxSpan / len;
- // NOTE:
- // - When `scaleLinearSpan === 0`, no need to expand extent.
- // - `onBand: true` (`boundaryGap: true`) does not need to support `containShape`,
- // thereby no `invRatio`.
- if (!onBand && scaleLinearSpan && pxSpan) {
- out.w2 = out.w * scaleLinearSpan / pxSpan;
- }
- }
- function calcBandWidthForNumericAxis(out, axis, scaleLinearSpan, pxSpan, fromStat) {
- if (process.env.NODE_ENV !== 'production') {
- assert(fromStat);
- }
- var onlySingular = false;
- var bandWidthInData = -Infinity;
- each(fromStat.key ? [getAxisStat(axis, fromStat.key)] : getAxisStatBySeries(axis, fromStat.sers || []), function (stat) {
- var liPosMinGap = stat.liPosMinGap;
- // NOTE: `liPosMinGap == null` may indicate that `requireAxisStatistics`
- // is not used by any series on this axis. We should not make `bandWidth`
- // for this case.
- if (liPosMinGap != null) {
- if (liPosMinGap > 0) {
- if (liPosMinGap > bandWidthInData) {
- bandWidthInData = liPosMinGap;
- }
- onlySingular = false;
- } else if (liPosMinGap === LINEAR_POSITIVE_MIN_GAP_SINGLE_VALID_VALUE) {
- onlySingular = true;
- }
- }
- });
- if (isNullableNumberFinite(scaleLinearSpan) && scaleLinearSpan > 0 && isNullableNumberFinite(bandWidthInData)) {
- out.w = pxSpan / scaleLinearSpan * bandWidthInData;
- out.w2 = bandWidthInData;
- } else if (onlySingular) {
- // This is the special handing for single value case, where min gap can not
- // be calculated, but `w` and `w2` (for "containShape") are still needed.
- out.w = pxSpan * FALLBACK_BAND_WIDTH_RATIO;
- out.w2 = out.w * scaleLinearSpan / pxSpan;
- // Consider an axis has both candlestick and bar series, where candlestick has multiple data
- // but the bar series has no data. In this case, that bar series should be ignored; otherwise,
- // the axis will be significantly expanded by "containShape" but no bar shape displayed.
- }
- }
|