Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/component/dataZoom/InsideZoomModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import DataZoomModel, {DataZoomOption} from './DataZoomModel';
import { inheritDefaultOption } from '../../util/component';
import { WheelAxisType } from '../helper/RoamController';

export interface InsideDataZoomOption extends DataZoomOption {

Expand All @@ -40,6 +41,29 @@ export interface InsideDataZoomOption extends DataZoomOption {

preventDefaultMouseMove?: boolean

/**
* Restricts the pan (triggered by `moveOnMouseWheel`) to a single
* wheel axis. Has no effect on zoom — see `zoomOnMouseWheelAxis`.
*
* - Omitted (default): either wheel axis can drive the pan, preserving
* the pre-existing single-`scrollDelta` behavior.
* - `'horizontal'`: only `deltaX` drives the pan.
* - `'vertical'`: only `deltaY` drives the pan.
*/
moveOnMouseWheelAxis?: WheelAxisType

/**
* Restricts the zoom (triggered by `zoomOnMouseWheel`) to a single
* wheel axis. Has no effect on pan — see `moveOnMouseWheelAxis`.
*
* - Omitted (default): any wheel direction triggers zoom, matching the
* pre-existing behavior where zrender's collapsed `wheelDelta` drives
* the scale factor.
* - `'horizontal'`: only `deltaX` drives the zoom.
* - `'vertical'`: only `deltaY` drives the zoom.
*/
zoomOnMouseWheelAxis?: WheelAxisType

/**
* Inside dataZoom don't support textStyle
*/
Expand Down
58 changes: 51 additions & 7 deletions src/component/dataZoom/InsideZoomView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ 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 RoamController, {RoamEventParams, WheelAxisType} from '../helper/RoamController';
import { AxisBaseModel } from '../../coord/AxisBaseModel';
import Polar from '../../coord/polar/Polar';
import SingleAxis from '../../coord/single/SingleAxis';
Expand Down Expand Up @@ -104,6 +104,14 @@ const getRangeHandlers: {
return;
}

// `zoomOnMouseWheelAxis` restricts the zoom to one wheel axis;
// unset falls back to the combined `scale` for backward
// compatibility.
const effectiveScale = pickWheelAxisValue(
(this.dataZoomModel as InsideZoomModel).get('zoomOnMouseWheelAxis', true),
e.scaleX, e.scaleY, e.scale
);

const directionInfo = getDirectionInfo[coordSysMainType](
null, [e.originX, e.originY], axisModel, controller, coordSysInfo
);
Expand All @@ -113,7 +121,7 @@ const getRangeHandlers: {
: (directionInfo.pixel - directionInfo.pixelStart)
) / directionInfo.pixelLength * (range[1] - range[0]) + range[0];

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

Expand All @@ -140,19 +148,55 @@ const getRangeHandlers: {
}),

scrollMove: makeMover(
function (range, axisModel, coordSysInfo, coordSysMainType, controller, e: RoamEventParams['scrollMove']
function (
this: InsideZoomView,
range, axisModel, coordSysInfo, coordSysMainType, controller,
e: RoamEventParams['scrollMove']
) {
// `moveOnMouseWheelAxis` restricts the pan to one wheel axis;
// unset falls back to the combined `scrollDelta` for backward
// compatibility.
const effectiveDelta = pickWheelAxisValue(
(this.dataZoomModel as InsideZoomModel).get('moveOnMouseWheelAxis', true),
e.scrollDeltaX, e.scrollDeltaY, e.scrollDelta
);
const directionInfo = getDirectionInfo[coordSysMainType](
[0, 0], [e.scrollDelta, e.scrollDelta], axisModel, controller, coordSysInfo
[0, 0], [effectiveDelta, effectiveDelta],
axisModel, controller, coordSysInfo
);
return directionInfo.signal * (range[1] - range[0]) * e.scrollDelta;
// Only `directionInfo.signal` is used here — the scalar already
// encodes the magnitude. `directionInfo.pixel` would go through
// `pointToCoord` for polar and no longer match the scalar.
return directionInfo.signal * (range[1] - range[0]) * effectiveDelta;
})
};

/**
* Picks the wheel-derived value for this dataZoom given a
* `moveOnMouseWheelAxis` / `zoomOnMouseWheelAxis` setting. Unset falls
* back to the caller-supplied scalar so existing configurations keep
* their pre-existing behavior.
*/
function pickWheelAxisValue(
wheelAxis: WheelAxisType | undefined,
axisHorizontal: number,
axisVertical: number,
fallback: number
): number {
if (wheelAxis === 'horizontal') {
return axisHorizontal;
}
if (wheelAxis === 'vertical') {
return axisVertical;
}
return fallback;
}

export type DataZoomGetRangeHandlers = typeof getRangeHandlers;

function makeMover(
getPercentDelta: (
this: InsideZoomView,
range: [number, number],
axisModel: AxisBaseModel,
coordSysInfo: DataZoomReferCoordSysInfo,
Expand All @@ -177,8 +221,8 @@ function makeMover(
return;
}

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

sliderMove(percentDelta, range, [0, 100], 'all');
Expand Down
40 changes: 34 additions & 6 deletions src/component/dataZoom/roams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
// pan or zoom, only dispatch one action for those data zoom
// components.

import RoamController, { RoamOption } from '../../component/helper/RoamController';
import RoamController, { RoamOption, WheelAxisType } from '../../component/helper/RoamController';
import * as throttleUtil from '../../util/throttle';
import { makeInner } from '../../util/model';
import { Dictionary, RoamOptionMixin, ZRElementEvent } from '../../util/types';
Expand Down Expand Up @@ -198,6 +198,10 @@ function mergeControllerParams(
'type_undefined': -1
};
let preventDefaultMouseMove = true;
let zoomOnMouseWheelEverActive = false;
let moveOnMouseWheelEverActive = false;
let zoomOnMouseWheelAxis: WheelAxisType | undefined;
let moveOnMouseWheelAxis: WheelAxisType | undefined;

dataZoomInfoMap.each(function (dataZoomInfo) {
const dataZoomModel = dataZoomInfo.model;
Expand All @@ -214,17 +218,41 @@ function mergeControllerParams(
// users may be confused why it does not work when multiple insideZooms exist.
preventDefaultMouseMove = preventDefaultMouseMove
&& dataZoomModel.get('preventDefaultMouseMove', true);

if (dataZoomModel.get('zoomOnMouseWheel', true) !== false) {
const axis = dataZoomModel.get('zoomOnMouseWheelAxis', true);
if (!zoomOnMouseWheelEverActive) {
zoomOnMouseWheelAxis = axis;
}
else if (zoomOnMouseWheelAxis !== axis) {
zoomOnMouseWheelAxis = undefined;
}
zoomOnMouseWheelEverActive = true;
}
if (dataZoomModel.get('moveOnMouseWheel', true) !== false) {
const axis = dataZoomModel.get('moveOnMouseWheelAxis', true);
if (!moveOnMouseWheelEverActive) {
moveOnMouseWheelAxis = axis;
}
else if (moveOnMouseWheelAxis !== axis) {
moveOnMouseWheelAxis = undefined;
}
moveOnMouseWheelEverActive = true;
}
});

return {
controlType: controlType,
opt: {
// RoamController will enable all of these functionalities,
// and the final behavior is determined by its event listener
// provided by each inside zoom.
zoomOnMouseWheel: true,
// RoamController enables these functionalities if any inside
// zoom opts in, and the final behavior (including modifier
// specifics) is determined by its event listener provided by
// each inside zoom.
zoomOnMouseWheel: zoomOnMouseWheelEverActive,
moveOnMouseMove: true,
moveOnMouseWheel: true,
moveOnMouseWheel: moveOnMouseWheelEverActive,
zoomOnMouseWheelAxis: zoomOnMouseWheelAxis,
moveOnMouseWheelAxis: moveOnMouseWheelAxis,
preventDefaultMouseMove: !!preventDefaultMouseMove,
api,
zInfo: {
Expand Down
Loading