画像編集プラグイン Cropper

Cropperとは

画像についての切り抜き、拡大、縮小、回転操作機能を提供するjQueryプラグイン
画像の縦横比率を固定できるのでサイトの構成にマッチした画像を強制しつつ画像を編集できる。

公式サイト
https://fengyuanchen.github.io/cropper/

設定

ライブラリを公式サイトからGitHub経由でダウンロード

<script src="dist/jquery.js"</script>
<script src="dist/cropper.js"></script>
<link href="dist/cropper.css" rel="stylesheet">

実装

HTML

<div class="cropper-container">
 <p><img src="/webroot/test.jpeg" id="trimed_image" /></p>
</div>
<p><input type="file" id="file_image" required /></p>
<p><input type="button" id="crop_btn" value="画像をトリミングして送信" /></p>

JavaScript

参考:non’s lab

$(function(){
 $('#file_image').on('change', function(event){
  var trimingImage = event.target.files;
  
  // imageタグは1つしかファイルを送信できない仕組みと複数送信する仕組みの二通りある
  if(trimingImage.length > 1){
   console.log(trimingImage.length + 'つのファイルが選択されました。');
   return false;
  }
  // 改めて代入
  trimingImage = trimingImage[0];

  // 画像のチェック
  if(!trimingImage.type.match('image/jp.*') // jpg jpeg でない
   &&!trimingImage.type.match('image/png') // png でない
   &&!trimingImage.type.match('image/gif') // gif でない
   &&!trimingImage.type.match('image/bmp') // bmp でない
  ){
   alert('No Support ' + trimingImage.type + ' type image');
   $(this).val('');
   return false;
  }
  
  var fileReader = new FileReader();
  fileReader.onload = function(e){
   var int32View = new Uint8Array(e.target.result);
   // ファイルのヘッダを参照し、マイムタイプを疑似的に取得
   if((int32View.length>4 && int32View[0]==0xFF && int32View[1]==0xD8 && int32View[2]==0xFF && int32View[3]==0xE0)
   || (int32View.length>4 && int32View[0]==0xFF && int32View[1]==0xD8 && int32View[2]==0xFF && int32View[3]==0xDB)
   || (int32View.length>4 && int32View[0]==0xFF && int32View[1]==0xD8 && int32View[2]==0xFF && int32View[3]==0xD1)
   || (int32View.length>4 && int32View[0]==0x89 && int32View[1]==0x50 && int32View[2]==0x4E && int32View[3]==0x47)
   || (int32View.length>4 && int32View[0]==0x47 && int32View[1]==0x49 && int32View[2]==0x46 && int32View[3]==0x38)
   || (int32View.length=2 && int32View[0]==0x42 && int32View[1]==0x4D && int32View[2]==0x46 && int32View[3]==0x38)
   ){
    // success
    $('#trimed_image').css('display', 'block');
    $('#trimed_image').attr('src', URL.createObjectURL(trimingImage));
    return true;
   } else {
    // failed
    alert('No Support ' + trimingImage.type + ' type image');
    $('#trimed_image').val('');
    return false;
   }
  };
  fileReader.readAsArrayBuffer(trimingImage);
  
  fileReader.onloadend = function(e){
   var image = document.getElementById('trimed_image');
   var button = document.getElementById('crop_btn');

   var croppable = false;
   var cropper = new Cropper(image, {
    aspectRatio: 16 / 9,
    viewMode: 1,
    ready: function () {
     croppable = true;
    },
   });

   // fileReaderが完了した後にボタンクリックイベントを作成する必要あり
   button.onclick = function () {
    var croppedCanvas;

    if (!croppable) {
     alert('トリミングする画像が設定されていません。');
     return false;
    }

    // cropper.jsに用意されている機能
    croppedCanvas = cropper.getCroppedCanvas();
    // 下記toBlob関数はブラウザによって名前が違う
    var blob;
    if(croppedCanvas.toBlob){
     croppedCanvas.toBlob(function(blob){
      var trimedImageForm = new FormData();
      trimedImageForm.append('blob', blob);
      //Ajax送信
      $.ajax({
       url: 'test/upload', // POST送信先
       type: 'post',
       processData: false,
       contentType: false,
       data: trimedImageForm,
      }).done(function( jsonResponse ){
       var responese = $.parseJSON(jsonResponse);
       if(responese.status == 'success'){
        console.log(responese);
        alert('アップロードしました。');
       }else if(responese.status == 'error'){
        alert('画像作成に失敗しました。再度お試しください。\n' + responese.msg);
       }else{
        alert('システムエラーが発生しました。');
       }
      }).fail(function( responese ) {
       alert('システムエラーが発生しました。');
       // フレームワークによってはサーバーエラーをjsonで返す
       var responese = $.parseJSON(jsonResponse);
      });
     });
    }else if(croppedCanvas.msToBlob){
     blob = croppedCanvas.msToBlob();
     var trimedImageForm = new FormData();
     trimedImageForm.append('blob', blob);
     // Ajax送信
     $.ajax({
      url: 'test/upload', // POST送信先
      type: 'post',
      processData: false,
      contentType: false,
      data: trimedImageForm,
     }).done(function( jsonResponse ){
      var responese = $.parseJSON(jsonResponse);
      if(responese.status == 'success'){
       console.log(responese);
       alert('アップロードしました。');
      }else if(responese.status == 'error'){
       alert('画像作成に失敗しました。再度お試しください。\n' + responese.msg);
      }else{
       alert('システムエラーが発生しました。');
      }
     }).fail(function( responese ) {
      alert('システムエラーが発生しました。');
      // フレームワークによってはサーバーエラーをjsonで返す
      var responese = $.parseJSON(jsonResponse);
     });
    }else{
     // これは少しわからないです。申し訳ない。
     imageURL = canvas.toDataURL();
    }
   };
  };
 });
});

PHP

public function upload()
{
 $res = [];
 try{
  // $_FILESで受け取り
  $file = $_FILES['blob'];
  
  $res = [
   'status' => 'success',
   'msg' => 'sample01',
   'obj' => $file,
  ];

 // 保存
 move_uploaded_file($file['tmp_name'], 'aaa.jpeg');

 }catch(Exception $ex){
  $res = [
   'status' => 'error',
   'msg' => $ex->getMessge(),
   'obj' => null,
  ];
 }
 echo json_encode($res);
 exit;
}

1週間でできる会員サイト「Limited」

1週間でできる会員サイト「Limited」
必要最小限。だから分かりやすい。始めやすい。続けやすい。
限定① 安⼼・安全の会員制
限定② 必要最⼩限の機能
限定③ 独⾃機能を追加可能

次の記事

Docker