Skip to content

Commit

Permalink
feat: better panzoom functionalities with react-roi
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Daniel Kostro <[email protected]>
  • Loading branch information
moonayyur and stropitek authored Feb 5, 2024
1 parent 4affcac commit 63f4cab
Show file tree
Hide file tree
Showing 7 changed files with 1,500 additions and 783 deletions.
2,162 changes: 1,428 additions & 734 deletions package-lock.json

Large diffs are not rendered by default.

32 changes: 16 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"@commitlint/config-conventional": "^17.6.3",
"@simbathesailor/use-what-changed": "^2.0.0",
"@swc/plugin-emotion": "^2.5.67",
"@types/react": "^18.0.28",
"@types/react": "^18.2.48",
"@types/react-dom": "^18.0.11",
"@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.57.1",
Expand All @@ -48,33 +48,33 @@
"eslint-config-cheminfo-react": "^9.1.1",
"eslint-config-cheminfo-typescript": "^11.3.1",
"husky": "^8.0.3",
"ky": "^0.25.1",
"modern-normalize": "^2.0.0",
"prettier": "^2.8.8",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.11.2",
"typescript": "^5.0.2",
"vite": "^4.3.2",
"ky": "^0.25.1",
"modern-normalize": "^2.0.0"
"typescript": "~5.1.0",
"vite": "^4.3.2"
},
"dependencies": {
"@lukeed/uuid": "^2.0.1",
"@emotion/react": "^11.11.0",
"@emotion/styled": "^11.11.0",
"@lukeed/uuid": "^2.0.1",
"cheminfo-font": "^1.9.0",
"fifo-logger": "^0.6.1",
"file-collection": "^0.2.0",
"filelist-utils": "^1.9.0",
"image-js": "0.0.0-next-ce6a4f4a28",
"immer": "^10.0.2",
"react-science": "^0.26.2",
"lodash": "^4.17.21",
"react-use": "^17.4.0",
"react-plot": "^1.4.2",
"react-map-interaction": "^2.1.0",
"react-kbs": "^2.1.1",
"react-icons": "^4.10.1",
"react-d3-utils": "^1.0.0",
"filelist-utils": "^1.9.0",
"file-collection": "^0.2.0",
"fifo-logger": "^0.6.1",
"cheminfo-font": "^1.9.0"
"react-icons": "^4.10.1",
"react-kbs": "^2.1.1",
"react-plot": "^1.4.2",
"react-roi": "^0.14.0",
"react-science": "^0.26.2",
"react-use": "^17.4.0"
},
"volta": {
"node": "18.16.0",
Expand Down
77 changes: 50 additions & 27 deletions src/components/ImageViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import styled from '@emotion/styled';
import { Image, Mask, writeCanvas } from 'image-js';
import {
CSSProperties,
MutableRefObject,
memo,
useCallback,
useEffect,
useMemo,
useRef,
} from 'react';
import { MapInteractionCSS } from 'react-map-interaction';
import { RoiContainer, RoiProvider, useTargetRef } from 'react-roi';

import useImage from '../hooks/useImage';
import useView from '../hooks/useView';
Expand All @@ -33,14 +33,23 @@ const canvasStyle: CSSProperties = {
imageRendering: 'pixelated',
};

function TargetCanvas({ imageToShow }: { imageToShow: Image | Mask }) {
const canvasRef: MutableRefObject<HTMLCanvasElement> = useTargetRef() as any;

useEffect(() => {
if (canvasRef.current === null) return;
writeCanvas(imageToShow, canvasRef.current);
}, [canvasRef, imageToShow]);

return <canvas ref={canvasRef} style={canvasStyle} />;
}

function ImageViewer({
identifier,
showOriginal = false,
image,
annotable = false,
}: ImageViewerProps) {
const canvasRef = useRef<HTMLCanvasElement>(null);

const view = useView();
const viewDispatch = useViewDispatch();

Expand All @@ -51,14 +60,14 @@ function ImageViewer({
return showOriginal ? original : pipelined;
}, [image, original, pipelined, showOriginal]);

const panZoom = useMemo(
() =>
const panZoom = useMemo(() => {
return (
view.imageViewerProps[identifier] || {
translation: { x: 0, y: 0 },
scale: 1,
},
[identifier, view.imageViewerProps],
);
translation: [0, 0],
}
);
}, [identifier, view.imageViewerProps]);

const setPanZoom = useCallback(
(panZoom) => {
Expand All @@ -70,24 +79,38 @@ function ImageViewer({
[identifier, viewDispatch],
);

useEffect(() => {
if (canvasRef.current === null) return;
writeCanvas(imageToShow, canvasRef.current);
}, [imageToShow]);

return (
<MapInteractionCSS value={panZoom} onChange={setPanZoom} maxScale={20}>
<RelativeBox>
<canvas ref={canvasRef} style={canvasStyle} />
{annotable && (
<ROIAnnotations
width={imageToShow?.width}
height={imageToShow?.height}
identifier={identifier}
/>
)}
</RelativeBox>
</MapInteractionCSS>
<RoiProvider
initialConfig={{
zoom: {
initial: panZoom,
min: 0.1,
max: 30,
spaceAroundTarget: 0,
},
resizeStrategy: 'contain',
mode: 'select',
}}
onAfterZoomChange={setPanZoom}
>
<RoiContainer
target={<TargetCanvas imageToShow={imageToShow} />}
style={{
width: '100%',
height: '100%',
}}
>
<RelativeBox>
{annotable && (
<ROIAnnotations
width={imageToShow?.width}
height={imageToShow?.height}
identifier={identifier}
/>
)}
</RelativeBox>
</RoiContainer>
</RoiProvider>
);
}

Expand Down
4 changes: 3 additions & 1 deletion src/components/layout/CenterPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ function CenterPanel() {
Object.keys(images).map((identifier) => ({
id: identifier,
title: <TabTitle>{images[identifier].metadata.name}</TabTitle>,
content: <ImageViewer identifier={identifier} annotable />,
content: (
<ImageViewer key={identifier} identifier={identifier} annotable />
),
})),
[images],
);
Expand Down
1 change: 1 addition & 0 deletions src/demo/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const StyledSidebar = styled.div`
color: white;
background-color: cornflowerblue;
padding: 0 20px;
overflow-y: auto;
h1 {
font-size: 1.5rem;
Expand Down
5 changes: 1 addition & 4 deletions src/state/view/ViewReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,7 @@ export interface ViewState {
imageViewerProps: Record<
string,
{
translation: {
x: number;
y: number;
};
translation: [number, number];
scale: number;
}
>;
Expand Down
2 changes: 1 addition & 1 deletion src/state/view/actions/ImageViewerActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ViewState } from '../ViewReducer';

interface PanZoomData {
scale: number;
translation: { x: number; y: number };
translation: [number, number];
}

export type SetPanZoomAction = ViewActionType<
Expand Down

0 comments on commit 63f4cab

Please sign in to comment.