Skip to content

Commit af2505e

Browse files
authored
Merge pull request #13 from boostcampwm-2024/refactor/#12
feat: Enhance drawing with Bezier curve interpolation
2 parents bf5b7bf + aa50a46 commit af2505e

File tree

3 files changed

+51
-17
lines changed

3 files changed

+51
-17
lines changed

client/src/hooks/canvas/useDrawing.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export const useDrawing = (
103103
if (position === 'middle') {
104104
operation.redrawCanvas();
105105
} else {
106-
if (strokeData.points.length > 2) {
106+
if (strokeData.points.length > 3) {
107107
operation.applyFill(strokeData);
108108
} else {
109109
operation.drawStroke(strokeData);
@@ -155,14 +155,22 @@ export const useDrawing = (
155155
);
156156
state.setInkRemaining((prev: number) => Math.max(0, prev - pixelsUsed));
157157

158+
// 최근 3개 점 유지
158159
currentDrawingPoints.current.push(point);
160+
159161
const drawingData = createDrawingData([...currentDrawingPoints.current]);
160162

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

165-
currentDrawingPoints.current = [point];
167+
// 점이 3개 이상일 때 그 이전 점 삭제
168+
if (currentDrawingPoints.current.length >= 3) {
169+
const [, p1, curr] = currentDrawingPoints.current;
170+
171+
// 최신 점만 남기기
172+
currentDrawingPoints.current = [p1, curr];
173+
}
166174

167175
return {
168176
type: CRDTMessageTypes.UPDATE,
@@ -322,7 +330,7 @@ export const useDrawing = (
322330
if (position === 'middle' || existingEntryIndex !== -1 || isDeactivated) {
323331
operation.redrawCanvas();
324332
} else if (stroke) {
325-
if (stroke.points.length > 2) {
333+
if (stroke.points.length > 3) {
326334
operation.applyFill(stroke);
327335
} else {
328336
operation.drawStroke(stroke);

client/src/hooks/canvas/useDrawingOperation.ts

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -82,29 +82,54 @@ export const useDrawingOperation = (
8282
[currentColor, brushSize],
8383
);
8484

85-
const drawStroke = useCallback((drawingData: DrawingData) => {
85+
const drawStroke = (drawingData: DrawingData): void => {
8686
const { ctx } = getCanvasContext(canvasRef);
8787
const { points, style } = drawingData;
8888

89-
if (points.length === 0) return;
90-
89+
// 스타일 설정
9190
ctx.strokeStyle = style.color;
9291
ctx.fillStyle = style.color;
9392
ctx.lineWidth = style.width;
94-
ctx.beginPath();
9593
ctx.lineCap = 'round';
9694
ctx.lineJoin = 'round';
9795

98-
if (points.length === 1) {
99-
const point = points[0];
100-
ctx.arc(point.x, point.y, style.width / 2, 0, Math.PI * 2);
101-
ctx.fill();
102-
} else {
103-
ctx.moveTo(points[0].x, points[0].y);
104-
points.slice(1).forEach((point) => ctx.lineTo(point.x, point.y));
105-
ctx.stroke();
96+
// path 설정
97+
ctx.beginPath();
98+
99+
// 점의 개수에 따른 그리기 처리
100+
switch (points.length) {
101+
case 1: {
102+
// 단일 점은 원으로 표현
103+
ctx.arc(points[0].x, points[0].y, style.width / 2, 0, Math.PI * 2);
104+
ctx.fill();
105+
break;
106+
}
107+
case 2: {
108+
// 두 점은 직선으로 연결
109+
ctx.moveTo(points[0].x, points[0].y);
110+
ctx.lineTo(points[1].x, points[1].y);
111+
ctx.stroke();
112+
break;
113+
}
114+
case 3: {
115+
// 세 점은 부드러운 곡선으로 연결
116+
const [p0, p1, p2] = points;
117+
118+
// 비트 연산을 사용한 중간점 계산
119+
// x >> 1은 x / 2와 동일하지만 더 빠름
120+
const mid1x = (p0.x + p1.x) >> 1;
121+
const mid1y = (p0.y + p1.y) >> 1;
122+
const mid2x = (p1.x + p2.x) >> 1;
123+
const mid2y = (p1.y + p2.y) >> 1;
124+
125+
// 중간점 객체 생성을 피하고 직접 좌표 사용
126+
ctx.moveTo(mid1x, mid1y);
127+
ctx.quadraticCurveTo(p1.x, p1.y, mid2x, mid2y);
128+
ctx.stroke();
129+
break;
130+
}
106131
}
107-
}, []);
132+
};
108133

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

115140
const activeStrokes = state.crdtRef.current.getActiveStrokes();
116141
for (const { stroke } of activeStrokes) {
117-
if (stroke.points.length > 2) applyFill(stroke);
142+
if (stroke.points.length > 3) applyFill(stroke);
118143
else drawStroke(stroke);
119144
}
120145
}, [drawStroke]);

client/src/routes.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export const router = createBrowserRouter(
5555
v7_fetcherPersist: true,
5656
v7_normalizeFormMethod: true,
5757
v7_partialHydration: true,
58+
v7_skipActionErrorRevalidation: true,
5859
},
5960
},
6061
);

0 commit comments

Comments
 (0)