LoginSignup
0
1

More than 1 year has passed since last update.

StimulusJSでCropper.jsを使ってみた

Last updated at Posted at 2022-08-26

タイトルの通り、StimulusJSでCropper.jsを使ってみました。
最近の自分は、StimulusJSのキャッチアップしています。なので、布教がてらに実装例を紹介しようと思います。

よくあるユースケースだとクロップ後の画像をサーバに送信しがちですが、この画面では、画像のクロップ範囲 のみ をサーバに送信します。

スクリーンショット 2022-08-26 19.24.24.png

よくある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はいいぞ。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1