오늘은 핵심 기능구현 두 번째로 드래그 & 드롭에 이어
성냥개비를 회전하는 기능을 만들어 보려고한다

오늘도 재밌게 만들어보자~!
개인적인 공부를 위해 작성하는 블로그입니다. 혹시라도 잘못되거나 부족한 부분이 있다면 댓글로 알려주시면 감사하겠습니다.
💡 핵심 기능 구현
- 성냥개비 드래그 & 드롭
- 성냥개비 회전 (오늘 할 것)
- 퍼즐 정답 검증 시스템
💁🏻 현재 선택된 성냥개비 구현
우선 Image에 onClick을 추가하고 클릭했을때 handleSelect()를 통해 현재 선택된 성냥의 id값을 저장한다.
import { useRef, useEffect, useState } from "react"
import { Stage, Layer, Image, Transformer } from "react-konva"
export default function PuzzleCanvas() {
const [matchsticks, setMatchsticks] = useState([
{ id: "1", x: 50, y: 50, angle: 10 },
{ id: "2", x: 200, y: 100, angle: 30 },
{ id: "3", x: 100, y: 150, angle: 180 },
{ id: "4", x: 150, y: 100, angle: 270 },
]);
const [selectedMatchstick, setSelectedMatchstick] = useState(null)
const imageRef = useRef(null);
// 이미지 로드
useEffect(() => {
const img = new window.Image()
img.src = "/matchstick.webp" // 이미지 경로
img.onload = () => {
imageRef.current = img;
setMatchsticks((sticks) => [...sticks])
};
}, []);
const handleSelect = (id) => {
setSelectedMatchstick((current) => (current === id ? null : id));
};
return (
<Stage
ref={stageRef}
width={window.innerWidth}
height={window.innerHeight}
>
<Layer>
{matchsticks.map((stick) => (
<Image
key={stick.id}
id={stick.id}
x={stick.x}
y={stick.y}
rotation={stick.angle}
width={18}
height={150}
image={imageRef.current}
draggable
onTap={() => handleSelect(stick.id)} // 모바일 지원
onClick={() => handleSelect(stick.id)} // 선택
/>
))}
</Layer>
</Stage>
)
}
모바일에서도 클릭을 지원하려면 onTap을 같이 넣어주면 된다.
👨🏻💻 Transformer로 회전 구현
선택되었을 때와 성량의 위치가 바뀌었을때 useEffect를 통해 선택된 성냥을 찾아서 tr.node() tr.getLayer().batchDraw()로 Transformer를 업데이트 해준다.
export default function PuzzleCanvas() {
const transformerRef = useRef(null);
const stageRef = useRef(null);
(생략)
// Transformer 업데이트
useEffect(() => {
const tr = transformerRef.current;
if (tr) {
if (selectedMatchstick) {
const selectedNode = stageRef.current.findOne(`#${selectedMatchstick}`);
if (selectedNode) {
tr.nodes([selectedNode]) // 선택된 노드에 Transformer 적용
tr.getLayer().batchDraw()
}
} else {
tr.nodes([]) // 선택 해제 시 Transformer 초기화
}
}
}, [selectedMatchstick, matchsticks])
(생략)
return (
<Stage
ref={stageRef}
width={window.innerWidth}
height={window.innerHeight}
>
<Layer>
{matchsticks.map((stick) => (
<Image
(생략)
onTap={() => handleSelect(stick.id)} // 모바일 지원
onClick={() => handleSelect(stick.id)} // 선택
onDragMove={(e) => handleDragMove(e, stick.id)} // 이동
/>
))}
{/* Transformer */}
<Transformer
ref={transformerRef}
rotationSnaps={[0, 90, 180, 270]} // 회전 스냅
anchorSize={10} // 앵커 크기
anchorCornerRadius={3}
centeredScaling={true}
resizeEnabled={false} // 크기 조정 비활성화
/>
</Layer>
</Stage>
)
}
그럼 이렇게 바운딩박스와 함께 회전이 가능해진다

읽어주셔서 감사합니다.
'개발 > 개발로그' 카테고리의 다른 글
[React] 간단한 성냥퍼즐 웹 서비스 만들기 7일차 (Undo, Redo, Remove구현) (0) | 2024.11.25 |
---|---|
[React] 간단한 성냥퍼즐 웹 서비스 만들기 6일차 (리팩토링, History 기능) (0) | 2024.11.24 |
[React] 간단한 성냥퍼즐 웹 서비스 만들기 4일차 (react-konva) (3) | 2024.11.15 |
[React] 간단한 성냥퍼즐 웹 서비스 만들기 3일차 (navbar, darkmode) (2) | 2024.11.14 |
[React] 간단한 성냥퍼즐 웹 서비스 만들기 2일차 (react-router-dom) (1) | 2024.11.13 |