UvumiTools Crop
Description
In today's web2.0 era, more and more websites are user generated and boast dynamic content. Users sumbit text, images, videos, providing content for entire web sites. Most of the time, people submit photos straight from their camera because they don't have photo editing programs or they don't know how to use them. This simplified tool gives your users the ability to create a selection area that can be used to crop an image, live on your web site.
Features
- Simple: There are some other Javascript image cropping tools out there already. We don't necessarily think they are bad--most of them accomplish the same task, some do it better, but they are frequently too complex for our tastes. With UvumiTools Crop, you don't have a dozen handles and double-click features. Drag from the middle to move, tug on the lower-right corner to resize, and that's it. Simple.
-
Set minimum sizes: If you know the thumbnails on your website will be 120*90 pixels, just set those values as minimums, and your users won't be able to select any smaller area than this. Why? Because if a smaller area is submitted, you have three possibilities:
- The user will end up with a smaller picture, not filling containers designed for a specific size.
- The server script will automatically expend the area before cropping to match the minimum size, surprising the user with a thumbnail not matching what was actually selected.
- The server script will crop the image to this smaller size first, then resize the thumb by expending it to the minimum size, resulting in picture quality loss, especially if the user selected a very small area (like a 30px area for a 120px thumbnail).
- Keep aspect ratio (or not): If you want all the thumbnails on your website to be squared or 4/3 and nothing else, you can lock the aspect ratio to the dimensions you specified as minimums (see above). Selection's height and width will grow and shrink together, maintaining proportions.
- Real time preview: You can set an element of your document to render a preview of the thumbnail. It might not look as good as an actual resampled image, but it definitely gives your users a good idea of what the resulting image will look like.
- Support HTML resizing: If the image has been resized to fit in the document, with <img> WIDTH and HEIGHT attributes or with CSS, the script will detect it and still return correct coordinates.
- Callback function: This feature is very important, because without it this tool would be useless. Making selections on top of a picture is fun, but if you can't do anything with it, what's the point? Once you've created a selection, you must communicate the coordinates to your server-side script so it can perform the actual crop. It will need need two pieces of data: position and dimensions. That's why the cropper has a callback function, fired after every drag on the selection. By default, this function does absolutly nothing, but you can set it do anything when you initialize the script. The callback function recieves four arguments: top, left, width, height. It's up to you to grab those values, and put them in a form to submit to the server-side script. The demo shows how to do that. Ideally you would put them into hidden inputs, with another one referencing the image file to be cropped.
- Can be toggled on and off: UvumiTools Crop offers tools to completly remove itself from the document (ideal once the the coordinates have been submited to the server) or to hide it so you can show it again later, without completely regenerating a new one. Good for memory management.
- Modify style with CSS: Style is not hard-coded, you can modify the mask's color, the selection's border color, its thickness and style, with basic CSS. Use the downloadable sample to get started. Some important properties are overwritten by javscript to ensure the script will work, but they don't affect the way it looks. There isn't much you want to modifiy beside the mask and the border colors anyway.
-
Fast, even on slow computers: This one is for advanced CSS users: the other cropping scripts I've seen use a four-DIVs trick to display a mask around the selection. And that's how we initially coded ours--Everytime the selection is moved or resized we had to recalculate the positions and dimentions of the four Div elements. That meant 4 css properties for each div, except the first one which always stayed in the top left corner. But that's still 14 properties to calculate and update on every mouse move. If you add the preview at the same time, it can slow things down a bit.
Then we found a blog article about the little-known CSS cliping property. It almost does what this mask does: you specify four coordinates within an element (top, right, bottom, left) and it only renders this area, everything else is masked out. It took usa while to figure how to use it in the cropper context, because at first it was doing the opposite of what I wanted: it was rendering the mask only inside the selection, not outside. So in the end we duplicated the picture, and superimposed everything in four layers from bottom to top: original picture, mask, picture clone, selection. Then we applied the clipping property on the image clone, while keeping the mask as a single div covering the original. And that's it. Now when modifiying the selection, all I have to do is update the clip property on the image clone. That's one CSS property to update instead of 14.
Requirements
What you'll need:
- A server-side script: Unlike other UvumiTools scripts which are mostly client-side only tools, UvumiTools Crop must be paired with a server-side script that will actually be able to so something with the coordinates. We are now providing a sample PHP script to crop images on the server side. It is available in the downloads section below.
-
Mootools 1.2: To use this plugin you'll need Mootools 1.2, but if you are already using another javascript framework like Prototype or JQuery, you may have to decide which one you want to keep because those frameworks were not designed to work together, and they ofen conflict with each other.
And yes, you actually do need version 1.2 of Mootools. If you are already using a previous version of Mootools then the Crop will not work unless you upgrade. Sure, upgrading is a slight hassle, but trust us, it's worth it in the long run. -
Mootools Dependencies: If your website already contains some Mootools 1.2 stuff (from this wesite or elsewhere), then you're stoked because you can use a single Mootools library for everything. All you'll need is the UvumiTools Crop script, and to make sure your library contains the following classes:
-
Core
- Core
- Browser
-
Native
- Array
- Function
- Number
- String
- Hash
- Event
-
Class
- Class
- Class.Extra
-
Element
- Element
- Element.Event
- Element.Style
- Element.Dimensions
-
Utilities
- DomReady
-
Fx
- Fx
- FX.CSS
- FX.Tween
-
Plugins
- Fx.Elements
- Drag
- Drag.Move
- Assets
-
Core
How To
Initialization
Arguments
- Image: Can be the ID of an image HTML element, or the element it-self, if grabbed the mootools way with the $() function. If you don't understand what it means, just pass the image ID.
- Options: an object that will allow you to modify some properties of the script. Options are optional (of course). If you just want to keep default value, you don't need this second parameter.
Options
- maskOpacity: Number between 0 and 1, defining the opacity of the masked overlayed on top of the image. Default is 0.5. To change its color, use the attached CSS file.
- maskClassName: The css class you want to be applied to the mask, to modify its style with css. Default is cropperMask which corresponds to the name used in the sample CSS file that comes with this plugin.
- moverClassName: The css class you want to be applied to the middle area that lets you drag the cropping region. You shouldn't have to modify this style. Default is cropperMove which corresponds to the name used in the sample CSS file that comes with this plugin.
- resizerClassName: The css class you want to be applied to the outter area of cropping region. If you want to overrride the default red dashed border, this is the class you will alter. Default is cropperResize which corresponds to the name used in the sample CSS file that comes with this plugin.
- wrapperClassName: The css class you want to be applied to the image wrapper. You shouldn't have to modify this style. Default is cropperWrapper which corresponds to the name used in the sample CSS file that comes with this plugin.
- mini: An object with two values, x and y, defining the size of the thumbnail. These coordinates are used to generate the preview and as minimum size for the cropping region. Default is {x:80,y:80}.
- onComplete: Event function fired when when you stop dragging/resizing. recieves four parameters: top, left, width, height (of the selection). By default, it's empty, but you can write a function to update a form that contains one hidden input for each coordinate (or one input with a json string, it's up to you). Then by submitting this form to a server script, you should be able to crop your image on the back-end (eg with GD library in PHP, just as we do in the sample script you can download below).
- resizerWidth: Width of the resizing area (left and bottom margin of the cropping region). Default is 8px wide.
- resizable: Boolean value, if the selection can be resized or not. Default is true
- keepRatio: Boolean value, if the width/height ratio of the selection should be maintained or not. Default is true
- preview: if you want to display a preview of the cropped image, you must specify a target container by its ID. Default is false, which means no preview will be generated. If any string is passed, the script will try to select the element with the corresponding ID.
Implementation
First, you simply import the files provided in the zip archive into your document. While you can insert <script> tags anywhere, we recommend you put them inside the <head> tag:
<link rel="stylesheet" type="text/css" media="screen" href="css/uvumi-crop.css"/>
<script type="text/javascript" src="js/mootools-for-crop.js"> </script>
<script type="text/javascript" src="js/UvumiCrop.js"> </script>
Then you must prepare the HTML code. You need one image. Let's just give it the id "myImage".
"my_image.jpg" is just a random image file name, we just assume it exists.
Then we initialize the cropper object with this image's ID. Don't forget to wrap the ID with quotes when passing it to the object (double or single, doesn't matter);
In the end, if we put everything together. Mootools requires a strict Doctype to work properly. Use something like this:
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<script type="text/javascript" src="js/mootools-for-crop.js"> </script>
<script type="text/javascript" src="js/UvumiCrop.js"> </script> <script type="text/javascript" >
<body>
You should get something like this. A cropper with default options: 80*80 pixels, resizable, keeps aspect ratio, no preview, 50% opacity mask
Let's try a step above. This time, we'll set no fixed ratio, with a preview. First part where you include the required script is the same. But you'll need an existing container for preview (because the script is not supposed to guess where to display it). Where just going to create an empty div, with id "myPreview".
Then we must tell the script to use this div as a preview container when we initialize the object, with the preview option. We also said we didn't want to keep the selection's aspect ratio, so we're going to set keepRatio to false
preview:'myPreview'
Put it together:
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<script type="text/javascript" src="js/mootools-for-crop.js"> </script>
<script type="text/javascript" src="js/UvumiCrop.js"> </script> <script type="text/javascript" >
preview:'myPreview'
<body>
And you should get something like this. Try to resize the selection and check out how the preview reacts.
One more example: we're going to modify the genearal look of the cropper by assigning alternate CSS classes. We are also going to change the default minimum width and height, and, just to show that it's possible, disable resizing.
maskClassName:'blueMask',
resizerClassName:'yellowSelection',
mini:{
y:90
resizable:false
HTML will be the same as the first exemple, but we are going to create new CSS classes, corresponding the those we set in the cropper's options
.blueMask{
cursor:pointer;
Resulting code:
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<style type="text/css" >
.blueMask{
cursor:pointer;
<script type="text/javascript" src="js/mootools-for-crop.js"> </script>
<script type="text/javascript" src="js/UvumiCrop.js"> </script> <script type="text/javascript" >
maskClassName:'blueMask',
resizerClassName:'yellowSelection',
mini:{
y:90
resizable:false
<body>
Should produce this, if not, go back and check for typos or mistakes:
Ok, last but not least, we'll look at how the callback function works. At the same time, we are going to demontrate the HTML resizing feature: We are going to pick an 800px wide image, but we are going to scale it down to 400px match with the other. So techincally, when we draw a 100px*100px selection on this scaled down image, it virtually represents 200*200px on the full size image, the one the server will use. Same goes with top and height, and preview too, everything has to match this X2 factor. The script handles it and does all the conversion for you, if the image has been scaled up or down.
We prepare the HTML first. We are going to create a form with four inputs. For the image, we are going to set the WIDTH attribute (we can either set here or with CSS, works with height too):
<form action="crop-image.php" method="post" >
<input id="input-left" name="left" type="text" readonly="readonly" />
<input id="input-width" name="width" type="text" readonly="readonly" />
<input id="input-height" name="height" type="text" readonly="readonly" />
<input name="image" value="my_image.jpg" type="hidden" />
<p>
Note that we create four read-only text inputs for this example, but in a real production environment, we'd probably set them as hidden, just like the one containing the image name (or any other kind of unique identifier). Now we want to synchronize those inputs with our cropper:
$('input-left').set('value', left);
$('input-width').set('value', width);
$('input-height').set('value', height);
It's that simple!
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<script type="text/javascript" src="js/mootools-for-crop.js"> </script>
<script type="text/javascript" src="js/UvumiCrop.js"> </script> <script type="text/javascript" >
$('input-left').set('value', left);
$('input-width').set('value', width);
$('input-height').set('value', height);
<body>
<form action="crop-image.php" method="post" >
<label for="input-left" >Left: </label> <input id="input-left" name="left" type="text" readonly="readonly" />
<label for="input-width" >Width: </label> <input id="input-width" name="width" type="text" readonly="readonly" />
<label for="input-height" >Height: </label> <input id="input-height" name="height" type="text" readonly="readonly" />
<input name="image" value="my_image.jpg" type="hidden" />
<p>
You can see the form's inputs being updated whenever you release the selection. Note how the values are twice as large as the actual selection because the picture is scalled down by 50%:
Actual picture size : 800*698 pixels
Displayed size : 400*349 pixels
Coordinates generated match the picture's real size.
Known Issues
- Rounding problems: This only happens when dealing with images directly resized on the client side, especially with images scaled down. Coordinates need to be multiplied by a ratio to get the actual size. The result must be rounded to get a pixel value, and sometimes it's rounded to the upper value when that's not desirable. What happens? In the worst case scenario, you may end up with a selection area popping one pixel out of the picture. We'll try to fix this in the future.
Download
Change Log
- 20080910 - Version 1.0.1: Added a PHP sample cropping script to the download package
- 20080902 - Version 1.0.0: Initial release. Stable with Mootools 1.2