Skip to content

Commit

Permalink
ui-manchette-with-spacetime: adapt hook to work with both zoom and sc…
Browse files Browse the repository at this point in the history
…roll sliding

Signed-off-by: Valentin Chanas <[email protected]>
  • Loading branch information
anisometropie committed Dec 18, 2024
1 parent da20190 commit dea47ce
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 27 deletions.
8 changes: 5 additions & 3 deletions ui-manchette-with-spacetimechart/src/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ export const BASE_WAYPOINT_HEIGHT = 32;
export const INITIAL_WAYPOINT_LIST_HEIGHT = 521;
export const INITIAL_SPACE_TIME_CHART_HEIGHT = INITIAL_WAYPOINT_LIST_HEIGHT + 40;

export const MIN_ZOOM_X = 1;
export const MAX_ZOOM_X = 10;
export const ZOOM_X_DELTA = 0.5;
export const MIN_ZOOM_MS_PER_PX = 600000;
export const MAX_ZOOM_MS_PER_PX = 625;
export const DEFAULT_ZOOM_MS_PER_PX = 7500;
export const MIN_ZOOM_X = 0;
export const MAX_ZOOM_X = 100;

export const MIN_ZOOM_Y = 1;
export const MAX_ZOOM_Y = 10.5;
Expand Down
44 changes: 32 additions & 12 deletions ui-manchette-with-spacetimechart/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@ import type {
ProjectPathTrainResult,
Waypoint,
} from '@osrd-project/ui-manchette/dist/types';
import type {
OperationalPoint,
SpaceTimeChartProps,
} from '@osrd-project/ui-spacetimechart/dist/lib/types';

import { BASE_WAYPOINT_HEIGHT, MAX_TIME_WINDOW, MAX_ZOOM_X, MIN_ZOOM_X } from './consts';
import type { OperationalPoint } from '@osrd-project/ui-spacetimechart/dist/lib/types';
import { clamp } from 'lodash';

import {
BASE_WAYPOINT_HEIGHT,
MAX_TIME_WINDOW,
MAX_ZOOM_MS_PER_PX,
MAX_ZOOM_X,
MIN_ZOOM_MS_PER_PX,
MIN_ZOOM_X,
} from './consts';
import { calcTotalDistance, getHeightWithoutLastWaypoint, msToS } from './utils';

type WaypointsOptions = { isProportional: boolean; yZoom: number; height: number };
Expand Down Expand Up @@ -154,17 +159,32 @@ export const getScales = (
];
};

export const zoomValueToTimeScale = (slider: number) =>
MIN_ZOOM_MS_PER_PX * Math.pow(MAX_ZOOM_MS_PER_PX / MIN_ZOOM_MS_PER_PX, slider / 100);

export const timeScaleToZoomValue = (timeScale: number) =>
(100 * Math.log(timeScale / MIN_ZOOM_MS_PER_PX)) /
Math.log(MAX_ZOOM_MS_PER_PX / MIN_ZOOM_MS_PER_PX);

/** Zoom on X axis and center on the mouse position */
export const zoomX = (
currentXZoom: number,
currentXOffset: number,
{ delta, position: { x } }: Parameters<NonNullable<SpaceTimeChartProps['onZoom']>>[0]
newXZoom: number,
position: number
) => {
const xZoom = Math.min(Math.max(currentXZoom * (1 + delta / 10), MIN_ZOOM_X), MAX_ZOOM_X);
const boundedXZoom = clamp(newXZoom, MIN_ZOOM_X, MAX_ZOOM_X);
const oldTimeScale = zoomValueToTimeScale(currentXZoom);
const newTimeScale = zoomValueToTimeScale(boundedXZoom);
// by default zooming expands the graph around timeOrigin
// changing the offset to timeOriginShift alone keeps the left border in place.
// subtracting centerShift keeps the center in place
// (xOffset = how many px the timeOrigin is shifted to the right)
const timeOriginShift = (currentXOffset * oldTimeScale) / newTimeScale;
const centerShift = (position * oldTimeScale - position * newTimeScale) / newTimeScale;
const newOffset = timeOriginShift - centerShift;
return {
xZoom,
// Adjust zoom level relatively to the input delta value:
// These lines are here to center the zoom on the mouse position:
xOffset: x - ((x - currentXOffset) / currentXZoom) * xZoom,
xZoom: boundedXZoom,
xOffset: newOffset,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,22 @@ import type {
} from '@osrd-project/ui-spacetimechart/dist/lib/types';

import usePaths from './usePaths';
import { MAX_ZOOM_Y, MIN_ZOOM_Y, ZOOM_Y_DELTA, INITIAL_SPACE_TIME_CHART_HEIGHT } from '../consts';
import {
MAX_ZOOM_Y,
MIN_ZOOM_Y,
ZOOM_Y_DELTA,
INITIAL_SPACE_TIME_CHART_HEIGHT,
DEFAULT_ZOOM_MS_PER_PX,
} from '../consts';
import {
calcWaypointsToDisplay,
computeTimeWindow,
getWaypointsWithPosition as getOperationalPointWithPosition,
getScales,
calcWaypointsHeight,
zoomX,
zoomValueToTimeScale,
timeScaleToZoomValue,
} from '../helpers';
import { getDiff } from '../utils/point';

Expand All @@ -39,7 +47,7 @@ const useManchettesWithSpaceTimeChart = (
) => {
const [isShiftPressed, setIsShiftPressed] = useState(false);
const [state, setState] = useState<State>({
xZoom: 1,
xZoom: timeScaleToZoomValue(DEFAULT_ZOOM_MS_PER_PX),
yZoom: 1,
xOffset: 0,
yOffset: 0,
Expand Down Expand Up @@ -130,7 +138,6 @@ const useManchettesWithSpaceTimeChart = (
[operationalPointsWithPosition, height, isProportional, yZoom]
);

// Memoize manchetteProps separately
const manchetteProps = useMemo(
() => ({
waypoints: waypointWithHeight,
Expand All @@ -144,21 +151,30 @@ const useManchettesWithSpaceTimeChart = (
[waypointWithHeight, zoomYIn, zoomYOut, resetZoom, toggleMode, yZoom, isProportional]
);

// Memoize spaceTimeChartProps separately
const handleXZoom = useCallback(
(
newXZoom: number,
xPosition = (manchetteWithSpaceTimeChartContainer.current?.offsetWidth || 0) / 2
) => {
setState((prev) => ({
...prev,
...zoomX(prev.xZoom, prev.xOffset, newXZoom, xPosition),
}));
},
[manchetteWithSpaceTimeChartContainer]
);

const spaceTimeChartProps = useMemo(
() => ({
operationalPoints: operationalPointsWithPosition,
spaceScales: computedScales,
timeScale: timeWindow / xZoom,
timeScale: zoomValueToTimeScale(xZoom),
paths,
xOffset,
yOffset: -scrollPosition + 14,
onZoom: (payload: Parameters<NonNullable<SpaceTimeChartProps['onZoom']>>[0]) => {
onZoom: ({ delta, position }: Parameters<NonNullable<SpaceTimeChartProps['onZoom']>>[0]) => {
if (isShiftPressed) {
setState((prev) => ({
...prev,
...zoomX(prev.xZoom, prev.xOffset, payload),
}));
handleXZoom(xZoom + delta, position.x);
}
},
onPan: (payload: {
Expand Down Expand Up @@ -195,7 +211,6 @@ const useManchettesWithSpaceTimeChart = (
[
operationalPointsWithPosition,
computedScales,
timeWindow,
xZoom,
paths,
xOffset,
Expand All @@ -205,6 +220,7 @@ const useManchettesWithSpaceTimeChart = (
panning,
yOffset,
manchetteWithSpaceTimeChartContainer,
handleXZoom,
]
);

Expand All @@ -213,8 +229,9 @@ const useManchettesWithSpaceTimeChart = (
manchetteProps,
spaceTimeChartProps,
handleScroll,
handleXZoom,
}),
[manchetteProps, spaceTimeChartProps, handleScroll]
[manchetteProps, spaceTimeChartProps, handleScroll, handleXZoom]
);
};

Expand Down

0 comments on commit dea47ce

Please sign in to comment.