Skip to content

Commit 4b3900b

Browse files
authored
Merge pull request #16 from Visual-Regression-Tracker/37-ignore-draw
37 ignore draw
2 parents 673f0f2 + d78fb6b commit 4b3900b

File tree

5 files changed

+104
-23
lines changed

5 files changed

+104
-23
lines changed

package-lock.json

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"dependencies": {
66
"@material-ui/core": "^4.9.11",
77
"@material-ui/icons": "^4.9.1",
8+
"@material-ui/lab": "^4.0.0-alpha.56",
89
"@testing-library/jest-dom": "^4.2.4",
910
"@testing-library/react": "^9.5.0",
1011
"@testing-library/user-event": "^7.2.1",

src/components/DrawArea.tsx

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { FunctionComponent } from "react";
22
import { Stage, Layer, Image } from "react-konva";
33
import { RectConfig } from "konva/types/shapes/Rect";
4-
import Rectangle from "./Rectangle";
4+
import Rectangle, { MIN_RECT_SIDE_PIXEL } from "./Rectangle";
55
import { KonvaEventObject } from "konva/types/Node";
66
import { IgnoreArea } from "../types/ignoreArea";
77

@@ -25,6 +25,7 @@ interface IDrawArea {
2525
React.Dispatch<React.SetStateAction<{ x: number; y: number }>>
2626
];
2727
stageScaleState: [number, React.Dispatch<React.SetStateAction<number>>];
28+
drawModeState: [boolean, React.Dispatch<React.SetStateAction<boolean>>];
2829
}
2930
const DrawArea: FunctionComponent<IDrawArea> = ({
3031
image,
@@ -37,20 +38,67 @@ const DrawArea: FunctionComponent<IDrawArea> = ({
3738
stageOffsetState,
3839
stageInitPosState,
3940
stagePosState,
41+
drawModeState,
4042
}) => {
4143
const [stageInitPos, setStageInitPos] = stageInitPosState;
4244
const [stageOffset, setStageOffset] = stageOffsetState;
4345
const [stagePos, setStagePos] = stagePosState;
4446
const [stageScale] = stageScaleState;
4547
const [isDrag, setIsDrag] = React.useState(false);
4648

49+
const [isDrawMode, setIsDrawMode] = drawModeState;
50+
const [isDrawing, setIsDrawing] = React.useState(isDrawMode);
51+
52+
const handleContentMousedown = (e: any) => {
53+
if (!isDrawMode) return;
54+
55+
const newArea: IgnoreArea = {
56+
id: Date.now().toString(),
57+
x: Math.round((e.evt.layerX - stageOffset.x) / stageScale),
58+
y: Math.round((e.evt.layerY - stageOffset.y) / stageScale),
59+
width: MIN_RECT_SIDE_PIXEL,
60+
height: MIN_RECT_SIDE_PIXEL,
61+
};
62+
setIgnoreAreas([...ignoreAreas, newArea]);
63+
setSelectedRectId(newArea.id);
64+
setIsDrawing(true);
65+
};
66+
67+
const handleContentMouseup = (e: any) => {
68+
if (isDrawing) {
69+
setIsDrawing(!isDrawing);
70+
setIsDrawMode(false);
71+
}
72+
};
73+
74+
const handleContentMouseMove = (e: any) => {
75+
if (!isDrawMode) return;
76+
77+
if (isDrawing) {
78+
// update the current rectangle's width and height based on the mouse position + stage scale
79+
const mouseX = (e.evt.layerX - stageOffset.x) / stageScale;
80+
const mouseY = (e.evt.layerY - stageOffset.y) / stageScale;
81+
82+
const newShapesList = ignoreAreas.map((i) => {
83+
if (i.id === selectedRectId) {
84+
// new width and height
85+
i.width = Math.max(Math.round(mouseX - i.x), MIN_RECT_SIDE_PIXEL);
86+
i.height = Math.max(Math.round(mouseY - i.y), MIN_RECT_SIDE_PIXEL);
87+
return i;
88+
}
89+
return i;
90+
});
91+
setIgnoreAreas(newShapesList);
92+
}
93+
};
94+
4795
return (
4896
<div
4997
style={{
5098
transform: `translate3d(${stagePos.x}px, ${stagePos.y}px, 0px)`,
5199
}}
52100
onMouseMove={(event) => {
53-
if (isDrag && !selectedRectId) {
101+
if (!isDrawMode && isDrag && !selectedRectId) {
54102
event.preventDefault();
55103
setStagePos({
56104
x: event.clientX - stageInitPos.x,
@@ -83,12 +131,15 @@ const DrawArea: FunctionComponent<IDrawArea> = ({
83131
transform: `scale(${stageScale})`,
84132
transformOrigin: "top left",
85133
}}
134+
onContentMousedown={handleContentMousedown}
135+
onContentMouseup={handleContentMouseup}
136+
onContentMouseMove={handleContentMouseMove}
86137
>
87138
<Layer>
88139
<Image
89140
image={image}
90141
onMouseOver={(event) => {
91-
document.body.style.cursor = "grab";
142+
document.body.style.cursor = isDrawMode ? "crosshair" : "grab";
92143
}}
93144
onMouseDown={(event) => {
94145
document.body.style.cursor = "grabbing";
@@ -117,8 +168,12 @@ const DrawArea: FunctionComponent<IDrawArea> = ({
117168

118169
rects[i].x = Math.round(newAttrs.x || 0);
119170
rects[i].y = Math.round(newAttrs.y || 0);
120-
rects[i].width = Math.round(newAttrs.width || 0);
121-
rects[i].height = Math.round(newAttrs.height || 0);
171+
rects[i].width = Math.round(
172+
newAttrs.width || MIN_RECT_SIDE_PIXEL
173+
);
174+
rects[i].height = Math.round(
175+
newAttrs.height || MIN_RECT_SIDE_PIXEL
176+
);
122177

123178
setIgnoreAreas(rects);
124179
}}

src/components/Rectangle.jsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React from "react";
22
import { Rect, Transformer } from "react-konva";
33

4+
export const MIN_RECT_SIDE_PIXEL = 5;
5+
46
const Rectangle = ({ shapeProps, isSelected, onSelect, onChange }) => {
57
const shapeRef = React.useRef();
68
const trRef = React.useRef();
@@ -59,8 +61,8 @@ const Rectangle = ({ shapeProps, isSelected, onSelect, onChange }) => {
5961
x: node.x(),
6062
y: node.y(),
6163
// set minimal value
62-
width: Math.max(5, node.width() * scaleX),
63-
height: Math.max(node.height() * scaleY),
64+
width: Math.max(MIN_RECT_SIDE_PIXEL, node.width() * scaleX),
65+
height: Math.max(MIN_RECT_SIDE_PIXEL, node.height() * scaleY),
6466
});
6567
}}
6668
onMouseOver={(event) => {
@@ -82,7 +84,10 @@ const Rectangle = ({ shapeProps, isSelected, onSelect, onChange }) => {
8284
rotateEnabled={false}
8385
boundBoxFunc={(oldBox, newBox) => {
8486
// limit resize
85-
if (newBox.width < 5 || newBox.height < 5) {
87+
if (
88+
newBox.width < MIN_RECT_SIDE_PIXEL ||
89+
newBox.height < MIN_RECT_SIDE_PIXEL
90+
) {
8691
return oldBox;
8792
}
8893
return newBox;

src/components/TestDetailsModal.tsx

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
Box,
1212
makeStyles,
1313
} from "@material-ui/core";
14+
import { ToggleButton } from "@material-ui/lab";
1415
import { TestRun } from "../types";
1516
import {
1617
testRunService,
@@ -37,11 +38,7 @@ import { TestRunDetails } from "./TestRunDetails";
3738
import useImage from "use-image";
3839
import { routes } from "../constants";
3940
import { NoImagePlaceholder } from "./NoImageAvailable";
40-
import {
41-
useTestRunDispatch,
42-
updateTestRun,
43-
selectTestRun,
44-
} from "../contexts";
41+
import { useTestRunDispatch, updateTestRun, selectTestRun } from "../contexts";
4542

4643
const useStyles = makeStyles((theme) => ({
4744
imageContainer: {
@@ -89,6 +86,7 @@ const TestDetailsModal: React.FunctionComponent<{
8986
testRun.diffName && staticService.getImage(testRun.diffName)
9087
);
9188

89+
const [isDrawMode, setIsDrawMode] = useState(false);
9290
const [isDiffShown, setIsDiffShown] = useState(false);
9391
const [selectedRectId, setSelectedRectId] = React.useState<string>();
9492

@@ -219,20 +217,15 @@ const TestDetailsModal: React.FunctionComponent<{
219217
</Typography>
220218
</Grid>
221219
<Grid item>
222-
<IconButton
220+
<ToggleButton
221+
value={"drawMode"}
222+
selected={isDrawMode}
223223
onClick={() => {
224-
const newArea: IgnoreArea = {
225-
id: Date.now().toString(),
226-
x: 0,
227-
y: 0,
228-
width: 150,
229-
height: 100,
230-
};
231-
setIgnoreAreas([...ignoreAreas, newArea]);
224+
setIsDrawMode(!isDrawMode);
232225
}}
233226
>
234227
<Add />
235-
</IconButton>
228+
</ToggleButton>
236229
</Grid>
237230
<Grid item>
238231
<IconButton
@@ -351,6 +344,7 @@ const TestDetailsModal: React.FunctionComponent<{
351344
stagePosState={[stagePos, setStagePos]}
352345
stageInitPosState={[stageInitPos, setStageInitPos]}
353346
stageOffsetState={[stageOffset, setStageOffset]}
347+
drawModeState={[false, setIsDrawMode]}
354348
/>
355349
</div>
356350
</Grid>
@@ -384,6 +378,7 @@ const TestDetailsModal: React.FunctionComponent<{
384378
stagePosState={[stagePos, setStagePos]}
385379
stageInitPosState={[stageInitPos, setStageInitPos]}
386380
stageOffsetState={[stageOffset, setStageOffset]}
381+
drawModeState={[isDrawMode, setIsDrawMode]}
387382
/>
388383
</div>
389384
</Grid>
@@ -415,6 +410,7 @@ const TestDetailsModal: React.FunctionComponent<{
415410
stagePosState={[stagePos, setStagePos]}
416411
stageInitPosState={[stageInitPos, setStageInitPos]}
417412
stageOffsetState={[stageOffset, setStageOffset]}
413+
drawModeState={[isDrawMode, setIsDrawMode]}
418414
/>
419415
</div>
420416
</Grid>

0 commit comments

Comments
 (0)