6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Laravel Blade】Cropperで画像の加工をやってみる

6
Posted at

書くこと

  • LaravelにCropper導入
  • Cropperを使った画像データの受け渡し

書かないこと

  • Cropperからもらったデータでの処理
  • CSSなどのUI部分

前提

  • templateはbladeです
  • Laravel 5.6での実装(たぶん、ほかのVersionでもいけます)
  • Composerやnpmでのモジュール導入ができる
  • ある程度のLaravelの前提知識がある
  • 今回のcropperはJQuery用なのでJQueryが読み込まれていること

流れ

  1. Cropperって?
  2. Cropperの準備
  3. Cropperの読み込み
  4. Cropperの最適化

1. Cropperって?

  1. 必要なモジュール準備
  • フロントの実装
  • バックエンドの実装

1. 必要なモジュール準備

croppergit) & jquery

  • JavaScriptを使った画像加工の便利なモジュール。
  • 基本的には擬似加工処理をするだけで実際の加工は裏側で行う(はず)

2. Cropperの準備

Laravelで使うnodeにて管理できるのでnpm(nodeオーケストレーション)で準備する。

1. Cropperのinstall

コンソール画面にて以下のコマンドを入力する

npm install cropper

2. Cropperのファイルを配備

Laravelにあるwebpackの機能を使いCropperで使うファイルをpublicディレクトリ配下に置く。
publicにcopyしておくことで、勝手に更新されたり、気づかないうちに差分が出て動かなくなるなどを防ぐのが目的。

webpack.mix.js に記載

mix.copy('node_modules/cropper/dist/cropper.min.css', 'public/css/cropper.min.css').version();
mix.copy('node_modules/cropper/dist/cropper.min.js', 'public/js/cropper.min.js').version();

3. Cropperの読み込み

読み込みたい箇所に記載

<link href="{{ mix('css/cropper.min.css') }}" rel="stylesheet">
<script src="{{ mix('js/cropper.min.js') }}"></script>

4. Cropperの最適化

HTML部分(blade)

<!-- cropperの領域 -->
<div id="img-cropper-image" data-name="image">
  <div class="close-area">
    <i class="fa fa-times" aria-hidden="true"></i>
  </div>
  <div class="wrapper"></div>
  <div class="btn btn-primary">画像を加工する</div>
</div>

{!! Form::open(['route' => ['store'], 'files' => true]) !!}
<div class="cropper-file" data-name="image">
    {{ Form::file('image', ['id' => 'datafile']) }}
    <label for="datafile">画像を選ぶ</label>

    <!-- プレビューが表示される枠 -->
    <div class="img-preview">
        @if($image)
            {{ Html::image($image->path, null, ['width' => '420px']) }}
        @endif
    </div>

    <!-- Cropperで計算したデータをformで送るためのhidden要素 -->
    {{ Form::hidden('image_cropp_width', null) }}
    {{ Form::hidden('image_cropp_height', null) }}
    {{ Form::hidden('image_cropp_x', null) }}
    {{ Form::hidden('image_cropp_y', null) }}
</div>
{{!! Form::close() !!}}

JS部分

<script>
  $(function () {
    // 「画像を加工する」もしくはモーダルを閉じたことで発火
    // CropperのデータをHTMLに挿入する
    $('[id="img-cropper-image"]').on('click', '.btn,.fa-times', function () {
      var imgCropper = $(this).parents('[id="img-cropper-image"]');
      var imageName = imgCropper.data('name');
      var data = imgCropper.find('.wrapper > img').cropper('getData');

      $('input[name="'+ imageName +'_cropp_width"]').val(Math.round(data.width));
      $('input[name="'+ imageName +'_cropp_height"]').val(Math.round(data.height));
      $('input[name="'+ imageName +'_cropp_x"]').val(Math.round(data.x));
      $('input[name="'+ imageName +'_cropp_y"]').val(Math.round(data.y));
      imgCropper.css({'width':'0','height':'0','position':'static'});
    });

    // ファイルがアップロードされたことで発火
    // Cropperを起動する
    $('[id^="datafile"]').on('change', function (e) {
      var file = e.target.files[0],
      reader = new FileReader(),
      previewDiv = $(this).parents('.cropper-file').find(".img-preview"),
      croppDiv = $('#img-cropper-' + $(this).parents('.cropper-file').data('name'));

      // 画像ファイル以外の場合は何もしない
      if(file.type.indexOf("image") < 0){
        return false;
      }
      // check over 2MB
      if (file.size > 2097152) {
        alert('お手数ですが、画像のサイズは2MB以下のものをご用意ください。');
        return;
      }

      img = new Image();
      img.onload = function () {
        // ファイル読み込みが完了した際のイベント登録
        reader.onload = (function(file) {
          return function(e) {
            //既存のプレビューを削除
            previewDiv.empty();
            // .prevewの領域の中にロードした画像を表示するimageタグを追加
            previewDiv.append($('<img>').attr({
              src: e.target.result,
              title: file.name
            })).show();

            croppDiv.css({'width':'100%','height':'100%','position':'fixed'}).show();

            //既存のcropper用画像を削除
            croppDiv.find('.wrapper').empty();
            // #img-cropperの領域の中にロードした画像を表示するimageタグを追加
            var appendImage = $('<img>').attr({
              src: e.target.result,
              title: file.name
            });
            croppDiv.find('.wrapper').append(appendImage);
            appendImage.ready(function () {
              var image = croppDiv.find('img');
              image.cropper({
                preview: previewDiv,
                @if(isset($aspectRatio) && $aspectRatio)
                aspectRatio: 3 / 2,
                @endif
              });
            });
          };
        })(file);
        reader.readAsDataURL(file);
      };
      img.src = (window.URL || window.webkitURL).createObjectURL(file);
    });
  });
</script>

おわりに

冒頭にも書いたんですが、CSS部分は一切記載ないので
このままつかってもうまく動かないと思います。あくまでJSとHTML(blade)部分の
参考と思ってください。

余力あればGitにコードあげます笑

6
5
1

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
6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?