タイトルの通り、StimulusJSでCropper.jsを使ってみました。
最近の自分は、StimulusJSのキャッチアップしています。なので、布教がてらに実装例を紹介しようと思います。
よくあるユースケースだとクロップ後の画像をサーバに送信しがちですが、この画面では、画像のクロップ範囲 のみ をサーバに送信します。
よくあるWEBアプリでは、画像をS3などのストレージサービスに保存しますが、自分が作っているWEBアプリではherokuで動いていることもあり、DBに何でも突っ込みたかったので画像をBASE64でエンコードしてDB内に保存しました。また、登録した画像は公開することを考えていないので、パフォーマンスは考慮しなくていい、という理由もあります。
この実装では、「編集時のクロップエリアの復元」「クロップエリアの送信」ができます。
実装は次の通りです。
<h1><%= @sketch.name %>の切り取り範囲の編集</h1>
<% crop_data = @sketch.crop_data %>
<%= form_with model: @sketch, url: feature_splatoon2_sketch_path(@sketch), method: :put, data: { controller: "image-crop", target: "image-crop.form", "image-crop-crop_data-value": crop_data } do |f| %>
<%= render "shared/validation_errors", f: f %>
<canvas id="image-canvas"></canvas>
<div>
<img src='data:<%= @sketch.encoded_image %>' id="sketch-image" style="display:none;">
</div>
<%= f.hidden_field :crop_data, data: { target: "image-crop.crop_data" } %>
<div class="form-group row mt-5">
<a href="#" class="form-control btn btn-primary" data-action="click->image-crop#submit">更新する</a>
</div>
<% end %>
import { Controller } from "@hotwired/stimulus"
import Cropper from 'cropperjs';
// Connects to data-controller="image-crop"
export default class extends Controller {
static values = {
cropData: Object,
}
static targets = [
'crop_data',
'form',
]
connect() {
const sketchImage = document.getElementById('sketch-image');
const cvs = document.getElementById('image-canvas');
const ctx = cvs.getContext('2d');
const img = new Image();
img.src = sketchImage.src;
cvs.width = img.width;
cvs.height = img.height;
const onload = function(instance) {
ctx.drawImage(img, 0, 0);
instance.cropperValue = new Cropper(cvs, {
zoomable: false,
aspectRatio: 320 / 120,
background: true,
responsive: false,
viewMode: 1,
dragMode: "none",
minCropBoxWidth: 320,
minCropBoxHeight: 120,
ready() {
instance.cropperValue.setData(instance.cropDataValue)
},
})
};
img.onload = onload(this)
}
submit(event) {
event.preventDefault();
this.crop_dataTarget.value = JSON.stringify(this.cropperValue.getData());
this.formTarget.submit();
}
}
ソースコードは公開しています。
StimulusJSはいいぞ。