Merge branch 'fe/feat/canvas-overflow-click' into 'fe/develop'
Feat: 캔버스에 도형 겹칠 때 anchor 선택 가능하도록 변경 See merge request s11-s-project/S11P21S002!40
This commit is contained in:
commit
89026be422
10
frontend/src/components/CanvasControlBar/index.tsx
Normal file
10
frontend/src/components/CanvasControlBar/index.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import { Stage } from 'konva/lib/Stage';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
export default function CanvasControlBar({ stage }: { stage: Stage }) {
|
||||
useEffect(() => {
|
||||
console.log(stage);
|
||||
}, [stage]);
|
||||
|
||||
return <div>CanvasControlBar</div>;
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { Label } from '@/types';
|
||||
import Konva from 'konva';
|
||||
import { useRef, useState } from 'react';
|
||||
import { Group, Line } from 'react-konva';
|
||||
import { useState } from 'react';
|
||||
import { Line } from 'react-konva';
|
||||
import PolygonTransformer from './PolygonTransformer';
|
||||
|
||||
export default function LabelPolygon({
|
||||
@ -9,26 +9,25 @@ export default function LabelPolygon({
|
||||
onSelect,
|
||||
info,
|
||||
stage,
|
||||
dragLayer,
|
||||
}: {
|
||||
isSelected: boolean;
|
||||
onSelect: () => void;
|
||||
info: Label;
|
||||
stage: Konva.Stage;
|
||||
dragLayer: Konva.Layer;
|
||||
}) {
|
||||
const polyRef = useRef<Konva.Line>(null);
|
||||
const [coordinates, setCoordinates] = useState<Array<[number, number]>>(info.coordinates);
|
||||
|
||||
return (
|
||||
<Group zIndex={isSelected ? 2 : 1}>
|
||||
<>
|
||||
<Line
|
||||
points={coordinates.flat()}
|
||||
stroke={info.color}
|
||||
strokeWidth={1}
|
||||
ref={polyRef}
|
||||
onMouseDown={onSelect}
|
||||
onTouchStart={onSelect}
|
||||
strokeScaleEnabled={false}
|
||||
fillAfterStrokeEnabled={false}
|
||||
fill={`${info.color}33`}
|
||||
closed
|
||||
/>
|
||||
@ -37,8 +36,9 @@ export default function LabelPolygon({
|
||||
coordinates={coordinates}
|
||||
setCoordinates={setCoordinates}
|
||||
stage={stage}
|
||||
dragLayer={dragLayer}
|
||||
/>
|
||||
)}
|
||||
</Group>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,16 +1,18 @@
|
||||
import { Label } from '@/types';
|
||||
import Konva from 'konva';
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { Group, Line, Transformer } from 'react-konva';
|
||||
import { Line, Transformer } from 'react-konva';
|
||||
|
||||
export default function LabelRect({
|
||||
isSelected,
|
||||
onSelect,
|
||||
info,
|
||||
dragLayer,
|
||||
}: {
|
||||
isSelected: boolean;
|
||||
onSelect: () => void;
|
||||
onSelect: (evt: Konva.KonvaEventObject<TouchEvent | MouseEvent>) => void;
|
||||
info: Label;
|
||||
dragLayer: Konva.Layer;
|
||||
}) {
|
||||
const rectRef = useRef<Konva.Line>(null);
|
||||
const trRef = useRef<Konva.Transformer>(null);
|
||||
@ -20,6 +22,11 @@ export default function LabelRect({
|
||||
info.coordinates[1],
|
||||
[info.coordinates[1][0], info.coordinates[0][1]],
|
||||
].flat();
|
||||
const handleSelect = (evt: Konva.KonvaEventObject<TouchEvent | MouseEvent>): void => {
|
||||
onSelect(evt);
|
||||
rectRef.current?.moveToTop();
|
||||
trRef.current?.moveToTop();
|
||||
};
|
||||
const handleMoveEnd = () => {
|
||||
const rectPoints = rectRef.current?.points();
|
||||
const points = [
|
||||
@ -33,23 +40,25 @@ export default function LabelRect({
|
||||
useEffect(() => {
|
||||
if (isSelected) {
|
||||
trRef.current?.nodes([rectRef.current as Konva.Node]);
|
||||
trRef.current?.moveTo(dragLayer);
|
||||
trRef.current?.getLayer()?.batchDraw();
|
||||
}
|
||||
}, [isSelected]);
|
||||
}, [dragLayer, isSelected]);
|
||||
|
||||
return (
|
||||
<Group zIndex={isSelected ? 2 : 1}>
|
||||
<>
|
||||
<Line
|
||||
points={coordinates}
|
||||
stroke={info.color}
|
||||
strokeWidth={1}
|
||||
ref={rectRef}
|
||||
onMouseDown={onSelect}
|
||||
onTouchStart={onSelect}
|
||||
onMouseDown={handleSelect}
|
||||
onTouchStart={handleSelect}
|
||||
strokeScaleEnabled={false}
|
||||
fillAfterStrokeEnabled={false}
|
||||
fill={`${info.color}33`}
|
||||
onDragEnd={handleMoveEnd}
|
||||
shadowForStrokeEnabled={false}
|
||||
closed
|
||||
draggable
|
||||
/>
|
||||
@ -66,6 +75,6 @@ export default function LabelRect({
|
||||
onTransformEnd={handleMoveEnd}
|
||||
/>
|
||||
)}
|
||||
</Group>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ interface PolygonTransformerProps {
|
||||
coordinates: Array<[number, number]>;
|
||||
setCoordinates: (coordinates: Array<[number, number]>) => void;
|
||||
stage: Konva.Stage;
|
||||
dragLayer: Konva.Layer;
|
||||
}
|
||||
|
||||
const TRANSFORM_CHANGE_STR = [
|
||||
@ -21,8 +22,8 @@ const TRANSFORM_CHANGE_STR = [
|
||||
'strokeWidthChange',
|
||||
];
|
||||
|
||||
export default function PolygonTransformer({ coordinates, setCoordinates, stage }: PolygonTransformerProps) {
|
||||
const trRef = useRef<Konva.Group>(null);
|
||||
export default function PolygonTransformer({ coordinates, setCoordinates, stage, dragLayer }: PolygonTransformerProps) {
|
||||
const anchorsRef = useRef<Konva.Group>(null);
|
||||
const handleDragMove = (index: number) => (e: Konva.KonvaEventObject<DragEvent>) => {
|
||||
const circle = e.target as Konva.Circle;
|
||||
const pos = circle.position();
|
||||
@ -47,13 +48,13 @@ export default function PolygonTransformer({ coordinates, setCoordinates, stage
|
||||
|
||||
useEffect(() => {
|
||||
const transformEvents = TRANSFORM_CHANGE_STR.join(' ');
|
||||
anchorsRef.current?.moveTo(dragLayer);
|
||||
|
||||
stage.on(transformEvents, () => {
|
||||
if (!trRef.current) return;
|
||||
if (!anchorsRef.current) return;
|
||||
|
||||
const [line, ...anchors] = trRef.current!.children as Konva.Shape[];
|
||||
const anchors = anchorsRef.current!.children as Konva.Shape[];
|
||||
|
||||
line.strokeWidth(1 / stage.getAbsoluteScale().x);
|
||||
anchors.forEach((anchor) => {
|
||||
anchor.scale({
|
||||
x: 1 / stage.getAbsoluteScale().x,
|
||||
@ -65,38 +66,44 @@ export default function PolygonTransformer({ coordinates, setCoordinates, stage
|
||||
return () => {
|
||||
stage.off(transformEvents);
|
||||
};
|
||||
}, [stage]);
|
||||
}, [dragLayer, stage]);
|
||||
|
||||
return (
|
||||
<Group ref={trRef}>
|
||||
<>
|
||||
<Line
|
||||
points={coordinates.flat()}
|
||||
stroke="#00a1ff"
|
||||
strokeWidth={1 / stage.getAbsoluteScale().x}
|
||||
strokeScaleEnabled={true}
|
||||
// strokeWidth={1 / stage.getAbsoluteScale().x}
|
||||
strokeWidth={1}
|
||||
strokeScaleEnabled={false}
|
||||
closed
|
||||
zIndex={1}
|
||||
perfectDrawEnabled={false}
|
||||
shadowForStrokeEnabled={false}
|
||||
listening={false}
|
||||
/>
|
||||
{coordinates.map((point, index) => {
|
||||
return (
|
||||
<Circle
|
||||
key={index}
|
||||
x={point[0]}
|
||||
y={point[1]}
|
||||
radius={5}
|
||||
stroke="#00a1ff"
|
||||
strokeWidth={1}
|
||||
fill="white"
|
||||
draggable
|
||||
onDragMove={handleDragMove(index)}
|
||||
onMouseOver={handleMouseOver}
|
||||
onMouseOut={handleMouseOut}
|
||||
scale={{ x: 1 / stage.getAbsoluteScale().x, y: 1 / stage.getAbsoluteScale().y }}
|
||||
perfectDrawEnabled={false}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Group>
|
||||
<Group ref={anchorsRef}>
|
||||
{coordinates.map((point, index) => {
|
||||
return (
|
||||
<Circle
|
||||
key={index}
|
||||
x={point[0]}
|
||||
y={point[1]}
|
||||
radius={5}
|
||||
stroke="#00a1ff"
|
||||
strokeWidth={1}
|
||||
fill="white"
|
||||
draggable
|
||||
strokeScaleEnabled={false}
|
||||
onDragMove={handleDragMove(index)}
|
||||
onMouseOver={handleMouseOver}
|
||||
onMouseOut={handleMouseOut}
|
||||
scale={{ x: 1 / stage.getAbsoluteScale().x, y: 1 / stage.getAbsoluteScale().y }}
|
||||
perfectDrawEnabled={false}
|
||||
shadowForStrokeEnabled={false}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Group>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ export default function ImageCanvas() {
|
||||
const stageWidth = window.innerWidth;
|
||||
const stageHeight = window.innerHeight;
|
||||
const stageRef = useRef<Konva.Stage>(null);
|
||||
const dragLayerRef = useRef<Konva.Layer>(null);
|
||||
const scale = useRef<number>(0);
|
||||
const imageUrl = '/sample.jpg';
|
||||
const labels = useCanvasStore((state) => state.labels) ?? [];
|
||||
@ -120,6 +121,7 @@ export default function ImageCanvas() {
|
||||
isSelected={label.id === selectedId}
|
||||
onSelect={() => setSelectedId(label.id)}
|
||||
info={label}
|
||||
dragLayer={dragLayerRef.current as Konva.Layer}
|
||||
/>
|
||||
) : (
|
||||
<LabelPolygon
|
||||
@ -128,10 +130,12 @@ export default function ImageCanvas() {
|
||||
onSelect={() => setSelectedId(label.id)}
|
||||
info={label}
|
||||
stage={stageRef.current as Konva.Stage}
|
||||
dragLayer={dragLayerRef.current as Konva.Layer}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</Layer>
|
||||
<Layer ref={dragLayerRef} />
|
||||
</Stage>
|
||||
) : (
|
||||
<div></div>
|
||||
|
Loading…
Reference in New Issue
Block a user