Croppie - element plugin to crop and zoom images before upload

Introducing Croppie, a plugin to give another element in Bubble.

The element can be put on a page, for the user to choose their own pictures, rotate, zoom, crop, then upload them to Bubble. The image will be cropped to the page designer’s chosen size.

Getting started

  1. Add the plugin.
  • Add the Croppie element to your page.

  • Add a button to Browse local images, workflow action:

  • Browse a Croppie.

  • Add buttons to Rotate image, workflow action:

  • Rotate a Croppie, choose rotation.

  • Add button to Save cropped image, workflow actions:

  • Create a database record to attach image to (if making file private).

  • Save a Croppie, this will initiate an image upload to storage (S3).

  • Add a workflow event for Croppie is saved, workflow action:

  • Make changes to a database record, set Image = This Croppie’s image.

  • Set the properties on the Croppie element.

Sample page, editor and runtime.

Some features

  • Crop will match Viewport width and height in pixels.

  • Viewport can be square or circle, meaning rectangle or oval.

  • Boundary is an option to use only part of the Croppie container for cropping. It can be set in pixels, or in percentage of the container. Boundary is handy to leave room for the zoomer control.

  • Zoomer is an optional slider control inside the Croppie element.

  • There is a Zoom workflow action if you want to provide your own zoom controls.

  • EXIF turned on allows Croppie to find the correct orientation of the image, if set.

  • Custom class can be entered, to allow you to add your own styles, for example on the page html header.

  • Output format can be configured.

  • auto will set the output to jpeg if the input is jpeg, and png otherwise.

  • png is best to allow transparency, particularly for a circle viewport.

  • jpeg output will have black corners for a circle viewport.

  • Resulting file can be set as private, similar to the Picture Uploader control. Attach to an existing database record for the setting to be applied.

  • The Croppie javascript library will only be loaded on a page that has the Croppie element.


I hope this is useful, and please comment here :slight_smile:


Awesome! Very excited to try it out! Looks highly valuable.

Amazing, nice job!

Great, great work mishav!

Great work ! Thanks.

Absolutely amazing! It works perfectly!

Thank you so much Misha!

F**kingtastical! Thanks for your hard work and providing to the community!

Super Duper work! Thanks so much for making.

Damn, that’s neat! Thanks for sharing :slight_smile:

Yay! This is awesome, thank you!


Is it possible to load the previously uploaded “before crop” image when you are wanting to (for example) edit something ?

So if you have saved a cropped profile picture, and you want to adjust it, you would want to be able to go back to the croppie element with the existing image so you can adjust it. Rather than having to reselect the image from the device.

I am wondering if some if my issues are because I am using Croppie in a Repeating Group. When you do the “Save Croppie” it seems to be in a workflow with a Create Thing. Because an RG needs to have something created already to work, I am just doing the “Save Croppie” action. The thing is already created.

Could potentially change this so you have a single Croppie and a “gallery” of images, but this then makes it more complex when you want to go back and tweak a Crop.

So … can you save both the cropped and pre-cropped image, and load the pre-cropped instead of Browsing ?

However, that gets similarly complex, as you are relying on the thing you need to update being the most recently created. Which may not always be the case, and you could end up updating another thing by mistake. I don’t think that is a good design, hence I was using a repeating group (so I know exactly which thing to update).

As a workaround I have placed the cropped image behind the croppie element in the repeating group for now.

Hi Nigel, I’m glad you brought that up! The record only needs to be created prior to the upload, if you want the uploaded image to be “made private” and attached to a thing. If the private setting isn’t being used, you can do the create after the “is saved” event, or use an existing record.

If you’re referring to my sample app page: updating the most recently created record was just a hack to avoid being too complex.

If needing to create before upload, the create action could be followed by an action to save the created thing to a custom state, and refer to it again on the saved event after the upload. Hmmm that doesn’t sound too hard, I’ll add it to the sample app. (Added!)

I think this is an excellent suggestion, I’ll put that in. :smiley:

Load is one feature that I originally had, but there is a CORS error that comes up, sometimes, on the Chrome browser. I have a dialogue with Emmanuel, we’re trying to pin down the exact cause.

So for the moment Load and Default Image is off the feature list and is keeping the spare blankets warm in the cupboard.

Does this look good? It sounds like a good idea for layout.

Thanks for the detailed feedback, @NigelG :slight_smile:

Ah, ok. Wasn’t entirely sure what this was doing initially. So if I want it to be “private” I HAVE to create the thing in the same workflow as the Croppie Save ? What is the upshot of it not being Private ? I can’t do it like that as it is in a repeating group.

Yes, it was an obvious workaround :slight_smile: But I am still a little worried about how we can get around multiple Croppies being saved in quick succession. Is there the (remote) chance the that the 2nd Croppie save could come back first ?

Gotcha :slight_smile: I think the workaround with the image is OK, so below.

It does look pretty good. Not quite sure what the green “bits” are doing there - they aren’t mine I don’t think. And I need to sort the scrolling on the RG. But it works quite well I think :slight_smile:

Well, thank YOU for developing this. It is really really useful.

The privacy setting is similar to File Uploader and Picture Uploader, to use it needs an existing database record, referenced on the element properties. It doesn’t need to be created or referenced in the same workflow.

The privacy setting ties in the uploaded S3 resource with your particular app, and won’t allow other methods of accessing.

Have a look at the different URLs produced, private images start with your app url, public images start with s3. Then try loading each in a browser window outside your app.

Being in a repeating group doesn’t have to restrict your options about when to create the record.

Example 1: A button outside the RG creates a new empty record for the group to show.

Example 2 (slightly unrealistic): The repeating group data source is a list of some other record or type, and the picture data source is linked to it indirectly.

Sure yes that can happen, there is no determining the order. That’s why your point is so important: don’t use the most recent record to determine where to save.

Creating a record, setting the new record to a custom state, then using that to save to, is robust.

Is the repeating group’s cell information as robust? As in, if the cell changes position before the upload finishes, does “this cell” still refer to the same data? I expect it does but I haven’t tested.

Around the white viewport rectangle, the green area is a “mask” showing what will not be included in the crop. This gives the cropping process some context for moving and zooming.

In my opinion, showing the croppie artefacts when it is not ready to crop isn’t great UI for in-place editing of a picture library.

Alternative 1:

  • Initially hide the croppie element.
  • “Load” is clicked, show the croppie element and run the browse action.
  • On saved event, hide the croppie element.

Potential issue: on first show, the initialize will run, so the browse action may not work for as long as it takes.

Alternative 2:

  • We use a style to have the element hidden but active, like in the demo on github. Then toggle this off and on as needed.

New version 0.3.0

  • Option to upload the original uncropped image, gets published to a value “original image”.
  • Option to limit file size of original image, new event “image too large” if exceeded.
  • The original image is uploaded once, even if multiple crops on the same image are done.

New properties:

New event, image too large:

New value, Original image:

Enjoy the sloooow uploads of full-size photos :wink:


This is awesome

1 Like

It was the top of the Zoomer, so I have set Boundary Hieght to 70% and it is now a lot better looking :slight_smile:

Using Alternative 1 isn’t great, as if the user cancels the browse, there is no event to set it back to hidden.

I was hoping the loading of the original file would help, but despite deleting and reistalling Croppie … it doesn’t show up ?

Select the new version in the plugins page, then refresh the app editor.

Good point. How about initially just an Edit button, which shows the croppie, and makes the other buttons appear plus Cancel/Close?

Nice :slight_smile: I might need to make the Zoomer style configurable too.

Still struggling with the “Load Original Image” setting.

Am using the same Croppie-state based Save that you have used, and if you don’t refresh the page, then you get the same image back again after the save when it is a Repeating Group.

So you can have a nice line Croppies …

But if you refresh that page, then it won’t show you the original loaded anymore.

Can go back the way it was, but it did seem very friendly to be able to go back and tweak each Crop without having to reload the image. And you can do it … in the same “page” as long as you don’t refresh.