この記事では、Cropper.jsを利用し画像を加工したあとに、加工した画像をAjaxを通してLaravelに渡し、その画像を保存する方法を紹介します。
Cropper.jsは、ライブプレビューとカスタムアスペクト比をサポートしており、JavaScript / jQueryプラグインを画像のトリミングに利用するのに便利です。
事前準備
1. フォルダの作成
ファイルを保存する先のフォルダを作成します。
今回、コントローラで指定するフォルダは「storage/app/public/upload」です。
ファイルをアップロードして画像を切り取って保存を押すと、このフォルダに保存されます。
バックエンド側
2. ルーティング
次に下記のルーティングを設定してください。
routes/web.php
Route::get('image-cropper','ImageCropperController@index');
Route::post('image-cropper/upload','ImageCropperController@upload');
3. コントローラ
次に下記のようなコントローラを作成します。
app/Http/Controller/ImageCropperController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ImageCropperController extends Controller
{
public function index()
{
return view('cropper');
}
public function upload(Request $request)
{
$folderPath = storage_path('app/public/upload/'); // 保存先のパス
$image_parts = explode(";base64,", $request->image);
$image_type_aux = explode("image/", $image_parts[0]); // ファイルの型を取り出す(今回は使わない)
$image_type = $image_type_aux[1]; // ファイルの型を取り出す(今回は使わない)
$image_base64 = base64_decode($image_parts[1]); // 画像データとして取り出す
$file = $folderPath . uniqid() . '.png'; // 保存に使うファイル名
file_put_contents($file, $image_base64); // ファイルを保存
return response()->json(['success'=>'success']); // JSONでレスポンスを返す
}
}
フロントエンド側
3. ビュー
最後にお待ちかねのビューを用意します。
ここにCropper.jsの処理も記述します。
resources/views/cropper.blade.php
<!DOCTYPE html>
<html>
<head>
<title>Laravel Crop Image Before Upload using Cropper JS - LaravelCode</title>
<meta name="_token" content="{{ csrf_token() }}">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha256-WqU1JavFxSAMcLP2WIOI+GB2zWmShMI82mTpLDcqFUg=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.6/cropper.css" integrity="sha256-jKV9n9bkk/CTP8zbtEtnKaKf+ehRovOYeKoyfthwbC8=" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.6/cropper.js" integrity="sha256-CgvH7sz3tHhkiVKh05kSUgG97YtzYNnWt6OXcmYzqHY=" crossorigin="anonymous"></script>
</head>
<style type="text/css">
img {
display: block;
max-width: 100%;
}
.preview {
overflow: hidden;
width: 160px;
height: 160px;
margin: 10px;
border: 1px solid red;
}
.modal-lg{
max-width: 1000px !important;
}
</style>
<body>
<div class="container">
<h1>Cropper.JSで加工した画像をAjaxでLaravelに送信</h1>
<input type="file" name="image" class="image">
</div>
<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="modalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="img-container">
<div class="row">
<div class="col-md-8">
<img id="image" src="https://avatars0.githubusercontent.com/u/3456749">
</div>
<div class="col-md-4">
<div class="preview"></div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">キャンセル</button>
<button type="button" class="btn btn-primary" id="crop">保存</button>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
var $modal = $('#modal');
var image = document.getElementById('image');
var cropper;
$("body").on("change", ".image", function(e){
var files = e.target.files;
var done = function (url) {
image.src = url;
$modal.modal('show');
};
var reader;
var file;
var url;
if (files && files.length > 0) {
file = files[0];
if (URL) {
done(URL.createObjectURL(file));
} else if (FileReader) {
reader = new FileReader();
reader.onload = function (e) {
done(reader.result);
};
reader.readAsDataURL(file);
}
}
});
$modal.on('shown.bs.modal', function () {
cropper = new Cropper(image, {
aspectRatio: 1,
viewMode: 3,
preview: '.preview'
});
}).on('hidden.bs.modal', function () {
cropper.destroy();
cropper = null;
});
$("#crop").click(function(){
canvas = cropper.getCroppedCanvas({
width: 160,
height: 160,
});
canvas.toBlob(function(blob) {
url = URL.createObjectURL(blob);
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
var base64data = reader.result;
$.ajax({
type: "POST",
dataType: "json",
url: "image-cropper/upload",
data: {'_token': $('meta[name="_token"]').attr('content'), 'image': base64data},
success: function(data){
$modal.modal('hide');
alert("success upload image");
}
});
}
});
})
</script>
</body>
</html>
最後に
以上の実装でAjaxを通してLaravelにCropper.jsで加工した画像を送れるはずです。
ぜひ試してみてください。