Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[READY_TO_REVIEW]feature/#433 Inconsistent behavior with zooming dragging elements #445

Merged
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
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { Coords } from '@/core/model';
import { useOffsetZoomToCoords } from './set-off-set-zoom-to-coords.hook';
import { CanvasViewSettingsContext } from '@/core/providers/';
import { renderHook } from '@testing-library/react';
import { setOffSetZoomToCoords } from './set-off-set-zoom-to-coords.helper';
import { CanvasViewSettingsContextModel } from '@/core/providers/canvas-view-settings/canvas-view-settings.model';

describe('useOffsetZoomToCoords', () => {
describe('setOffSetZoomToCoords', () => {
it('should return correct coordinates after applying offset zoom (random normal value #1)', () => {
// Arrange
const inputCoords: Coords = { x: 10, y: 10 };
Expand All @@ -31,22 +29,19 @@ describe('useOffsetZoomToCoords', () => {
setAutoSave: () => {},
};

const wrapper = ({ children }: { children: React.ReactNode }) => (
<CanvasViewSettingsContext.Provider value={initialContextState}>
{children}
</CanvasViewSettingsContext.Provider>
);

// Act
const { result } = renderHook(
() => useOffsetZoomToCoords({ x: inputCoords.x, y: inputCoords.y }),
{ wrapper }
const result = setOffSetZoomToCoords(
inputCoords.x,
inputCoords.y,
initialContextState.viewBoxSize,
initialContextState.canvasViewSettings.canvasSize,
initialContextState.canvasViewSettings.zoomFactor
);

const expected = { x: 20, y: 20 };

// Assert
expect({ x: result.current.x, y: result.current.y }).toEqual({
expect({ x: result.x, y: result.y }).toEqual({
x: expected.x,
y: expected.y,
});
Expand Down Expand Up @@ -77,21 +72,19 @@ describe('useOffsetZoomToCoords', () => {
setAutoSave: () => {},
};

const wrapper = ({ children }: { children: React.ReactNode }) => (
<CanvasViewSettingsContext.Provider value={initialContextState}>
{children}
</CanvasViewSettingsContext.Provider>
);

// Act
const { result } = renderHook(
() => useOffsetZoomToCoords({ x: inputCoords.x, y: inputCoords.y }),
{ wrapper }
const result = setOffSetZoomToCoords(
inputCoords.x,
inputCoords.y,
initialContextState.viewBoxSize,
initialContextState.canvasViewSettings.canvasSize,
initialContextState.canvasViewSettings.zoomFactor
);

const expected = { x: 312.5, y: 67.5 };
// Assert
expect({ x: result.current.x, y: result.current.y }).toEqual({

expect({ x: result.x, y: result.y }).toEqual({
x: expected.x,
y: expected.y,
});
Expand Down Expand Up @@ -122,21 +115,18 @@ describe('useOffsetZoomToCoords', () => {
setAutoSave: () => {},
};

const wrapper = ({ children }: { children: React.ReactNode }) => (
<CanvasViewSettingsContext.Provider value={initialContextState}>
{children}
</CanvasViewSettingsContext.Provider>
);

// Act
const { result } = renderHook(
() => useOffsetZoomToCoords({ x: inputCoords.x, y: inputCoords.y }),
{ wrapper }
const result = setOffSetZoomToCoords(
inputCoords.x,
inputCoords.y,
initialContextState.viewBoxSize,
initialContextState.canvasViewSettings.canvasSize,
initialContextState.canvasViewSettings.zoomFactor
);

const expected = { x: 26.66666666666667, y: 300 };
// Assert
expect({ x: result.current.x, y: result.current.y }).toEqual({
expect({ x: result.x, y: result.y }).toEqual({
x: expected.x,
y: expected.y,
});
Expand Down Expand Up @@ -173,21 +163,18 @@ describe('useOffsetZoomToCoords', () => {
setAutoSave: () => {},
};

const wrapper = ({ children }: { children: React.ReactNode }) => (
<CanvasViewSettingsContext.Provider value={initialContextState}>
{children}
</CanvasViewSettingsContext.Provider>
);

// Act
const { result } = renderHook(
() => useOffsetZoomToCoords({ x: inputCoords.x, y: inputCoords.y }),
{ wrapper }
const result = setOffSetZoomToCoords(
inputCoords.x,
inputCoords.y,
initialContextState.viewBoxSize,
initialContextState.canvasViewSettings.canvasSize,
initialContextState.canvasViewSettings.zoomFactor
);

const expected = { x: 55156935716294670, y: 461168781986723840 };
// Assert
expect({ x: result.current.x, y: result.current.y }).toEqual({
expect({ x: result.x, y: result.y }).toEqual({
x: expected.x,
y: expected.y,
});
Expand Down Expand Up @@ -218,21 +205,18 @@ describe('useOffsetZoomToCoords', () => {
setAutoSave: () => {},
};

const wrapper = ({ children }: { children: React.ReactNode }) => (
<CanvasViewSettingsContext.Provider value={initialContextState}>
{children}
</CanvasViewSettingsContext.Provider>
);

// Act
const { result } = renderHook(
() => useOffsetZoomToCoords({ x: inputCoords.x, y: inputCoords.y }),
{ wrapper }
const result = setOffSetZoomToCoords(
inputCoords.x,
inputCoords.y,
initialContextState.viewBoxSize,
initialContextState.canvasViewSettings.canvasSize,
initialContextState.canvasViewSettings.zoomFactor
);

const expected = { x: 0, y: 0 };
// Assert
expect({ x: result.current.x, y: result.current.y }).toEqual({
expect({ x: result.x, y: result.y }).toEqual({
x: expected.x,
y: expected.y,
});
Expand Down
26 changes: 26 additions & 0 deletions src/common/helpers/set-off-set-zoom-to-coords.helper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Size } from '@/core/model';
import { CANVAS_MAX_HEIGHT, CANVAS_MAX_WIDTH } from '@/core/providers';

export const setOffSetZoomToCoords = (
x: number,
y: number,
viewBoxSize: Size,
canvasSize: Size,
zoomFactor: number
) => {
const MULTIPLIER_TO_SET_OFFSET_TO_CANVAS_DIMENSION_WIDTH =
CANVAS_MAX_WIDTH / canvasSize.width;
const MULTIPLIER_TO_SET_OFFSET_TO_CANVAS_DIMENSION_HEIGHT =
CANVAS_MAX_WIDTH / canvasSize.height;
const adjustedWidth = CANVAS_MAX_WIDTH / viewBoxSize.width;
const adjustedHeight = CANVAS_MAX_HEIGHT / viewBoxSize.height;

const newX =
(x / (zoomFactor * adjustedWidth) / adjustedWidth) *
MULTIPLIER_TO_SET_OFFSET_TO_CANVAS_DIMENSION_WIDTH;
const newY =
(y / (zoomFactor * adjustedHeight) / adjustedHeight) *
MULTIPLIER_TO_SET_OFFSET_TO_CANVAS_DIMENSION_HEIGHT;

return { x: newX, y: newY };
};
4 changes: 4 additions & 0 deletions src/pods/canvas/canvas-svg.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { CANVAS_MAX_HEIGHT, CANVAS_MAX_WIDTH } from '@/core/providers';
interface Props {
viewBoxSize: Size;
canvasSize: Size;
zoomFactor: number;
canvasSchema: DatabaseSchemaVm;
onUpdateTablePosition: UpdatePositionFn;
onToggleCollapse: (tableId: GUID, fieldId: GUID) => void;
Expand All @@ -25,6 +26,7 @@ export const CanvasSvgComponent: React.FC<Props> = props => {
const {
viewBoxSize,
canvasSize,
zoomFactor,
canvasSchema,
onUpdateTablePosition,
onToggleCollapse,
Expand Down Expand Up @@ -65,6 +67,8 @@ export const CanvasSvgComponent: React.FC<Props> = props => {
isSelected={canvasSchema.selectedElementId === table.id}
selectTable={onSelectElement}
isTabletOrMobileDevice={isTabletOrMobileDevice}
viewBoxSize={viewBoxSize}
zoomFactor={zoomFactor}
/>
))}
</svg>
Expand Down
16 changes: 11 additions & 5 deletions src/pods/canvas/canvas.pod.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { mFlix } from './m-flix.mock.data';
import { CanvasAccessible } from './components/canvas-accessible';
import useAutosave from '@/core/autosave/autosave.hook';
import { CANVAS_MAX_WIDTH } from '@/core/providers';

import { setOffSetZoomToCoords } from '@/common/helpers/set-off-set-zoom-to-coords.helper';
const HEIGHT_OFFSET = 200;
export const CanvasPod: React.FC = () => {
const { openModal, closeModal, modalDialog } = useModalDialogContext();
Expand Down Expand Up @@ -97,10 +97,15 @@ export const CanvasPod: React.FC = () => {

const handleScroll = () => {
if (containerRef.current) {
setScrollPosition({
x: containerRef.current.scrollLeft,
y: containerRef.current.scrollTop,
});
setScrollPosition(
setOffSetZoomToCoords(
containerRef.current.scrollLeft,
containerRef.current.scrollTop,
viewBoxSize,
canvasSize,
zoomFactor
)
);
}
};

Expand Down Expand Up @@ -213,6 +218,7 @@ export const CanvasPod: React.FC = () => {
<CanvasSvgComponent
viewBoxSize={viewBoxSize}
canvasSize={canvasSize}
zoomFactor={zoomFactor}
canvasSchema={canvasSchema}
onUpdateTablePosition={updateTablePosition}
onToggleCollapse={handleToggleCollapse}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ interface Props {
isSelected: boolean;
selectTable: (tableId: GUID) => void;
isTabletOrMobileDevice: boolean;
viewBoxSize: Size;
zoomFactor: number;
}

export const DatabaseTable: React.FC<Props> = ({
Expand All @@ -34,6 +36,8 @@ export const DatabaseTable: React.FC<Props> = ({
isSelected,
selectTable,
isTabletOrMobileDevice,
viewBoxSize,
zoomFactor,
}) => {
const rowHeight = TABLE_CONST.FONT_SIZE + TABLE_CONST.ROW_PADDING;

Expand Down Expand Up @@ -62,7 +66,9 @@ export const DatabaseTable: React.FC<Props> = ({
tableInfo.y,
updatePosition,
totalHeight,
canvasSize
canvasSize,
viewBoxSize,
zoomFactor
);

const handleSelectTable = () => {
Expand Down
43 changes: 29 additions & 14 deletions src/pods/canvas/components/table/table-drag.hook.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,37 @@
import React, { useState, useCallback } from 'react';
import { Size } from '@/core/model';
import { UpdatePositionFn, UpdatePositionItemInfo } from '@/core/providers';

import { setOffSetZoomToCoords } from '@/common/helpers/set-off-set-zoom-to-coords.helper';
export const useDraggable = (
id: string,
initialX: number,
initialY: number,
updatePosition: UpdatePositionFn,
totalHeight: number,
canvasSize: Size
canvasSize: Size,
viewBoxSize: Size,
zoomFactor: number
) => {
const [isDragging, setIsDragging] = useState(false);
const [startDragPosition, setStartDragPosition] = useState({ x: 0, y: 0 });
const [finalInfoAfterDrag, setFinalInfoAfterDrag] =
useState<UpdatePositionItemInfo | null>(null);
const [node, setNode] = React.useState<SVGElement | null>(null);

const ref = React.useCallback((nodeEle: SVGElement): void => {
setNode(nodeEle);
}, []);

const startDrag = (x: number, y: number) => {
const { x: offsetX, y: offsetY } = setOffSetZoomToCoords(
x,
y,
viewBoxSize,
canvasSize,
zoomFactor
);
setStartDragPosition({
x: x - initialX,
y: y - initialY,
x: offsetX - initialX,
y: offsetY - initialY,
});
setIsDragging(true);
};
Expand All @@ -32,7 +40,7 @@ export const useDraggable = (
(event: React.MouseEvent) => {
startDrag(event.clientX, event.clientY);
},
[initialX, initialY]
[initialX, initialY, viewBoxSize]
);

const onTouchStart = useCallback(
Expand All @@ -41,23 +49,30 @@ export const useDraggable = (
const touch = event.touches[0];
startDrag(touch.clientX, touch.clientY);
},
[initialX, initialY]
[initialX, initialY, viewBoxSize]
);

const updateDrag = (x: number, y: number) => {
if (isDragging) {
const newX = x - startDragPosition.x;
const newY = y - startDragPosition.y;

const currentItemInfo = {
const { x: offsetX, y: offsetY } = setOffSetZoomToCoords(
x,
y,
viewBoxSize,
canvasSize,
zoomFactor
);
const newPosition = {
id,
position: { x: newX, y: newY },
position: {
x: offsetX - startDragPosition.x,
y: offsetY - startDragPosition.y,
},
totalHeight,
canvasSize,
};

updatePosition(currentItemInfo, false);
setFinalInfoAfterDrag(currentItemInfo);
updatePosition(newPosition, false);
setFinalInfoAfterDrag(newPosition);
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
} from '@/core/providers/canvas-schema';
import { ADD_COLLECTION_TITLE } from '@/common/components/modal-dialog';
import { SHORTCUTS } from '../../shortcut/shortcut.const';
import { useOffsetZoomToCoords } from './set-off-set-zoom-to-coords.hook';

const BORDER_MARGIN = 40;

Expand All @@ -19,16 +18,11 @@ export const AddCollection = () => {
const { canvasSchema, addTable } = useCanvasSchemaContext();
const { setLoadSample, scrollPosition } = useCanvasViewSettingsContext();

const { x: scrollOffsetX, y: scrollOffsetY } = useOffsetZoomToCoords({
x: scrollPosition.x + BORDER_MARGIN,
y: scrollPosition.y + BORDER_MARGIN,
});

const handleAddTable = (newTable: TableVm) => {
const updatedTable = {
...newTable,
x: scrollOffsetX,
y: scrollOffsetY,
x: scrollPosition.x + BORDER_MARGIN,
y: scrollPosition.y + BORDER_MARGIN,
};

addTable(updatedTable);
Expand Down
Loading
Loading