react-image-cropを用いたトリミング機能を追加するところで躓いたので、自分へのメモとして書きました。
##state
index.tsx
const [src, setSrc] = useState<any>(null);
const [crop, setCrop] = useState<Crop>({
unit: "%",
x: 0,
y: 0,
width: 50,
height: 50,
aspect: 1
});
const [imageRef, setImageRef] = useState<HTMLImageElement | null>(null);
##画像を読み込む関数
index.tsx
const onSelectFile = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.files !== null) {
const reader = new FileReader();
reader.addEventListener("load", () =>
setSrc(reader.result);
);
reader.readAsDataURL(event.target.files[0]);
}
};
const onImageLoaded = (image: HTMLImageElement) =>
setImageRef(image);
};
##画像をトリミングする関数
index.tsx
const onCropChange = (crop: Crop) => {
setCrop(crop);
};
const onCropComplete = (crop: any) => {
if(imageRef && crop.width && crop.height){
const canvas = document.createElement("canvas")
const scaleX = imageRef.naturalWidth / imageRef.width;
const scaleY = imageRef.naturalHeight / imageRef.height;
canvas.width = crop.width
canvas.height = crop.height
const ctx = canvas.getContext("2d")
if (ctx !== null) {
ctx.drawImage(
imageRef,
crop.x * scaleX,
crop.y * scaleY,
crop.width * scaleX,
crop.height * scaleY,
0,
0,
crop.width,
crop.height
)
}
}
};
##コンポーネント
index.tsx
import React, {useState} from "react";
import ReactCrop, {Crop} from "react-image-crop";
import "react-image-crop/dist/ReactCrop.css";
export const CropModal: React.FC<Props> = props => {
...
return (
<div>
<input type="file" accept="image/*" onChange={onSelectFile} />
{src && (
<ReactCrop
src={src}
crop={crop}
ruleOfThirds
onImageLoaded={onImageLoaded}
onComplete={onCropComplete}
onChange={onCropChange}
/>
)}
<div/>
)
}
今回トリミングした画像データをサーバーにアップロードするには、canvasのデータをBlobデータに変換し、axiosを用いてDataFormとして送る。
canvasの画像データをblobに変換し、axiosでpost.する方法
##参考にした記事
react-image-crop - npm
react-image-crop dom CodeSandBox