Wednesday

Image Crop with Javascript

MooCrop

About

MooCrop is an Image Cropping utility using the amazingly powerful mootools javascript framework. Alone it serves no practical purpose but used in conjuction with a server side script becomes a powerful image manipulation tool.

Why

Looking for a mootools solution, I searched and came up with a few existing implementations. Everything I came across were only partial implementations. Those that were more polished seemed to be sluggish and effecting the DOM needlessly in some places. I wanted a class that had a very intuitive interface and played nicely with the existing DOM and more importantly I wanted it to be fast. I came to the conclusion that developing my own would give me a better understanding of mootools and broaden my understanding of drag and drop inside the DOM.

Initially I tried using the Drag.Base class found within mootools but found this to be clumbsy for this highly specialized form of dragging. With default options a single drag is moving/resizing not one but 13 DOM elements. The dragging functionality has been optimized with this sole purpose in mind.

Features

MooCrop goal is to do only one thing (image crop ) but to do it well. With this in mind I tried to make the class as flexiable as possible for your own use.

  • Completely customizable CSS styling
  • Detects and handles multiple CSS box models
  • Allows for masking to be toggled
  • Ability to hide resize handles during drag
  • Custom events for your own modification
  • Relative based postioning rather then absolute (should handle overflow properly)
  • Works and retains layouts on floating images.
  • Resize from 8 different directions
  • Ability to set minimium size limit
  • Cleans up nicely, leaving your DOM in its original state when removed.
  • Fast!

Documentation

Arguments

element the image element you want to attach MooCrop to.

options an object. see options below

Options

maskColor css valid color value for the mask background color. default: 'black'

maskOpacity opacity value (0-1) for the masking areas. default: '.4'

handleColor css valid color value for the handle background color. default: 'blue'

handleWidth width of handles. default: '8px'

handleHeight height of handles. default: '8px'

cropBorder css valid border value for the crop area border. default: '1px dashed blue'

min an object representing the minimum size the crop box can be. default: { 'width' : 50, 'height' : 50 }

showMask a boolean flag to show or hide the masking area. default: true

showHandles a boolean flag to show or hide handles during drag. default: false

Methods

getCropInfo returns an object with the current relative coordinates of the crop area in relation to the image top left corner. object properties ( 'width','height','top','left','right','bottom' ).

removeOverlay detatches MooCrop from image and return the image to its pre MooCrop state.

Events

onBegin fired just before dragging or resizing occurs. returns [ image src, croparea, bounds, handle ] image src is the complete path of the image being cropped. croparea see getCropInfo(). bounds is a coordinates object defining the image bounds for the crop area, useful for labels ( see example below ). handle is the name of the current drag/resize event [NW,N,NE,E,SE,S,SW,W] if drag = NESW

onCrop fired during drag. returns [ image src, croparea, bounds, handle ]

onComplete fired after the drag or resize event. returns [ image src, croparea, bounds, handle ]

onDblClk fired when the crop area is double clicked. returns [image src, croparea, bounds ]

Additional Notes

MooCrop does not rely on any css within the document its all set through object initialization. In preventing issues from arising from padding and margins the target image is hidden and a div is inject before it in the DOM tree. The image is used as a background image. The box is adjusted and the offset of the background image is based on the box model.

If IE box model is being used and a border has been defined for the crop area the border will be included in the px width and height. The traditional box model will not include the border.

When using MooCrop you must attach during or after the window load event. Using domready doesn't work because the image hasn't been rendered yet.

Requirements

MooCrop has been tested with IE 6 & 7, FF 2+, Opera 9.2 and Safari 2 & 3.

Download mootools, required dependancies:

  • Core: Moo, Utility, Common
  • Native: Array, String, Function, Element, Event, Dom
  • Element: Element.Dimensions, Element.Events
  • Plugins: Hash

For your convenience:

Examples/Usage

Include mootools and MooCrop in your page header

 

Default

 new MooCrop('crop_example1');

Changing the mask

 new MooCrop('crop_example2',{
'maskColor' : '#96743f',
'maskOpacity' : '.8'
});

Changing the handles

 new MooCrop('crop_example3',{
'handleColor' : '#333333',
'handleWidth' : '10px',
'handleHeight' : '10px',
'showHandles' : true
});

Adding labels with events

 var crop4 = new MooCrop('crop_example4');

// create a container for a label
// wrapper is the container that all
//MooCrop operations are performed
var indicator = new Element('span',{
'styles' : {
'position' : 'absolute',
'display' : 'none',
'padding' : '4px',
'opacity' : '.7',
'background' : '#ffffff',
'border' : '1px solid #525252',
'font-size' : '11px'
}
}).injectInside(crop4.wrapper);

// when dragging/resizing begins show indicator
crop4.addEvent( 'onBegin' ,
function(imgsrc,crop,bound,handle){
indicator.setStyle('display' , 'block');
});

// during the event update label
crop4.addEvent('onCrop' ,
function(imgsrc,crop,bound,handle){
indicator.setStyles({
'top' : crop.bottom + 10,
'left' : crop.left
}).setText("w: "+crop.width+
" h: "+crop.height);
});

// once event is done hide label
crop4.addEvent('onComplete' , function(){
indicator.setStyle('display','none');
});

Server handling example (double click on crop area)

 var crop5 = new MooCrop('crop_example5');

crop5.addEvent('onDblClk', function(img,crop,bound){
$('cropped').src = "crop.php?w="+crop.width+"&h="+crop.height+
"&x="+crop.left+"&y="+crop.top;
});

Contact

Nathan White: < nw at nwhite.net>

No comments:

Python Meta Classes