canvasに画像を描画して千本鳥居を爆速で建築する
キャッキャ \(^o^)/
見栄えを良くしようと思うとめちゃくちゃ面倒くさそうだったのでやーめた
"use client";
import imgFile from "@/assets/torii.png";
import { type MouseEventHandler, useCallback, useEffect, useRef, useState } from "react";
export const Component = () => {
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const imgRef = useRef<HTMLImageElement | null>(null);
const [isDrawing, setIsDrawing] = useState(false);
const loadImg = useCallback(async () => {
const maxWidth = 100; // リサイズ後の最大幅
const maxHeight = 100; // リサイズ後の最大高さ
const originalWidth = imgFile.width;
const originalHeight = imgFile.height;
// アスペクト比を維持したままリサイズ
let width = originalWidth;
let height = originalHeight;
if (width > maxWidth || height > maxHeight) {
const aspectRatio = originalWidth / originalHeight;
if (width > maxWidth) {
width = maxWidth;
height = maxWidth / aspectRatio;
}
if (height > maxHeight) {
height = maxHeight;
width = maxHeight * aspectRatio;
}
}
// 画像を読み込む
const img = new Image(width, height);
return new Promise<HTMLImageElement>((resolve) => {
// 画像が読み込まれたらresolveする
img.onload = () => {
resolve(img);
};
// 画像の読み込みを開始
img.src = imgFile.src;
});
}, []);
useEffect(() => {
(async () => {
const img = await loadImg();
imgRef.current = img;
console.log("画像読み込み完了", img);
})();
}, [loadImg]);
const draw: MouseEventHandler<HTMLCanvasElement> = useCallback((event) => {
if (event.type === "mousedown") {
setIsDrawing(true);
console.log("描画開始");
}
if (!canvasRef.current) {
return;
}
const ctx = canvasRef.current.getContext("2d");
if (!ctx) {
return;
}
const img = imgRef.current;
if (!img) {
return;
}
// クリックした位置を画像の中心にする
const x = event.clientX - img.width / 2;
const y = event.clientY - img.height / 2;
// 画像が読み込まれたら描画
ctx.drawImage(img, x, y, img.width, img.height);
}, []);
useEffect(() => {
if (!isDrawing) {
return;
}
const onWindowMouseUp = () => {
setIsDrawing(false);
console.log("描画終了");
};
window.addEventListener("mouseup", onWindowMouseUp);
return () => {
window.removeEventListener("mouseup", onWindowMouseUp);
};
}, [isDrawing]);
return (
<>
<canvas ref={canvasRef} width={500} height={500} onMouseDown={draw} onMouseMove={isDrawing ? draw : undefined} />
</>
);
};