echarts axisAlignTicks 源码

  • 2022-10-20
  • 浏览 (772)

echarts axisAlignTicks 代码

文件路径:/src/coord/axisAlignTicks.ts

/*
* 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 { NumericAxisBaseOptionCommon } from './axisCommonTypes';
import { getPrecisionSafe, round } from '../util/number';
import IntervalScale from '../scale/Interval';
import { getScaleExtent } from './axisHelper';
import { AxisBaseModel } from './AxisBaseModel';
import LogScale from '../scale/Log';
import { warn } from '../util/log';
import { increaseInterval, isValueNice } from '../scale/helper';

const mathLog = Math.log;


export function alignScaleTicks(
    scale: IntervalScale | LogScale,
    axisModel: AxisBaseModel<Pick<NumericAxisBaseOptionCommon, 'min' | 'max'>>,
    alignToScale: IntervalScale | LogScale
) {

    const intervalScaleProto = IntervalScale.prototype;

    // NOTE: There is a precondition for log scale  here:
    // In log scale we store _interval and _extent of exponent value.
    // So if we use the method of InternalScale to set/get these data.
    // It process the exponent value, which is linear and what we want here.
    const alignToTicks = intervalScaleProto.getTicks.call(alignToScale);
    const alignToNicedTicks = intervalScaleProto.getTicks.call(alignToScale, true);
    const alignToSplitNumber = alignToTicks.length - 1;
    const alignToInterval = intervalScaleProto.getInterval.call(alignToScale);

    const scaleExtent = getScaleExtent(scale, axisModel);
    let rawExtent = scaleExtent.extent;
    const isMinFixed = scaleExtent.fixMin;
    const isMaxFixed = scaleExtent.fixMax;

    if (scale.type === 'log') {
        const logBase = mathLog((scale as LogScale).base);
        rawExtent = [mathLog(rawExtent[0]) / logBase, mathLog(rawExtent[1]) / logBase];
    }

    scale.setExtent(rawExtent[0], rawExtent[1]);
    scale.calcNiceExtent({
        splitNumber: alignToSplitNumber,
        fixMin: isMinFixed,
        fixMax: isMaxFixed
    });
    const extent = intervalScaleProto.getExtent.call(scale);

    // Need to update the rawExtent.
    // Because value in rawExtent may be not parsed. e.g. 'dataMin', 'dataMax'
    if (isMinFixed) {
        rawExtent[0] = extent[0];
    }
    if (isMaxFixed) {
        rawExtent[1] = extent[1];
    }

    let interval = intervalScaleProto.getInterval.call(scale);
    let min: number = rawExtent[0];
    let max: number = rawExtent[1];

    if (isMinFixed && isMaxFixed) {
        // User set min, max, divide to get new interval
        interval = (max - min) / alignToSplitNumber;
    }
    else if (isMinFixed) {
        max = rawExtent[0] + interval * alignToSplitNumber;
        // User set min, expand extent on the other side
        while (max < rawExtent[1] && isFinite(max) && isFinite(rawExtent[1])) {
            interval = increaseInterval(interval);
            max = rawExtent[0] + interval * alignToSplitNumber;
        }
    }
    else if (isMaxFixed) {
        // User set max, expand extent on the other side
        min = rawExtent[1] - interval * alignToSplitNumber;
        while (min > rawExtent[0] && isFinite(min) && isFinite(rawExtent[0])) {
            interval = increaseInterval(interval);
            min = rawExtent[1] - interval * alignToSplitNumber;
        }
    }
    else {
        const nicedSplitNumber = scale.getTicks().length - 1;
        if (nicedSplitNumber > alignToSplitNumber) {
            interval = increaseInterval(interval);
        }

        const range = interval * alignToSplitNumber;
        max = Math.ceil(rawExtent[1] / interval) * interval;
        min = round(max - range);
        // Not change the result that crossing zero.
        if (min < 0 && rawExtent[0] >= 0) {
            min = 0;
            max = round(range);
        }
        else if (max > 0 && rawExtent[1] <= 0) {
            max = 0;
            min = -round(range);
        }

    }

    // Adjust min, max based on the extent of alignTo. When min or max is set in alignTo scale
    const t0 = (alignToTicks[0].value - alignToNicedTicks[0].value) / alignToInterval;
    const t1 = (alignToTicks[alignToSplitNumber].value - alignToNicedTicks[alignToSplitNumber].value) / alignToInterval;

    // NOTE: Must in setExtent -> setInterval -> setNiceExtent order.
    intervalScaleProto.setExtent.call(scale, min + interval * t0, max + interval * t1);
    intervalScaleProto.setInterval.call(scale, interval);
    if (t0 || t1) {
        intervalScaleProto.setNiceExtent.call(scale, min + interval, max - interval);
    }

    if (__DEV__) {
        const ticks = intervalScaleProto.getTicks.call(scale);
        if (ticks[1]
            && (!isValueNice(interval) || getPrecisionSafe(ticks[1].value) > getPrecisionSafe(interval))) {
            warn(
                // eslint-disable-next-line
                `The ticks may be not readable when set min: ${axisModel.get('min')}, max: ${axisModel.get('max')} and alignTicks: true`
            );
        }
    }
}

相关信息

echarts 源码目录

相关文章

echarts Axis 源码

echarts AxisBaseModel 源码

echarts CoordinateSystem 源码

echarts View 源码

echarts axisCommonTypes 源码

echarts axisDefault 源码

echarts axisHelper 源码

echarts axisModelCommonMixin 源码

echarts axisModelCreator 源码

echarts axisTickLabelBuilder 源码

0  赞