Reactで画像の一部をクロップする機能を実装しました。自分のメモ程度にまとめました。
ライブラリ
実装の都合上react-image-crop の方が合っていたのでこちらを使用しました。他にcrop用のライブラリはあります。
react-easy-crop
実装
ライブラリをインストールします。
npm i react-image-crop --save
インストールするとReactCrop
タグが使用できます。このタグでcropするためのイメージを囲みます。
ReactCropタグの中に別の要素も配置できるので画像の上にテキストや図形なども配置したい場合は、react-image-crop
が合っているかもしれません。
function CropDemo({ src }) {
const [crop, setCrop] = useState<Crop>()
return (
<ReactCrop crop={crop} onChange={c => setCrop(c)}>
<Image src={src} />
</ReactCrop>
)
}
cropの四角の座標、width,heightがcropの値として更新されるようになります。
このようにすることでcropする四角の初期値を設定できます。unitはpxか%で指定できます。
const [crop, setCrop] = useState<Crop>({
unit: '%',
x: 25,
y: 25,
width: 50,
height: 50
})
実際はこのようなカスタムフックを作成しました。
スタイルはReactCropタグでstyle属性より指定することもできます。
初期値は%
ですが、一度でも操作するとunitの値はpx
になります。一度でも操作した場合に保存することができるようにisEnableSave
の条件式を指定しました。
import { useState } from 'react';
import { Crop } from 'react-image-crop';
export const useImageCrop = () => {
const [crop, setCrop] = useState<Crop>({
unit: '%',
x: 50,
y: 50,
width: 15,
height: 15,
});
const isEnableSave =
crop.width > 0 && crop.height > 0 && crop.unit === 'px';
const cropSelectionElement = document.querySelector(
'.ReactCrop__crop-selection'
) as HTMLElement;
if (cropSelectionElement) {
cropSelectionElement.style.border = '2px solid #fff';
cropSelectionElement.style.opacity = '1';
cropSelectionElement.style.backgroundImage = 'none';
cropSelectionElement.style.animation = 'none';
}
return {
crop,
setCrop,
isEnableSave
};
};
keepSelection属性を追加しcropする四角の枠が常に表示され続けるようにしました。これがないと別のところをクリックした場合四角が消えてしまいます。
<ReactCrop
crop={crop}
onChange={(c) => setCrop(c)}
keepSelection
minHeight={1}
minWidth={1}
style={{
cursor: 'initial',
}}
>
画像の拡大縮小や回転してcropすることも可能ですが、座標を取得して何か別の操作をしたい場合などは補正する必要が出てきます。
保存の処理があるなら保存時に補正するか、onChangeで補正した値をsetCrop(c)
としてcropを更新していくなどの処理が必要になってくるかもしれません。
まとめ
他にもいろいろな属性が追加できるようです。
割と簡単に実装できました。
こちらでライブラリのdemoが参照できます。