[Canvas] 이미지 에디터 만들기 3 : 이미지 회전 기능 구현
마릴린벅시
2024. 8. 26. 17:06ㆍ프론트엔드
이번엔 이미지 회전 기능을 구현해보자.
캔버스의 회전 방식은 객체의 중앙 축을 중심으로 객체를 회전 시키는 방식이 아니다.
자세한 내용은 이 링크를 참고하자.
어쨌든 캔버스 회전 방식대로 회전시키면 이미지가 제자리에서 회전하는게 아니라 원을 그리며 회전한다.
우리는 이미지 중심축을 기준으로 이미지가 회전하도록 만들 것이다.
⭐️ 이미지 회전 함수 구현
일단 canvas의 회전 방식이 어떻게 동작하는지 보기 위해
Konva의 Node에 내장된 rotate함수를 사용해보자.
import { useCallback, useEffect, useRef, useState } from 'react';
import Konva from 'konva';
import { Stage } from 'konva/lib/Stage';
import { Layer } from 'konva/lib/Layer';
import { Node } from 'konva/lib/Node';
import { Transformer } from 'konva/lib/shapes/Transformer';
const CANVAS_SIZE = 512;
export default function Canvas2() {
const source = '/images/bottle.jpeg';
const stageRef = useRef<Stage | null>(null);
const layerRef = useRef<Layer | null>(null);
const imageRef = useRef<Node | null>(null);
const transformerRef = useRef<Transformer | null>(null);
const [degree, setDegree] = useState(0);
//...이전 코드 생략
function rotateImage() {
if (imageRef.current) {
imageRef.current.rotate(90);
setDegree(degree + 90);
}
}
//...다음 코드 생략
return (
<section id='canvas_container'>
<div
id='container'
onMouseEnter={onFocus}
onMouseLeave={onFocusOut}
onTouchStart={onFocus}
></div>
<div className='btn_container'>
<button className='rotate_btn' onClick={rotateImage}>
회전하기
</button>
</div>
</section>
);
}
보는 바와 같이 이미지의 top-left부분을 중심축으로 회전하기 때문에
이미지가 원을 그리며 회전한다.
⭐️ 회전할 각도를 구하는 함수 구현
이제 우리가 원하는 방식으로 회전하도록 만들기 위해 rotateImage함수를 수정해보자.
rotateAroundCenter함수를 추가해준다. 여기 계산식에는 삼각함수등 어려운 개념이 들어간다.
canvas를 잘 다루려면 여러분들이 수학을 공부해야 하는 이유다.
하지만 우리에겐 구글링과 gpt가 있어서 괜찮다.
import { useCallback, useEffect, useRef, useState } from 'react';
import Konva from 'konva';
import { Stage } from 'konva/lib/Stage';
import { Layer } from 'konva/lib/Layer';
import { Node } from 'konva/lib/Node';
import { Transformer } from 'konva/lib/shapes/Transformer';
import { rotateAroundCenter } from '../utils/image.utils';
const CANVAS_SIZE = 512;
export default function Canvas2() {
const source = '/images/bottle.jpeg';
const stageRef = useRef<Stage | null>(null);
const layerRef = useRef<Layer | null>(null);
const imageRef = useRef<Node | null>(null);
const transformerRef = useRef<Transformer | null>(null);
const [degree, setDegree] = useState(0);
//..이전코드 생략
function rotateImage() {
if (imageRef.current) {
//변경할 이미지 객체, 변경할 각을 인자로 전달
rotateAroundCenter(imageRef.current, degree + 90);
//현재 각도를 저장. 이 때 다음 각도가 360일 경우 0도로 초기화해주고
//아직 360가 아닐 경우 현재 각에 90도를 더해준다.
setDegree(degree + 90 === 360 ? 0 : degree + 90);
}
}
//..다음코드 생략
return (
<section id='canvas_container'>
<div
id='container'
onMouseEnter={onFocus}
onMouseLeave={onFocusOut}
onTouchStart={onFocus}
></div>
<div className='btn_container'>
<button className='rotate_btn' onClick={rotateImage}>
회전하기
</button>
</div>
</section>
);
}
//주어진 점을 원점을 기준으로 지정된 각도(라디안)만큼 회전시킨 좌표를 리턴.
const rotatePoint = ({ x, y }: { x: number; y: number }, rad: number) => {
const rcos = Math.cos(rad);
const rsin = Math.sin(rad);
return { x: x * rcos - y * rsin, y: y * rcos + x * rsin };
};
//Node 객체를 특정 각도로 회전시키고, 회전 후에도 그 중심이 고정되도록 위치를 조정함.
export function rotateAroundCenter(node: Node, rotation: number) {
const topLeft = {
x: -(node.width() * node.scaleX()) / 2,
y: -(node.height() * node.scaleY()) / 2,
};
const current = rotatePoint(topLeft, Konva.getAngle(node.rotation()));
const rotated = rotatePoint(topLeft, Konva.getAngle(rotation));
const dx = rotated.x - current.x,
dy = rotated.y - current.y;
node.rotation(rotation);
node.x(node.x() + dx);
node.y(node.y() + dy);
}
여기까지 따라왔다면 이미지가 정상적으로 회전하는 것을 볼 수 있다.
⭐️ 최종 코드 깃헙에서 보기
아래의 레포를 clone받은 뒤 4c75fc3커밋으로 체크아웃 하면 여기까지의 코드를 볼 수 있다.
https://github.com/seoulsaram/canvas-search
GitHub - seoulsaram/canvas-search
Contribute to seoulsaram/canvas-search development by creating an account on GitHub.
github.com
반응형
'프론트엔드' 카테고리의 다른 글
[Canvas] 이미지 에디터 만들기 5 : Redo, Undo기능 구현 (1) | 2024.08.26 |
---|---|
[Canvas] 이미지 에디터 만들기 4 : 이미지 중앙정렬 기능 구현 (0) | 2024.08.26 |
[Canvas] 이미지 에디터 만들기 2 : 이미지 바운딩 박스 구현 (0) | 2024.08.26 |
[Canvas] 이미지 에디터 만들기 1: 캔버스에 이미지 띄우기 (1) | 2024.08.26 |
HTML Canvas로 이미지 편집기 만들기 (feat. Konva.js) (0) | 2024.08.26 |