pickingElements.forEach((element) => {
pickingContext.save();
pickingContext.translate(
element.translate.x + element.rect.width / 2,
element.translate.y + element.rect.height / 2
);
pickingContext.rotate(15 * (Math.PI / 180));
pickingContext.translate(
-element.rect.width / 2,
-element.rect.height / 2
);
const scale = 1.2;
pickingContext.scale(scale, scale);
pickingContext.translate(
element.rect.width / 2,
element.rect.height / 2
);
pickingContext.drawImage(
element.pickImage,
element.rect.left,
element.rect.top,
element.rect.width,
element.rect.height,
-(element.rect.width / 2),
-(element.rect.height / 2),
element.rect.width,
element.rect.height
);
pickingContext.restore();
});
const updatePickingCanvas = () => {
if (pickingContext) {
pickingElements.forEach((element) => {
pickingContext.drawImage(
element.pickImage,
element.rect.left,
element.rect.top,
element.rect.width,
element.rect.height,
element.translate.x,
element.translate.y,
element.rect.width,
element.rect.height
);
});
}
};
먼저 위치값에 대한 변환을 적용하려했다.
현재 하나의 Picking Canvas에서
1. 새로운 picking Element를 그려주는 작업
2. 다 그려진 element의 영역을 이미지로 변환하여 picking Elements로 추가하고 elements를 Canvas에 그려주는 작업
이 두 작업을 하고 있어서 발생한 문제였다.
<div className="canvas_container">
<canvas className="picking_canvas" ref={pickingDrawCanvas} />
<canvas className="main_canvas" ref={mainCanvas} />
<canvas className="picking_canvas" ref={pickingCanvas} />
</div>
1번의 작업을 위해 pickingDrawCanvas를 하나 더 만들어줘서 element List에 추가하기 전에 현재 그려지고 있는 element만을 위한 렌더링 작업을 하도록 변경하였다.
이제 translate, rotate, scale 처리를 해줘야한다. 먼저 translate와 rotate 처리를 해주자
pickingContext.save();
pickingContext.translate(
element.translate.x + element.rect.width / 2,
element.translate.y + element.rect.height / 2
);
pickingContext.rotate(15 * (Math.PI / 180));
pickingContext.drawImage(
element.pickImage,
element.rect.left,
element.rect.top,
element.rect.width,
element.rect.height,
-(element.rect.width / 2),
-(element.rect.height / 2),
element.rect.width,
element.rect.height
);
pickingContext.restore();
먼저 도형의 정가운데 원점으로 translate 이동해준다. 이렇게 해야 원점을 중심으로 Rotate하게 된다.
그리고 DrawImage 함수에서
기존에 translate(0, 0)일때는 이미지의 시작점 (top,left)이 translate.x y만큼 이동한 위치
현재는 translate(x+width/2, y+height/2)만큼 적용되어 있으므로 이미지의 시작점(top, left)는 -width/2, height/2가 된다.
여기까지 했으면 translate와 rotate에 대해서는 문제없이 동작한다.
현재 코드에서 rotate 아래에 scale을 추가하면 원점을 중심으로 크기가 변경된다.
하지만 그림처럼 각각의 크기 조정 버튼을 클릭하고 scale변경 시 원점이 중심이 아닌 각각 다른 곳으로 설정해줘야 알맞은 동작을 하게 된다.
pickingElements.forEach((element) => {
pickingContext.save();
pickingContext.translate(
element.translate.x + element.rect.width / 2,
element.translate.y + element.rect.height / 2
);
pickingContext.rotate(15 * (Math.PI / 180));
pickingContext.translate(
-element.rect.width / 2,
-element.rect.height / 2
);
const scale = 1.2;
pickingContext.scale(scale, scale);
pickingContext.translate(
element.rect.width / 2,
element.rect.height / 2
);
pickingContext.drawImage(
element.pickImage,
element.rect.left,
element.rect.top,
element.rect.width,
element.rect.height,
-(element.rect.width / 2),
-(element.rect.height / 2),
element.rect.width,
element.rect.height
);
pickingContext.restore();
});
context가 아닌 element.style.transform을 위 코드처럼 변경해야하는 경우도 있는데 다음과 같이 변경해주면 된다.
const translate = `translate(${el.rect.left}px, ${el.rect.top}px)`;
const rotate = `rotate(${15}deg)`;
const translateOrigin = `translate(${-el.rect.width / 2}px, ${-el.rect.height / 2}px)`;
const scale = `scale(${1.2}, ${1.2})`;
const translateRevert = `translate(${el.rect.width / 2}px, ${el.rect.height / 2}px)`;
canvasRef.current.style.transform = `${translate} ${rotate} ${translateOrigin} ${scale} ${translateRevert}`;
'👨💻 javascript' 카테고리의 다른 글
Chorme Extensions 업비트 (0) | 2024.02.26 |
---|---|
[React로 화이트보드] Canvas Color Picking + 선택된 요소 변형 동시에 적용하기 (0) | 2024.02.05 |
[React로 화이트보드] 마우스를 이용한 자연스러운 Rotate, Scale 구현하기 (0) | 2024.02.05 |
[React로 화이트보드] Draw Element Picking 구현 (2) | 2024.01.10 |
[React로 화이트보드] Canvas 동적생성 (0) | 2024.01.09 |