sawastacks / kropify-laravel
Kropify is a tool that can be integrated into Laravel framework from version 8 and above for the purpose of giving users easy way to crop their profile pictures and cover images.
Requires
- php: ^7.2|^8.0
README
Kropify - Image Cropping Package
- Author: Sawa Stacks - GitHub
- License: MIT License
- Initial version: 10/03/2023
This package (Kropify class) handles the server-side file upload and saving. The Kropify.js script integrates with the frontend to provide cropping, previewing, and uploading of images with your Laravel
backend.
This package is built using vanilla JavaScript, so it doesn't require jQuery as a dependency. It's lightweight, easy to integrate into your project without adding any extra library overhead, and supports multiple instances on a single page.
Requirements
- PHP >= 7.2
- Composer is required
- Laravel 8.x, 9.x , 10.x, 11.x and 12.x
Installation
This package can be installed through composer require
command. Before install this, make sure that your are working with PHP >= 7.2 in your system.
Just run the following command in your cmd or terminal:
-
Install the package via Composer:
composer require sawastacks/kropify-laravel
The package will automatically register its service provider if your Laravel framework is 8.x or above.
-
Optionally, After you have installed Kropify, open your Laravel config file
config/app.php
and add the following lines.In the
$providers
array, add the service providers for this package.SawaStacks\Utils\KropifyServiceProvider::class,
-
After Kropify package installed, you need to publish its css and js minified files in Laravel public folder by running the following command in terminal:
php artisan vendor:publish --tag=kropify-assets
NOTE:
Kropify
package assets files can be included on blade file via CDN links instead of using published files. If you need to use CDN links, just use below links:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/sawastacks/kropify-laravel@3.0.0/src/resources/assets/css/kropify.min.css">
<script src="https://cdn.jsdelivr.net/gh/sawastacks/kropify-laravel@3.0.0/src/resources/assets/js/kropify.min.js"></script>
Updating Package
When new Kropify version released and try to update the current package to the latest version, you will need to use composer update
command:
composer update sawastacks/kropify-laravel
When package not updated by using the above command, use below command that will remove current package version and install new version of package.
composer remove sawastacks/kropify-laravel && composer require sawastacks/kropify-laravel
After Kropify package updated, you need also to update its assets (css and js minified files) by running the following command in terminal:
php artisan vendor:publish --tag=kropify-assets --force
For Kropify
directives, you have to run this command to get immediately changes in views.
php artisan view:clear
Finally, It is neccessary to run the following command to autoload package files.
composer dump-autoload
Usage
This package uses css and js minified files, that is why you first need to include this package assets on your blade file. Place the following directive inside <head>
tag of your blade file to including Kropify css file on page. So, if you are using published file, use package style directive as shown below:
<html> <head> <title>Page title</title> <meta name="csrf-token" content="{{ csrf_token() }}"> @kropifyStyles ...... ... </head>
When you're using CDN links, no need of using any directive, just use below way:
<html> <head> <title>Page title</title> <meta name="csrf-token" content="{{ csrf_token() }}"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/sawastacks/kropify-laravel@3.0.0/src/resources/assets/css/kropify.min.css"> ...... ... </head>
NOTICE:
Don't forgot to add CSRF
meta tags to every blade file included Kropify assets as shown in above example.
For Kropify Js file, you need to add the following directive inside <body>
tag but before closing </body>
tag as shown in below example:
.......... ..... @kropifyScripts </body> </html>
But when you're using CDN links, use it in way below:
.......... ..... <script src="https://cdn.jsdelivr.net/gh/sawastacks/kropify-laravel@3.0.0/src/resources/assets/js/kropify.min.js"></script> </body> </html>
Package initialization
Suppose that you have an input file on your form for user profile picture:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>Document</title> @kropifyStyles </head> <body> <!-- Element for previewing cropped image --> <div style="width: 300px; min-height:24px; background:cyan"> <img src="" alt="" style="width: 100%" id="image-preview" data-kropify-default-src="...addCurrentImagePathIfExists.png"> </div> <!-- Targeted input file --> <input type="file" name="avatar" id="imageInput"> ........ .......... ........... @kropifyScripts <script> const cropper = new Kropify('#imageInput', { aspectRatio: 1, preview: '#image-preview', processURL: '{{ route("crop-handler") }}', // or processURL:'/crop' allowedExtensions: ['jpg', 'jpeg', 'png'], showLoader: true, animationClass: 'pulse', // fileName: 'avatar', // leave this commented if you want it to default to the input name cancelButtonText:'Cancel', maxWoH:500, onError: function (msg) { alert(msg); // toastr.error(msg); }, onDone: function(response){ alert(response.message); console.log(response.data); // toastr.success(response.message); } }); </script> </body> </html>
Routes
Route::post('/crop',[TestController::class,'cropHandler'])->name('crop-handler');
🖼️ Kropify scripts - Frontend Integration
The Kropify script handles the cropping interface, sends AJAX requests, and previews the result. When you want to initiate Kropify on that particular input file, you will use the following scripts.
<script> const cropper = new Kropify('#imageInput', { aspectRatio: 1, viewMode: 1, preview: 'img#image-preview', processURL: '{{ route("crop-handler") }}', // or processURL:'/crop' maxSize: 2 * 1024 * 1024, // 2MB allowedExtensions: ['jpg', 'jpeg', 'png'], showLoader: true, animationClass: 'pulse', // fileName: 'avatar', // leave this commented if you want it to default to the input name cancelButtonText:'Cancel', resetButtonText: 'Reset', cropButtonText: 'Crop & Upload', maxWoH:500, onError: function (msg) { alert(msg); // toastr.error(msg); }, onDone: function(response){ // alert(response.message); console.log(response); // toastr.success(response.message); } }); </script>
⚙️ Kropify.js Options
Option | Type | Description |
---|---|---|
viewMode |
Number |
You can set this value to (1,2 or 3). But you can not add this option if you are happy with the default value which is 1. |
aspectRatio |
Number |
Aspect ratio for cropping. You can add your custom cropped image ratio. You can use fractional numbers and float numbers. eg: 16/4 , 10/32 , 0.25 , 2.25 , etc... Default value is 1 |
preview |
String |
CSS selector for image preview. you must use jquery selector to select id="..." or class="..." of the img tag element where you want to display cropped image result. |
processURL |
String |
URL to send the cropped image to (your Laravel route). This option is very required. You must define your url of croping selected image. eg: processURL : "{{ route('crop') }}" or processURL : "{{ url('crop') }}" |
allowedExtensions |
Array |
Allowed file extensions default value is: ['jpg', 'jpeg', 'png']. |
showLoader |
Boolean |
Show loading indicator. Default value is true |
animationClass |
String |
CSS animation class for animate modal box. you may use this option by choosing one of three animation classes allowed pulse ,headShake ,fadeIn and pulse . By default, this value set to pulse class |
fileName |
String |
Desired filename for the uploaded image. This will be used when want to specify or overwrite file name of the input file. Default value is image , In controller you may write: $upload = Kropify::getFile('image')->... |
cancelButtonText |
String |
You can change this button text with your need and according to your language. |
resetButtonText |
String |
You can change this button text with your need and according to your language. |
cropButtonText |
String |
You can change this button text with your need and according to your language. |
maxWoH |
Number |
Maximum width / height of the image. |
onError |
Function |
Callback function on error (shows alert/toastr/etc.). |
onDone |
Function |
Callback function when upload is successful (response is passed). |
maxSize |
Number |
By default, this value set to the maximum size of 2MB .But, you can set your own maximum size of selected image. |
Callbacks
onError: function (msg) { alert(msg); // toastr.error(msg); }, onDone: function(response){ alert(response.message); console.log(response.data); // toastr.success(response.message); }
In controller
To include Kropify class in controller is very simple. Just import the following lines on your controller.
use SawaStacks\Utils\Kropify;
To upload the cropped image you will use the following lines inside method:
public function cropHandler(Request $request){ $file = $request->file('avatar'); $path = 'uploads'; /** When you upload with move() */ $upload = Kropify::getFile($file,'userpic.png') // ->setDisk('public') // local, public ->setPath($path) ->useMove() ->save(); /** When you upload with Storage */ $upload = Kropify::getFile($file,'userpic.png') ->setDisk('public') // local, public ->setPath($path) // ->useMove() ->save(); /** * GET UPLOADED IMAGE DETAILS (INFO) * ================================= * */ // if( $upload ){ $info = $upload->getUploadedInfo(); } // $info = $upload ? $upload->getUploadedInfo() : null; // $info = $upload?->getUploadedInfo(); if (!$upload) { return; } $info = $upload->getUploadedInfo(); // Store image details into DB $im = new StoredImage(); $im->filename = $info['filename']; $im->size = $info['size']; $im->extension = $info['extension']; $im->width = $info['width']; $im->height = $info['height']; $im->mime = $info['mime']; $im->path = $info['path']; $im->url = $info['url']; $im->save(); // Returning json data return response()->json([ 'status'=>'OK', 'message'=>'Image successfully uploaded', 'data'=>$info ],201); }
🚀 Kropify Class - Methods Overview
Method | Description | Usage/Notes |
---|---|---|
getFile($file, $filename = null) |
Initializes the file upload. Must be called first. | $file : instance of uploaded file, $filename : optional custom filename. |
setDisk(string $disk) |
Set the storage disk to use (public , local , etc.). |
Throws error if useMove() already used or if not preceded by getFile() . |
useMove() |
Use PHP’s move() instead of Laravel’s Storage . |
Can’t be used with setDisk() . |
setPath(string $path) |
Set the relative path (within storage/public) for the file. | Example: uploads/avatars . |
save() |
Saves the uploaded file. Must be called after setting up the upload. | Can only be called once per instance. |
getUploadedInfo() |
Retrieve details of the saved file: filename, size, extension, dimensions, mime, path, URL. | Can only be called after save() . |
📄 License
This package is open-sourced software licensed under the MIT license.
🙌 Credits
Author: Sawa Stacks
📧 Email: sawastacks@gmail.com
🌐 GitHub: github.com/sawastacks