Skip to content
14 changes: 11 additions & 3 deletions client/src/hooks/canvas/useDrawing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export const useDrawing = (
if (position === 'middle') {
operation.redrawCanvas();
} else {
if (strokeData.points.length > 2) {
if (strokeData.points.length > 3) {
operation.applyFill(strokeData);
} else {
operation.drawStroke(strokeData);
Expand Down Expand Up @@ -155,14 +155,22 @@ export const useDrawing = (
);
state.setInkRemaining((prev: number) => Math.max(0, prev - pixelsUsed));

// 졜근 3개 점 μœ μ§€
currentDrawingPoints.current.push(point);

const drawingData = createDrawingData([...currentDrawingPoints.current]);

const { id, position } = state.crdtRef.current.addStroke(drawingData);
state.currentStrokeIdsRef.current.push(id);
renderStroke(drawingData, position);

currentDrawingPoints.current = [point];
// 점이 3개 이상일 λ•Œ κ·Έ 이전 점 μ‚­μ œ
if (currentDrawingPoints.current.length >= 3) {
const [, p1, curr] = currentDrawingPoints.current;

// μ΅œμ‹  점만 남기기
currentDrawingPoints.current = [p1, curr];
}

return {
type: CRDTMessageTypes.UPDATE,
Expand Down Expand Up @@ -322,7 +330,7 @@ export const useDrawing = (
if (position === 'middle' || existingEntryIndex !== -1 || isDeactivated) {
operation.redrawCanvas();
} else if (stroke) {
if (stroke.points.length > 2) {
if (stroke.points.length > 3) {
operation.applyFill(stroke);
} else {
operation.drawStroke(stroke);
Expand Down
53 changes: 39 additions & 14 deletions client/src/hooks/canvas/useDrawingOperation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,29 +82,54 @@ export const useDrawingOperation = (
[currentColor, brushSize],
);

const drawStroke = useCallback((drawingData: DrawingData) => {
const drawStroke = (drawingData: DrawingData): void => {
const { ctx } = getCanvasContext(canvasRef);
const { points, style } = drawingData;

if (points.length === 0) return;

// μŠ€νƒ€μΌ μ„€μ •
ctx.strokeStyle = style.color;
ctx.fillStyle = style.color;
ctx.lineWidth = style.width;
ctx.beginPath();
ctx.lineCap = 'round';
ctx.lineJoin = 'round';

if (points.length === 1) {
const point = points[0];
ctx.arc(point.x, point.y, style.width / 2, 0, Math.PI * 2);
ctx.fill();
} else {
ctx.moveTo(points[0].x, points[0].y);
points.slice(1).forEach((point) => ctx.lineTo(point.x, point.y));
ctx.stroke();
// path μ„€μ •
ctx.beginPath();

// 점의 κ°œμˆ˜μ— λ”°λ₯Έ 그리기 처리
switch (points.length) {
case 1: {
// 단일 점은 μ›μœΌλ‘œ ν‘œν˜„
ctx.arc(points[0].x, points[0].y, style.width / 2, 0, Math.PI * 2);
ctx.fill();
break;
}
case 2: {
// 두 점은 μ§μ„ μœΌλ‘œ μ—°κ²°
ctx.moveTo(points[0].x, points[0].y);
ctx.lineTo(points[1].x, points[1].y);
ctx.stroke();
break;
}
case 3: {
// μ„Έ 점은 λΆ€λ“œλŸ¬μš΄ κ³‘μ„ μœΌλ‘œ μ—°κ²°
const [p0, p1, p2] = points;

// λΉ„νŠΈ 연산을 μ‚¬μš©ν•œ 쀑간점 계산
// x >> 1은 x / 2와 λ™μΌν•˜μ§€λ§Œ 더 빠름
const mid1x = (p0.x + p1.x) >> 1;
const mid1y = (p0.y + p1.y) >> 1;
const mid2x = (p1.x + p2.x) >> 1;
const mid2y = (p1.y + p2.y) >> 1;

// 쀑간점 객체 생성을 ν”Όν•˜κ³  직접 μ’Œν‘œ μ‚¬μš©
ctx.moveTo(mid1x, mid1y);
ctx.quadraticCurveTo(p1.x, p1.y, mid2x, mid2y);
ctx.stroke();
break;
}
}
}, []);
};

const redrawCanvas = useCallback(() => {
if (!state.crdtRef.current) return;
Expand All @@ -114,7 +139,7 @@ export const useDrawingOperation = (

const activeStrokes = state.crdtRef.current.getActiveStrokes();
for (const { stroke } of activeStrokes) {
if (stroke.points.length > 2) applyFill(stroke);
if (stroke.points.length > 3) applyFill(stroke);
else drawStroke(stroke);
}
}, [drawStroke]);
Expand Down
1 change: 1 addition & 0 deletions client/src/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const router = createBrowserRouter(
v7_fetcherPersist: true,
v7_normalizeFormMethod: true,
v7_partialHydration: true,
v7_skipActionErrorRevalidation: true,
},
},
);
Loading