cropper.jsというブラウザ上で画像をリサイズするjsライブラリがあり、
画像をブラウザ上で任意のサイズに切り取ってからアップロードするという処理などに使ったりします。
非常に優れたライブラリなのですが、アスペクト比を一定の範囲内で可変にするという動きが出来なかったので実装してみました。
課題
アスペクト比を指定するにはsetAspectRatio
メソッドで比率を指定すればよいのですが、
setAspectRatio
を呼び出すと選択範囲をリセットする動きもします。
変更したいアスペクト比が予め固定でよければ、公式サイトにあるデモのようにアスペクト比変更ボタンを置けばいいのですが、
今回やりたかったことはアスペクト比を自由に変更しつつ、範囲を指定することでした。
例)1:1〜16:9の間で自由に指定
対応内容
単純に、
- 現在の選択範囲を取得
- その時点でのアスペクト比を確認
- 範囲外なら、範囲内のアスペクト比に変更
- 選択範囲がリセットされるので、1で取得した選択範囲に上書き
という動きで対応しました。
具体的には、cropperの選択範囲を変更するたびに実行されるcropmove
トリガーに以下の処理を入れます。
const aspectLowerLimit = アスペクト比の下限;
const aspectUpperLimit = アスペクト比の上限;
// 現在の選択範囲
const cropBoxData = cropper.getCropBoxData();
// 現在のアスペクト比
const aspect = cropBoxData.width / cropBoxData.height;
if (aspect < aspectLowerLimit) {
// 下限を下回る場合、下限に変更
cropper.setAspectRatio(aspectLowerLimit);
} else if (aspect > aspectUpperLimit) {
// 上限を上回る場合、上限に変更
cropper.setAspectRatio(aspectUpperLimit);
} else {
// 範囲内なら自由に選択できるのでアスペクト比の指定を無効化
cropper.setAspectRatio(NaN);
}
// 選択範囲がリセットされるので先程取得した選択範囲で上書き
cropper.setCropBoxData(cropBoxData);
完成品
サンプルとして、1:1から16:9の範囲でアスペクト比を自由に変えられるものを作成しました。
See the Pen Cropper.jsのアスペクト比を範囲内で調整可能にするサンプル by kametter (@kametter) on CodePen.
微妙にカクカクするときがありますが、概ね期待通りに動いています。
アスペクト比の判定が前回と同じならsetAspectRaito
を呼び出さないようにする処理を追加して負荷軽減できればいいんですが、カーソルの判定のためか境界を行ったり来たりするようでいい感じにしあげられませんでした。
カーソルの移動方向を見ればいい感じにできるかもしれないので、折を見て調査してみます。