【Python・Flask】JQueryとCroppieで画像をトリミングしてS3にアップロードする①

JQueryとCroppieでトリミングした画像をサーバサイド【Python・Flask】にAjaxを使ってPOSTし、S3にアップロードするまでの実装手順を紹介していきます。

画像トリミング機能の流れ

今回のトリミング機能は以下の流れで処理していきます。今回の記事ではパート1として1〜4までの手順を記述し、5〜6はパート2として次回記事で紹介していきます。

  1. file inputから画像を選択
  2. 選択後、モーダル とcroppieのトリミング機能を表示
  3. トリミングしたい形でサイズと枠を合わせたら画像トリミングボタンをクリック
  4. 画像をトリミング処理
  5. トリミングされた画像をAjaxでサーバサイドへPOST
  6. サーバーサイド(python,flask)でトリミングした画像をAWS S3にアップロード

使用するライブラリ

・Croppie

Croppie – a javascript image cropper

Croppie uses canvas.drawImage(…) to manipulate images. Thus, images must obey the CORS policy. More info can be found here. Croppie is dependent on it’s container being visible when the bind method is called. This can be an issue when your croppie component is inside a modal that isn’t shown.

・Bootstrap Modal

Modal

Use Bootstrap’s JavaScript modal plugin to add dialogs to your site for lightboxes, user notifications, or completely custom content.

Croppieファイルをインストール

以下のGitHubページからcroppie.jsとcroppie.css をインストールし、プロジェクト内に設置します。Headタグ内に以下を記述。

Foliotek/Croppie

Bower: bower install croppie Npm: npm install croppie Download: croppie.js & croppie.css cdnjs.com provides croppie via cdn https://cdnjs.com/libraries/croppie https://cdnjs.cloudflare.com/ajax/libs/croppie/{version}/croppie.min.css https://cdnjs.cloudflare.com/ajax/libs/croppie/{version}/croppie.min.js Documentation First, thanks for contributing. This project is difficult to maintain with one person. Here’s a “checklist” of things to remember when contributing to croppie. Don’t forget to update the documentation.

 <!-- Jquery -->

 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!-- croppie.css -->
   <link href="{{ url_for('static', filename='css/croppie.css')}}" rel="stylesheet" type="text/css">
   <script src="{{ url_for('static', filename='js/croppie.js')}}"></script>

<!-- BOOTSTRAP -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>

ファイルinputを追加

最初に画像をアップロードするためHTMLのFile Inputを追加します。idにupload_imageを指定。このidは画像選択後、画像トリミング用のモーダル を表示させる際の発火用に使用します。

 <div class="panel panel-default">
    <div class="panel-body" align="left">
      <h5><i class="far fa-images"></i>サークル画像アップロード</h5>
      <div class="custom-file">
         <input type="file" name="upload_image" id="upload_image" class="custom-file-input" accept="image/*" />
         <label class="custom-file-label" for="customFile">Choose file</label>
      </div>
    </div>
 </div>

bootstrapのmodalを追加

先述した通り、画像選択後、画像トリミング用のモーダル を表示させます。まず、bootstrapからmodalのコードをコピーアンドペーストで持ってきます。追加で必要なコードはアップロードした画像を表示させるためid=”image_demo”をmodal-body内に記述します。その下に画像トリミングとアップロードボタンを設置します。これで下準備が終了したので、続いてJQueryで画像トリミングの処理部分のコードを記述していきます。

       

<!-- #########Modal################################### -->

      <div style="z-index: 3;" class="modal fade" id="uploadimageModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
        <div class="modal-dialog modal-lg" role="document">
          <div class="modal-content">
            <div class="modal-header">
              <h5 class="modal-title" id="exampleModalLabel">メディアを編集</h5>
            </div>
            <div class="modal-body">
              <div id="image_demo" style="width:350px; margin-top:10px"></div>
                <div class="col-md-4" style="padding-top:10px;">
                  <button class="btn btn-outline-success crop_image">画像をトリミング&アップロード</button>
                </div>
              </div>
              <div class="modal-footer">
                <button type="button" class="btn btn-outline-secondary" id="croppie_close" data-dismiss="modal">閉じる</button>
              </div>
            </div>
          </div>
        </div>

今回、レスポンシブにも対応させたいので、window.matchMediaを使用してデバイスごとにサイズを調整します。続いてcroppieの基本設定のコードを記述します。画像アップロード後、id=image_demoに表示された画像がトリミングの対象です。boundaryは画像のサイズ、viewportは内枠のサイズ。詳しくはcroppieのサイトをご参照ください。

Croppieの基本設定

#レスポンシブ対応
$(document).ready(function(){
if (window.matchMedia( '(min-width: 320px) and (max-width: 639px)' ).matches) {
  viewportWidth = 270
  viewportHeight = 170
  boundaryWidth = 290
  boundaryHeight = 180
} else if (window.matchMedia( '(min-width: 640px) and (max-width: 1023px)' ).matches) {
  viewportWidth = 460
  viewportHeight = 290
  boundaryWidth = 480
  boundaryHeight = 290
} else {
  viewportWidth = 650
  viewportHeight = 400
  boundaryWidth = 700
  boundaryHeight = 400
 }

#croppieの初期設定
$image_crop = $('#image_demo').croppie({
 enableExif: true,
  viewport: {
   width: viewportWidth,
   height:viewportHeight,
   type:'square' //circle
  },
  boundary: {
   width: boundaryWidth,
   height: boundaryHeight
  }
});

画像選択後モーダル を表示させる

画像選択されたら、画像をバインドしcroppieに画像URLをセットしてあげます。同時にbootstrapのモーダル を表示させます。これで、モーダル が表示されcroppieの初期化は終了です。

$('#upload_image').on('change', function(){
  var reader = new FileReader();
  reader.onload = function (event) {
    $image_crop.croppie('bind', {
    url: event.target.result
   }).then(function(){
     console.log('jQuery bind complete');
   });
 }
 reader.readAsDataURL(this.files[0]);
  $('#uploadimageModal').addClass('show');
  $('#uploadimageModal').css('display','block');
});

ボタンをクリックしたら画像をトリミングする

画像をトリミング&アップロードボタンをクリックすると画像がトリミングされた画像データを取得できるので、Ajaxでサーバーサイドにデータを渡します。最後に画像トリミングが終了したらモーダル を閉じるためのコードを記述します。サーバサイドに画像データを渡してS3にアップロードする手順については次回記事で記述していきます。

#ボタンをクリックしたら
$('.crop_image').click(function(event){
 $image_crop.croppie('result', {
   type: 'canvas',
   size: 'viewport'
 }).then(function(response){
  //  console.log(response)
   $.ajax({
     url:"/image",
     type: "POST",
     data:{"image": response},
     success:function(data) {  
        パート②で記述
     }
   });
  })
 });

#モーダル を閉じる
$(document).ready(function(){
  $('#croppie_close').click(function() {
    $('#uploadimageModal').removeClass('show');
    $('#uploadimageModal').css('display','none');
    $('input[type=file]').val('');
  });
});
  });

パート2の記事ではサーバサイド側の処理を以下の二つに分けて記述していきます。

  • トリミングされた画像をAjaxでサーバサイドへPOST
  • サーバーサイド(python,flask)でトリミングした画像をAWS S3にアップロード
>文系エンジニア大学生の技術ブログ

文系エンジニア大学生の技術ブログ

社会が多様化していく中、大学生の学生生活も多様であるべきと考えています。主にエンジニア向けにITやプログラミングなどの技術系と大学生向けに休学、留学、海外生活、トビタテ留学、長期インターンに関する記事を書いています。