Skip to content

Commit

Permalink
feat: zoom in/out scroll
Browse files Browse the repository at this point in the history
  • Loading branch information
dineug committed Dec 19, 2023
1 parent 9e5dc86 commit 9bb888b
Show file tree
Hide file tree
Showing 8 changed files with 128 additions and 27 deletions.
10 changes: 3 additions & 7 deletions packages/erd-editor/src/components/erd/Erd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,8 @@ import {
unselectAllAction$,
} from '@/engine/modules/editor/generator.actions';
import { Viewport } from '@/engine/modules/editor/state';
import {
streamScrollToAction,
streamZoomLevelAction,
} from '@/engine/modules/settings/atom.actions';
import { streamScrollToAction } from '@/engine/modules/settings/atom.actions';
import { streamZoomLevelAction$ } from '@/engine/modules/settings/generator.actions';
import { moveToTableAction } from '@/engine/modules/table/atom.actions';
import { useUnmounted } from '@/hooks/useUnmounted';
import { isMouseEvent } from '@/utils/domEvent';
Expand Down Expand Up @@ -103,9 +101,7 @@ const Erd: FC<ErdProps> = (props, ctx) => {

const handleWheel = (event: WheelEvent) => {
const { store } = app.value;
store.dispatch(
streamZoomLevelAction({ value: event.deltaY < 0 ? 0.1 : -0.1 })
);
store.dispatch(streamZoomLevelAction$(event.deltaY < 0 ? 0.1 : -0.1));
};

const handleMove = ({ event, movementX, movementY }: DragMove) => {
Expand Down
6 changes: 3 additions & 3 deletions packages/erd-editor/src/components/erd/useErdShortcut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
SelectType,
} from '@/engine/modules/editor/state';
import { addMemoAction$ } from '@/engine/modules/memo/generator.actions';
import { streamZoomLevelAction } from '@/engine/modules/settings/atom.actions';
import { streamZoomLevelAction$ } from '@/engine/modules/settings/generator.actions';
import {
addTableAction$,
pasteTableAction$,
Expand Down Expand Up @@ -155,9 +155,9 @@ export function useErdShortcut(ctx: Ctx) {
// KeyBindingName.find

type === KeyBindingName.zoomIn &&
store.dispatch(streamZoomLevelAction({ value: 0.1 }));
store.dispatch(streamZoomLevelAction$(0.1));
type === KeyBindingName.zoomOut &&
store.dispatch(streamZoomLevelAction({ value: -0.1 }));
store.dispatch(streamZoomLevelAction$(-0.1));
}

if (!showHighLevelTable) {
Expand Down
4 changes: 2 additions & 2 deletions packages/erd-editor/src/components/toolbar/Toolbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import { unselectAllAction$ } from '@/engine/modules/editor/generator.actions';
import {
changeCanvasTypeAction,
changeDatabaseNameAction,
changeZoomLevelAction,
resizeAction,
} from '@/engine/modules/settings/atom.actions';
import { changeZoomLevelAction$ } from '@/engine/modules/settings/generator.actions';
import {
canvasSizeInRange,
toNumString,
Expand Down Expand Up @@ -51,7 +51,7 @@ const Toolbar: FC<ToolbarProps> = (props, ctx) => {
const zoomLevel = zoomLevelInRange(Number(toNumString(el.value)) / 100);
const { store } = app.value;
el.value = toZoomFormat(zoomLevel);
store.dispatch(changeZoomLevelAction({ value: zoomLevel }));
store.dispatch(changeZoomLevelAction$(zoomLevel));
};

const handleChangeCanvasType = (value: string) => {
Expand Down
10 changes: 10 additions & 0 deletions packages/erd-editor/src/engine/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,16 @@ export const ChangeActionTypes: ReadonlyArray<ActionType> = [
'editor.clear',
];

export const StreamRegroupMoveActionTypes: ReadonlyArray<ActionType> = [
'table.move',
'memo.move',
];

export const StreamRegroupScrollActionTypes: ReadonlyArray<ActionType> = [
'settings.streamZoomLevel',
'settings.streamScrollTo',
];

export const StreamActionTypes: ReadonlyArray<ActionType> = [
...(Object.keys(pushStreamHistoryMap) as ActionType[]),
];
Expand Down
15 changes: 11 additions & 4 deletions packages/erd-editor/src/engine/modules/settings/atom.actions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createAction } from '@dineug/r-html';
import { createInRange } from '@dineug/shared';
import { round } from 'lodash-es';

import { replaceOperator } from '@/utils/collection/lww';
import {
Expand Down Expand Up @@ -80,8 +81,8 @@ const scrollTo: ReducerType<typeof ActionType.scrollTo> = (
const scrollTopInRange = createInRange(viewport.height - settings.height, 0);
const scrollLeftInRange = createInRange(viewport.width - settings.width, 0);

settings.scrollTop = scrollTopInRange(scrollTop);
settings.scrollLeft = scrollLeftInRange(scrollLeft);
settings.scrollTop = round(scrollTopInRange(scrollTop), 4);
settings.scrollLeft = round(scrollLeftInRange(scrollLeft), 4);
};

export const streamScrollToAction = createAction<
Expand All @@ -95,8 +96,14 @@ const streamScrollTo: ReducerType<typeof ActionType.streamScrollTo> = (
const scrollTopInRange = createInRange(viewport.height - settings.height, 0);
const scrollLeftInRange = createInRange(viewport.width - settings.width, 0);

settings.scrollTop = scrollTopInRange(settings.scrollTop + movementY);
settings.scrollLeft = scrollLeftInRange(settings.scrollLeft + movementX);
settings.scrollTop = round(
scrollTopInRange(settings.scrollTop + movementY),
4
);
settings.scrollLeft = round(
scrollLeftInRange(settings.scrollLeft + movementX),
4
);
};

export const changeShowAction = createAction<
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,71 @@
export const actions$ = {};
import { round } from 'lodash-es';

import { GeneratorAction } from '@/engine/generator.actions';
import { RootState } from '@/engine/state';
import { getZoomViewport } from '@/utils/dragSelect';
import { zoomLevelInRange } from '@/utils/validation';

import {
changeZoomLevelAction,
scrollToAction,
streamScrollToAction,
streamZoomLevelAction,
} from './atom.actions';

function getMovementScrollTo(
{
editor: { viewport },
settings: { scrollLeft, scrollTop, zoomLevel, width, height },
}: RootState,
nextZoomLevel: number
) {
const zoomViewport = getZoomViewport(width, height, zoomLevel);
const nextZoomViewport = getZoomViewport(width, height, nextZoomLevel);
const x = (zoomViewport.w - nextZoomViewport.w) / 2;
const y = (zoomViewport.h - nextZoomViewport.h) / 2;
const centerX = width / 2;
const centerY = height / 2;
const viewportCenterX = scrollLeft * -1 + viewport.width / 2;
const viewportCenterY = scrollTop * -1 + viewport.height / 2;
const centerXRatio = (centerX - viewportCenterX) / centerX;
const centerYRatio = (centerY - viewportCenterY) / centerY;
const movementX = round(-1 * x * centerXRatio, 4);
const movementY = round(-1 * y * centerYRatio, 4);

return { movementX, movementY };
}

export const changeZoomLevelAction$ = (value: number): GeneratorAction =>
function* (state) {
const {
settings: { scrollLeft, scrollTop },
} = state;
const nextZoomLevel = zoomLevelInRange(value);
const { movementX, movementY } = getMovementScrollTo(state, nextZoomLevel);

yield changeZoomLevelAction({ value });
yield scrollToAction({
scrollLeft: scrollLeft + movementX,
scrollTop: scrollTop + movementY,
});
};

export const streamZoomLevelAction$ = (value: number): GeneratorAction =>
function* (state) {
const {
settings: { zoomLevel },
} = state;
const nextZoomLevel = zoomLevelInRange(zoomLevel + value);
const { movementX, movementY } = getMovementScrollTo(state, nextZoomLevel);

yield streamZoomLevelAction({ value });
yield streamScrollToAction({
movementX,
movementY,
});
};

export const actions$ = {
changeZoomLevelAction$,
streamZoomLevelAction$,
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,39 @@ import { notEmptyActions } from '@/engine/rx-operators/notEmptyActions';

const NONE_STREAM_KEY = '@@none-stream';

type Regroup = [string, Array<string> | ReadonlyArray<string>];
type HasRegroup = [string, (type: string) => boolean];

const createToKey =
(has: (type: string) => boolean, hasRegroups: HasRegroup[]) =>
(type: string) => {
const hasRegroup = hasRegroups.find(([, has]) => has(type));
return hasRegroup ? hasRegroup[0] : has(type) ? type : NONE_STREAM_KEY;
};

export const groupByStreamActions = (
streamActionTypes: Array<string> | ReadonlyArray<string>
streamActionTypes: Array<string> | ReadonlyArray<string>,
regroups: Regroup[] = []
) => {
const has = arrayHas(streamActionTypes);
const hasRegroups: HasRegroup[] = regroups.map(([key, types]) => [
key,
arrayHas(types),
]);
const toKey = createToKey(has, hasRegroups);

return (source$: Observable<Array<AnyAction>>) =>
new Observable<Array<AnyAction>>(subscriber =>
source$.subscribe({
next: actions => {
const group = actions.reduce(
(acc, action) => {
const type = has(action.type) ? action.type : NONE_STREAM_KEY;
if (!acc[type]) {
acc[type] = [];
const key = toKey(action.type);
if (!acc[key]) {
acc[key] = [];
}

acc[type].push(action);
acc[key].push(action);
return acc;
},
{} as Record<string, Array<AnyAction>>
Expand All @@ -35,10 +51,7 @@ export const groupByStreamActions = (
})
).pipe(
notEmptyActions,
groupBy(actions => {
const type = actions[0].type;
return has(type) ? type : NONE_STREAM_KEY;
}),
groupBy(actions => toKey(actions[0].type)),
mergeMap(group$ =>
group$.key === NONE_STREAM_KEY
? group$
Expand Down
7 changes: 6 additions & 1 deletion packages/erd-editor/src/engine/rx-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {
ChangeActionTypes,
HistoryActionTypes,
StreamActionTypes,
StreamRegroupMoveActionTypes,
StreamRegroupScrollActionTypes,
} from '@/engine/actions';
import { EngineContext } from '@/engine/context';
import { createHistory } from '@/engine/history';
Expand Down Expand Up @@ -45,7 +47,10 @@ export function createRxStore(context: EngineContext): RxStore {
const history$ = dispatch$.pipe(
actionsFilter(HistoryActionTypes),
ignoreTagFilter(Tag.shared),
groupByStreamActions(StreamActionTypes)
groupByStreamActions(StreamActionTypes, [
['@@move', StreamRegroupMoveActionTypes],
['@@scroll', StreamRegroupScrollActionTypes],
])
);
const change$ = new Observable<Array<AnyAction>>(subscriber =>
store.subscribe(actions => subscriber.next(actions))
Expand Down

0 comments on commit 9bb888b

Please sign in to comment.