echarts InsideZoomView 源码

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

echarts InsideZoomView 代码

文件路径:/src/component/dataZoom/InsideZoomView.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 DataZoomView from './DataZoomView';
import sliderMove from '../helper/sliderMove';
import * as roams from './roams';
import InsideZoomModel from './InsideZoomModel';
import GlobalModel from '../../model/Global';
import ExtensionAPI from '../../core/ExtensionAPI';
import { bind } from 'zrender/src/core/util';
import RoamController, {RoamEventParams} from '../helper/RoamController';
import { AxisBaseModel } from '../../coord/AxisBaseModel';
import Polar from '../../coord/polar/Polar';
import SingleAxis from '../../coord/single/SingleAxis';
import { DataZoomCoordSysMainType, DataZoomReferCoordSysInfo } from './helper';


class InsideZoomView extends DataZoomView {
    static type = 'dataZoom.inside';
    type = 'dataZoom.inside';

    /**
     * 'throttle' is used in this.dispatchAction, so we save range
     * to avoid missing some 'pan' info.
     */
    range: number[];

    render(dataZoomModel: InsideZoomModel, ecModel: GlobalModel, api: ExtensionAPI) {
        super.render.apply(this, arguments as any);

        if (dataZoomModel.noTarget()) {
            this._clear();
            return;
        }

        // Hence the `throttle` util ensures to preserve command order,
        // here simply updating range all the time will not cause missing
        // any of the the roam change.
        this.range = dataZoomModel.getPercentRange();

        // Reset controllers.
        roams.setViewInfoToCoordSysRecord(
            api,
            dataZoomModel,
            {
                pan: bind(getRangeHandlers.pan, this),
                zoom: bind(getRangeHandlers.zoom, this),
                scrollMove: bind(getRangeHandlers.scrollMove, this)
            }
        );
    }

    dispose() {
        this._clear();
        super.dispose.apply(this, arguments as any);
    }

    private _clear() {
        roams.disposeCoordSysRecordIfNeeded(this.api, this.dataZoomModel as InsideZoomModel);
        this.range = null;
    }
}

interface DataZoomGetRangeHandler<
    T extends RoamEventParams['zoom'] | RoamEventParams['scrollMove'] | RoamEventParams['pan']
> {
    (
        coordSysInfo: DataZoomReferCoordSysInfo,
        coordSysMainType: DataZoomCoordSysMainType,
        controller: RoamController,
        e: T
    ): [number, number]
}

const getRangeHandlers: {
    pan: DataZoomGetRangeHandler<RoamEventParams['pan']>
    zoom: DataZoomGetRangeHandler<RoamEventParams['zoom']>
    scrollMove: DataZoomGetRangeHandler<RoamEventParams['scrollMove']>
} & ThisType<InsideZoomView> = {

    zoom(coordSysInfo, coordSysMainType, controller, e: RoamEventParams['zoom']) {
        const lastRange = this.range;
        const range = lastRange.slice() as [number, number];

        // Calculate transform by the first axis.
        const axisModel = coordSysInfo.axisModels[0];
        if (!axisModel) {
            return;
        }

        const directionInfo = getDirectionInfo[coordSysMainType](
            null, [e.originX, e.originY], axisModel, controller, coordSysInfo
        );
        const percentPoint = (
            directionInfo.signal > 0
                ? (directionInfo.pixelStart + directionInfo.pixelLength - directionInfo.pixel)
                : (directionInfo.pixel - directionInfo.pixelStart)
            ) / directionInfo.pixelLength * (range[1] - range[0]) + range[0];

        const scale = Math.max(1 / e.scale, 0);
        range[0] = (range[0] - percentPoint) * scale + percentPoint;
        range[1] = (range[1] - percentPoint) * scale + percentPoint;

        // Restrict range.
        const minMaxSpan = this.dataZoomModel.findRepresentativeAxisProxy().getMinMaxSpan();

        sliderMove(0, range, [0, 100], 0, minMaxSpan.minSpan, minMaxSpan.maxSpan);

        this.range = range;

        if (lastRange[0] !== range[0] || lastRange[1] !== range[1]) {
            return range;
        }
    },

    pan: makeMover(function (range, axisModel, coordSysInfo, coordSysMainType, controller, e: RoamEventParams['pan']) {
        const directionInfo = getDirectionInfo[coordSysMainType](
            [e.oldX, e.oldY], [e.newX, e.newY], axisModel, controller, coordSysInfo
        );

        return directionInfo.signal
            * (range[1] - range[0])
            * directionInfo.pixel / directionInfo.pixelLength;
    }),

    scrollMove: makeMover(
        function (range, axisModel, coordSysInfo, coordSysMainType, controller, e: RoamEventParams['scrollMove']
    ) {
        const directionInfo = getDirectionInfo[coordSysMainType](
            [0, 0], [e.scrollDelta, e.scrollDelta], axisModel, controller, coordSysInfo
        );
        return directionInfo.signal * (range[1] - range[0]) * e.scrollDelta;
    })
};

export type DataZoomGetRangeHandlers = typeof getRangeHandlers;

function makeMover(
    getPercentDelta: (
        range: [number, number],
        axisModel: AxisBaseModel,
        coordSysInfo: DataZoomReferCoordSysInfo,
        coordSysMainType: DataZoomCoordSysMainType,
        controller: RoamController,
        e: RoamEventParams['scrollMove']| RoamEventParams['pan']
    ) => number
) {
    return function (
        this: InsideZoomView,
        coordSysInfo: DataZoomReferCoordSysInfo,
        coordSysMainType: DataZoomCoordSysMainType,
        controller: RoamController,
        e: RoamEventParams['scrollMove']| RoamEventParams['pan']
    ): [number, number] {
        const lastRange = this.range;
        const range = lastRange.slice() as [number, number];

        // Calculate transform by the first axis.
        const axisModel = coordSysInfo.axisModels[0];
        if (!axisModel) {
            return;
        }

        const percentDelta = getPercentDelta(
            range, axisModel, coordSysInfo, coordSysMainType, controller, e
        );

        sliderMove(percentDelta, range, [0, 100], 'all');

        this.range = range;

        if (lastRange[0] !== range[0] || lastRange[1] !== range[1]) {
            return range;
        }
    };
}

interface DirectionInfo {
    pixel: number
    pixelLength: number
    pixelStart: number
    signal: -1 | 1
}
interface GetDirectionInfo {
    (
        oldPoint: number[],
        newPoint: number[],
        axisModel: AxisBaseModel,
        controller: RoamController,
        coordSysInfo: DataZoomReferCoordSysInfo
    ): DirectionInfo
}

const getDirectionInfo: Record<'grid' | 'polar' | 'singleAxis', GetDirectionInfo> = {

    grid(oldPoint, newPoint, axisModel, controller, coordSysInfo) {
        const axis = axisModel.axis;
        const ret = {} as DirectionInfo;
        const rect = coordSysInfo.model.coordinateSystem.getRect();
        oldPoint = oldPoint || [0, 0];

        if (axis.dim === 'x') {
            ret.pixel = newPoint[0] - oldPoint[0];
            ret.pixelLength = rect.width;
            ret.pixelStart = rect.x;
            ret.signal = axis.inverse ? 1 : -1;
        }
        else { // axis.dim === 'y'
            ret.pixel = newPoint[1] - oldPoint[1];
            ret.pixelLength = rect.height;
            ret.pixelStart = rect.y;
            ret.signal = axis.inverse ? -1 : 1;
        }

        return ret;
    },

    polar(oldPoint, newPoint, axisModel, controller, coordSysInfo) {
        const axis = axisModel.axis;
        const ret = {} as DirectionInfo;
        const polar = coordSysInfo.model.coordinateSystem as Polar;
        const radiusExtent = polar.getRadiusAxis().getExtent();
        const angleExtent = polar.getAngleAxis().getExtent();

        oldPoint = oldPoint ? polar.pointToCoord(oldPoint) : [0, 0];
        newPoint = polar.pointToCoord(newPoint);

        if (axisModel.mainType === 'radiusAxis') {
            ret.pixel = newPoint[0] - oldPoint[0];
            // ret.pixelLength = Math.abs(radiusExtent[1] - radiusExtent[0]);
            // ret.pixelStart = Math.min(radiusExtent[0], radiusExtent[1]);
            ret.pixelLength = radiusExtent[1] - radiusExtent[0];
            ret.pixelStart = radiusExtent[0];
            ret.signal = axis.inverse ? 1 : -1;
        }
        else { // 'angleAxis'
            ret.pixel = newPoint[1] - oldPoint[1];
            // ret.pixelLength = Math.abs(angleExtent[1] - angleExtent[0]);
            // ret.pixelStart = Math.min(angleExtent[0], angleExtent[1]);
            ret.pixelLength = angleExtent[1] - angleExtent[0];
            ret.pixelStart = angleExtent[0];
            ret.signal = axis.inverse ? -1 : 1;
        }

        return ret;
    },

    singleAxis(oldPoint, newPoint, axisModel, controller, coordSysInfo) {
        const axis = axisModel.axis as SingleAxis;
        const rect = coordSysInfo.model.coordinateSystem.getRect();
        const ret = {} as DirectionInfo;

        oldPoint = oldPoint || [0, 0];

        if (axis.orient === 'horizontal') {
            ret.pixel = newPoint[0] - oldPoint[0];
            ret.pixelLength = rect.width;
            ret.pixelStart = rect.x;
            ret.signal = axis.inverse ? 1 : -1;
        }
        else { // 'vertical'
            ret.pixel = newPoint[1] - oldPoint[1];
            ret.pixelLength = rect.height;
            ret.pixelStart = rect.y;
            ret.signal = axis.inverse ? -1 : 1;
        }

        return ret;
    }
};

export default InsideZoomView;

相关信息

echarts 源码目录

相关文章

echarts AxisProxy 源码

echarts DataZoomModel 源码

echarts DataZoomView 源码

echarts InsideZoomModel 源码

echarts SelectZoomModel 源码

echarts SelectZoomView 源码

echarts SliderZoomModel 源码

echarts SliderZoomView 源码

echarts dataZoomAction 源码

echarts dataZoomProcessor 源码

0  赞