Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Image Cropper Laravel Package

ajroudsoftwares/image-cropper

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require ajroudsoftwares/image-cropper
    php bin/console assets:install
    
  2. Basic Form Integration: Add the ImageCropperType to your form class:

    use AjroudSoftwares\ImageCropperBundle\Form\ImageCropperType;
    
    $builder->add('image', ImageCropperType::class, [
        'label' => 'Crop Image',
        'required' => false,
    ]);
    
  3. First Use Case:

    • Upload an image via the form.
    • Use the interactive cropper UI to select a region.
    • Submit the form to receive the cropped image data.

Where to Look First

  • Form Type Options: README.md
  • CropperJS Documentation: CropperJS Options
  • Twig Template: @ImageCropper/Form/image_cropper_type.html.twig (for customization)

Implementation Patterns

Common Workflows

  1. Basic Image Cropping:

    $builder->add('profileImage', ImageCropperType::class, [
        'label' => 'Profile Picture',
        'mapped' => true,
        'data_class' => null, // Handles file uploads automatically
    ]);
    
  2. Predefined Aspect Ratio:

    $builder->add('banner', ImageCropperType::class, [
        'cropperOptions' => [
            'aspectRatio' => 16 / 9, // Enforces 16:9 ratio
            'viewMode' => 2, // Only show the crop area
        ],
    ]);
    
  3. Custom Crop Dimensions:

    $builder->add('thumbnail', ImageCropperType::class, [
        'cropperSizeOptions' => [
            'width' => 300,
            'height' => 300,
        ],
    ]);
    
  4. Handling Submitted Data:

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => UploadedFile::class, // Default for file uploads
        ]);
    }
    
  5. Validation:

    $builder->add('image', ImageCropperType::class, [
        'constraints' => [
            new File([
                'maxSize' => '1024k',
                'mimeTypes' => ['image/jpeg', 'image/png'],
                'mimeTypesMessage' => 'Please upload a valid image (JPEG/PNG).',
            ]),
        ],
    ]);
    

Integration Tips

  • Asset Management: Ensure assets:install is run post-installation to register CropperJS assets. For production, use assets:install --symlink or configure Webpack Encore.

  • Twig Customization: Override the default template by extending @ImageCropper/Form/image_cropper_type.html.twig in your theme. Example:

    {% extends '@ImageCropper/Form/image_cropper_type.html.twig' %}
    {% block cropper_js_options %}
        {{ parent() }}
        {{ include('your_theme/_cropper_extras.js.twig') }}
    {% endblock %}
    
  • Symfony UX Integration: Combine with Symfony UX for a seamless experience:

    // config/packages/framework.yaml
    framework:
        assets:
            json_manifest_path: '%kernel.project_dir%/public/build/assets.json'
    
  • Entity Mapping: Use data_class to bind to entities with file fields (e.g., UploadedFile or custom DTOs).


Gotchas and Tips

Pitfalls

  1. Asset Loading:

    • Issue: CropperJS fails to load if assets aren’t installed or symlinked.
    • Fix: Run php bin/console assets:install and clear cache (php bin/console cache:clear).
  2. File Upload Limits:

    • Issue: Large images may exceed PHP’s upload_max_filesize or post_max_size.
    • Fix: Adjust php.ini or use client-side compression before upload.
  3. Twig Template Overrides:

    • Issue: Custom templates may break if block names or variables change in future updates.
    • Fix: Extend the base template instead of copying it entirely.
  4. CropperJS Initialization:

    • Issue: Cropper may not initialize if the image URL is invalid or CORS blocks it.
    • Fix: Validate image URLs server-side and use absolute paths in templates.
  5. Data Binding:

    • Issue: Submitted data may not map correctly if data_class is misconfigured.
    • Fix: Use UploadedFile or a custom class with a file property.

Debugging

  • Check Browser Console: Look for errors like Uncaught ReferenceError: Cropper is not defined (missing assets) or Failed to load resource (CORS issues).

  • Symfony Profiler: Inspect form data under the "Request" tab to verify uploaded files and cropper options.

  • Log Cropper Options: Temporarily log options in your template to debug:

    {{ dump(cropperOptions) }}
    

Configuration Quirks

  1. CropperJS Options:

    • Options like autoCrop or checkOrientation may require additional dependencies (e.g., exif-js).
    • Example:
      'cropperOptions' => [
          'checkOrientation' => true,
      ],
      
  2. Responsive Design:

    • CropperJS may not adapt to mobile screens by default. Use CSS to constrain the container:
      .image-cropper-container {
          max-width: 100%;
          overflow: hidden;
      }
      
  3. Multiple Instances:

    • If using multiple cropper fields on one page, ensure unique IDs for each instance:
      'attr' => ['id' => 'unique-cropper-id'],
      

Extension Points

  1. Custom Cropper Events:

    • Extend CropperJS by listening to events (e.g., crop.end) via JavaScript:
      document.querySelector('.image-cropper').addEventListener('crop.end', function(e) {
          console.log('Crop coordinates:', e.detail.x, e.detail.y);
      });
      
  2. Server-Side Processing:

    • Use Symfony’s FileUploadHandler or a service to process cropped images:
      // src/Service/ImageCropperService.php
      public function cropImage(UploadedFile $file, array $cropData): string
      {
          // Use Intervention Image or Imagick to crop $file based on $cropData
      }
      
  3. Dynamic Options:

    • Pass dynamic options from the controller:
      $builder->add('image', ImageCropperType::class, [
          'cropperOptions' => $this->getCropperOptionsFromRequest(),
      ]);
      
  4. Fallback for Non-JS Users:

    • Provide a fallback form for users without JavaScript:
      {% if app.request.isXmlHttpRequest or not app.request.headers.get('X-Requested-With') == 'XMLHttpRequest' %}
          {% include 'fallback_image_upload.html.twig' %}
      {% endif %}
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle