diff --git a/README.markdown b/README.markdown index 4698f85..def0249 100644 --- a/README.markdown +++ b/README.markdown @@ -1,74 +1,78 @@ -Description -=========== -Easy to use jQuery plugin for zoom & pan image cropping. - -Demo -==== -Visit: http://www.tmatthew.net/jwindowcrop - -Usage -===== - // minimum - $('img.crop_me').jWindowCrop(); - - // typical - $('img.crop_me').jWindowCrop({ - targetWidth:300, - targetHeight:300, - onChange: function(result) { - console.log($(this).attr('id')); - console.log('x: '+result.cropX); - } - }); - -Options -======= - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OptionTypeDefaultRequiredDescription
targetWidthinteger320noWidth in pixels of the cropping window
targetHeightinteger180noHeight in pixels of the cropping window
onChangefunctionfunction(){}noCallback function that gets called whenever the values change. cropX, cropY, cropW, cropH, mustStretch (boolean) values are passed to this function in a hash. Use the this keyword in the function for a reference to the element that was updated.
zoomStepsinteger10noNumber of incremental zoom steps. With the default of 10, you have to click the zoom-in button 9 times to reach 100%.
loadingTextstring"Loading..."noText (can be HTML) to display within frame until image is loaded.
smartControlsbooleantruenoIf true, controls will hide on mouseleave and appear on mouseenter.
showControlsOnStartbooleantruenoIf true, controls will be hidden on start. Note: Do not set both this and smartControls to false.
- -Advanced -======== -The structure for this plugin comes from http://starter.pixelgraphics.us/. An object is created for each dom element jWindowCrop is initialized on. A reverse reference to that object can be accessed like so: - - var jwc = $('img#beach').getjWindowCrop(); - -You then have access to all the properties and methods used for that specific element. - -Questions -========= -Email tyler at tmatthew dot net +Description +=========== +Easy to use jQuery plugin for zoom & pan image cropping. + +Demo +==== +Visit: http://www.tmatthew.net/jwindowcrop + +Usage +===== + // minimum + $('img.crop_me').jWindowCrop(); + + // typical + $('img.crop_me').jWindowCrop({ + targetWidth:300, + targetHeight:300, + onChange: function(result) { + console.log($(this).attr('id')); + console.log('x: '+result.cropX); + } + }); + +Options +======= + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionTypeDefaultRequiredDescription
targetWidthinteger320noWidth in pixels of the cropping window
targetHeightinteger180noHeight in pixels of the cropping window
onChangefunctionfunction(){}noCallback function that gets called whenever the values change. cropX, cropY, cropW, cropH, mustStretch (boolean) values are passed to this function in a hash. Use the this keyword in the function for a reference to the element that was updated.
zoomStepsinteger10noNumber of incremental zoom steps. With the default of 10, you have to click the zoom-in button 9 times to reach 100%.
loadingTextstring"Loading..."noText (can be HTML) to display within frame until image is loaded.
smartControlsbooleantruenoIf true, controls will hide on mouseleave and appear on mouseenter.
showControlsOnStartbooleantruenoIf true, controls will be hidden on start. Note: Do not set both this and smartControls to false.
customButtonsarray[]noButtons can be added to the toolbar here. e.g: [{class:'jwc_replace',name:'Replace Image', handler:triggerUpload, content:'Replace Image'}]
+ +Advanced +======== +The structure for this plugin comes from http://starter.pixelgraphics.us/. An object is created for each dom element jWindowCrop is initialized on. A reverse reference to that object can be accessed like so: + + var jwc = $('img#beach').getjWindowCrop(); + +You then have access to all the properties and methods used for that specific element. + +Questions +========= +Email tyler at tmatthew dot net diff --git a/jquery.jWindowCrop.js b/jquery.jWindowCrop.js index a2f85d4..2cea2f6 100644 --- a/jquery.jWindowCrop.js +++ b/jquery.jWindowCrop.js @@ -1,179 +1,191 @@ -/* - * jWindowCrop v1.0.0 - * - * Copyright (c) 2012 Tyler Brown - * Licensed under the MIT license. - * - */ - -(function($){ - function fillContainer(val, targetLength, containerLength) { // ensure that no gaps are between target's edges and container's edges - if(val + targetLength < containerLength) val = containerLength-targetLength; - if(val > 0) val = 0; - return val; - } - - $.jWindowCrop = function(image, options){ - var base = this; - base.$image = $(image); // target image jquery element - base.image = image; // target image dom element - base.$image.data("jWindowCrop", base); // target frame jquery element - - base.namespace = 'jWindowCrop'; - base.originalWidth = 0; - base.isDragging = false; - - base.init = function(){ - base.$image.css({display:'none'}); // hide image until loaded - base.options = $.extend({},$.jWindowCrop.defaultOptions, options); - if(base.options.zoomSteps < 2) base.options.zoomSteps = 2; - - base.$image.addClass('jwc_image').wrap('
'); // wrap image in frame - base.$frame = base.$image.parent(); - base.$frame.append('
' + base.options.loadingText + '
'); - base.$frame.append('
click to drag
'); - base.$frame.css({'overflow': 'hidden', 'position': 'relative', 'width': base.options.targetWidth, 'height': base.options.targetHeight}); - base.$image.css({'position': 'absolute', 'top': '0px', 'left': '0px'}); - initializeDimensions(); - - base.$frame.find('.jwc_zoom_in').on('click.'+base.namespace, base.zoomIn); - base.$frame.find('.jwc_zoom_out').on('click.'+base.namespace, base.zoomOut); - base.$frame.on('mouseenter.'+base.namespace, handleMouseEnter); - base.$frame.on('mouseleave.'+base.namespace, handleMouseLeave); - base.$image.on('load.'+base.namespace, handeImageLoad); - base.$image.on('mousedown.'+base.namespace, handleMouseDown); - $(document).on('mousemove.'+base.namespace, handleMouseMove); - $(document).on('mouseup.'+base.namespace, handleMouseUp); - }; - - base.destroy = function() { - base.$image.removeData("jWindowCrop"); // remove data - $(document).unbind(); // remove body binds - base.$image.unbind(); // remove image binds - base.$frame.unbind(); // remove frame binds - base.$frame.find('.jwc_zoom_out').unbind(); // remove zoom triggers - base.$frame.find('.jwc_zoom_in').unbind(); // remove zoom triggers - $('.jwc_loader').remove(); // remove the added text - $('.jwc_controls').remove(); // remove the added controls - base.$image.removeAttr( 'style' ); // undo the style - base.$image.unwrap(); // undo the wrap - }; - - base.setZoom = function(percent) { - if(base.minPercent >= 1) { - percent = base.minPercent; - } else if(percent > 1.0) { - percent = 1; - } else if(percent < base.minPercent) { - percent = base.minPercent; - } - base.$image.width(Math.ceil(base.originalWidth*percent)); - base.workingPercent = percent; - focusOnCenter(); - updateResult(); - }; - base.zoomIn = function() { - var zoomIncrement = (1.0 - base.minPercent) / (base.options.zoomSteps-1); - base.setZoom(base.workingPercent+zoomIncrement); - return false; - }; - base.zoomOut = function() { - var zoomIncrement = (1.0 - base.minPercent) / (base.options.zoomSteps-1); - base.setZoom(base.workingPercent-zoomIncrement); - return false; - }; - - function initializeDimensions() { - if(base.originalWidth == 0) { - base.originalWidth = base.$image.width(); - base.originalHeight = base.$image.height(); - } - if(base.originalWidth > 0) { - var widthRatio = base.options.targetWidth / base.originalWidth; - var heightRatio = base.options.targetHeight / base.originalHeight; - //base.minPercent = (widthRatio >= heightRatio) ? widthRatio : heightRatio; - if(widthRatio >= heightRatio) { - base.minPercent = (base.originalWidth < base.options.targetWidth) ? (base.options.targetWidth / base.originalWidth) : widthRatio; - } else { - base.minPercent = (base.originalHeight < base.options.targetHeight) ? (base.options.targetHeight / base.originalHeight) : heightRatio; - } - base.focalPoint = {'x': Math.round(base.originalWidth/2), 'y': Math.round(base.originalHeight/2)}; - base.setZoom(base.minPercent); - base.$image.fadeIn('fast'); //display image now that it has loaded - } - } - function storeFocalPoint() { - var x = (parseInt(base.$image.css('left'))*-1 + base.options.targetWidth/2) / base.workingPercent; - var y = (parseInt(base.$image.css('top'))*-1 + base.options.targetHeight/2) / base.workingPercent; - base.focalPoint = {'x': Math.round(x), 'y': Math.round(y)}; - } - function focusOnCenter() { - var left = fillContainer((Math.round((base.focalPoint.x*base.workingPercent) - base.options.targetWidth/2)*-1), base.$image.width(), base.options.targetWidth); - var top = fillContainer((Math.round((base.focalPoint.y*base.workingPercent) - base.options.targetHeight/2)*-1), base.$image.height(), base.options.targetHeight); - base.$image.css({'left': (left.toString()+'px'), 'top': (top.toString()+'px')}) - storeFocalPoint(); - } - function updateResult() { - base.result = { - cropX: Math.floor(parseInt(base.$image.css('left'))/base.workingPercent*-1), - cropY: Math.floor(parseInt(base.$image.css('top'))/base.workingPercent*-1), - cropW: Math.round(base.options.targetWidth/base.workingPercent), - cropH: Math.round(base.options.targetHeight/base.workingPercent), - mustStretch: (base.minPercent > 1) - }; - base.options.onChange.call(base.image, base.result); - } - function handeImageLoad() { - initializeDimensions(); - } - function handleMouseDown(event) { - event.preventDefault(); //some browsers do image dragging themselves - base.isDragging = true; - base.dragMouseCoords = {x: event.pageX, y: event.pageY}; - base.dragImageCoords = {x: parseInt(base.$image.css('left')), y: parseInt(base.$image.css('top'))} - } - function handleMouseUp() { - base.isDragging = false; - } - function handleMouseMove(event) { - if(base.isDragging) { - var xDif = event.pageX - base.dragMouseCoords.x; - var yDif = event.pageY - base.dragMouseCoords.y; - var newLeft = fillContainer((base.dragImageCoords.x + xDif), base.$image.width(), base.options.targetWidth); - var newTop = fillContainer((base.dragImageCoords.y + yDif), base.$image.height(), base.options.targetHeight); - base.$image.css({'left' : (newLeft.toString()+'px'), 'top' : (newTop.toString()+'px')}); - storeFocalPoint(); - updateResult(); - } - } - function handleMouseEnter() { - if(base.options.smartControls) base.$frame.find('.jwc_controls').fadeIn('fast'); - } - function handleMouseLeave() { - if(base.options.smartControls) base.$frame.find('.jwc_controls').fadeOut('fast'); - } - - base.init(); - }; - - $.jWindowCrop.defaultOptions = { - targetWidth: 320, - targetHeight: 180, - zoomSteps: 10, - loadingText: 'Loading...', - smartControls: true, - showControlsOnStart: true, - onChange: function() {} - }; - - $.fn.jWindowCrop = function(options){ - return this.each(function(){ - (new $.jWindowCrop(this, options)); - }); - }; - - $.fn.getjWindowCrop = function(){ - return this.data("jWindowCrop"); - }; -})(jQuery); - +/* + * jWindowCrop v1.0.0 + * + * Copyright (c) 2012 Tyler Brown + * Licensed under the MIT license. + * + */ + +(function($){ + function fillContainer(val, targetLength, containerLength) { // ensure that no gaps are between target's edges and container's edges + if(val + targetLength < containerLength) val = containerLength-targetLength; + if(val > 0) val = 0; + return val; + } + + $.jWindowCrop = function(image, options){ + var base = this; + base.$image = $(image); // target image jquery element + base.image = image; // target image dom element + base.$image.data("jWindowCrop", base); // target frame jquery element + + base.namespace = 'jWindowCrop'; + base.originalWidth = 0; + base.isDragging = false; + + base.init = function(){ + base.$image.css({display:'none'}); // hide image until loaded + base.options = $.extend(true,{},$.jWindowCrop.defaultOptions, options); + if(base.options.zoomSteps < 2) base.options.zoomSteps = 2; + + base.$image.addClass('jwc_image').wrap('
'); // wrap image in frame + base.$frame = base.$image.parent(); + base.$frame.append('
' + base.options.loadingText + '
'); + base.$frame.append('
click to drag
'); + base.$frame.css({'overflow': 'hidden', 'position': 'relative', 'width': base.options.targetWidth, 'height': base.options.targetHeight}); + base.$image.css({'position': 'absolute', 'top': '0px', 'left': '0px'}); + initializeDimensions(); + + //Add custom buttons to default buttons array. + $.merge(base.options.buttons,base.options.customButtons); + $.each(base.options.buttons,function (i,button){ + base.$frame.find('.jwc_controls').append('' + ((button.content) ? button.content : '')+ ''); + if (button.function && base[button.function]) { //Bind function to button. + base.$frame.find('.'+button.class).on('click.'+base.namespace, base[button.function]); + } else if (button.handler){ + base.$frame.find('.'+button.class).on('click.'+base.namespace,button.handler); + } + }); + base.$frame.on('mouseenter.'+base.namespace, handleMouseEnter); + base.$frame.on('mouseleave.'+base.namespace, handleMouseLeave); + base.$image.on('load.'+base.namespace, handeImageLoad); + base.$image.on('mousedown.'+base.namespace, handleMouseDown); + $(document).on('mousemove.'+base.namespace, handleMouseMove); + $(document).on('mouseup.'+base.namespace, handleMouseUp); + }; + + base.destroy = function() { + base.$image.removeData("jWindowCrop"); // remove data + $(document).unbind(); // remove body binds + base.$image.unbind(); // remove image binds + base.$frame.unbind(); // remove frame binds + $.each(base.options.buttons,function (i,button){ + base.$frame.find('.jwc_controls').unbind();// remove button triggers + }); + $('.jwc_loader').remove(); // remove the added text + $('.jwc_controls').remove(); // remove the added controls + base.$image.removeAttr( 'style' ); // undo the style + base.$image.unwrap(); // undo the wrap + base.options = null; + }; + + base.setZoom = function(percent) { + if(base.minPercent >= 1) { + percent = base.minPercent; + } else if(percent > 1.0) { + percent = 1; + } else if(percent < base.minPercent) { + percent = base.minPercent; + } + base.$image.width(Math.ceil(base.originalWidth*percent)); + base.workingPercent = percent; + focusOnCenter(); + updateResult(); + }; + base.zoomIn = function() { + var zoomIncrement = (1.0 - base.minPercent) / (base.options.zoomSteps-1); + base.setZoom(base.workingPercent+zoomIncrement); + return false; + }; + base.zoomOut = function() { + var zoomIncrement = (1.0 - base.minPercent) / (base.options.zoomSteps-1); + base.setZoom(base.workingPercent-zoomIncrement); + return false; + }; + + function initializeDimensions() { + if(base.originalWidth == 0) { + base.originalWidth = base.$image.width(); + base.originalHeight = base.$image.height(); + } + if(base.originalWidth > 0) { + var widthRatio = base.options.targetWidth / base.originalWidth; + var heightRatio = base.options.targetHeight / base.originalHeight; + //base.minPercent = (widthRatio >= heightRatio) ? widthRatio : heightRatio; + if(widthRatio >= heightRatio) { + base.minPercent = (base.originalWidth < base.options.targetWidth) ? (base.options.targetWidth / base.originalWidth) : widthRatio; + } else { + base.minPercent = (base.originalHeight < base.options.targetHeight) ? (base.options.targetHeight / base.originalHeight) : heightRatio; + } + base.focalPoint = {'x': Math.round(base.originalWidth/2), 'y': Math.round(base.originalHeight/2)}; + base.setZoom(base.minPercent); + base.$image.fadeIn('fast'); //display image now that it has loaded + } + } + function storeFocalPoint() { + var x = (parseInt(base.$image.css('left'))*-1 + base.options.targetWidth/2) / base.workingPercent; + var y = (parseInt(base.$image.css('top'))*-1 + base.options.targetHeight/2) / base.workingPercent; + base.focalPoint = {'x': Math.round(x), 'y': Math.round(y)}; + } + function focusOnCenter() { + var left = fillContainer((Math.round((base.focalPoint.x*base.workingPercent) - base.options.targetWidth/2)*-1), base.$image.width(), base.options.targetWidth); + var top = fillContainer((Math.round((base.focalPoint.y*base.workingPercent) - base.options.targetHeight/2)*-1), base.$image.height(), base.options.targetHeight); + base.$image.css({'left': (left.toString()+'px'), 'top': (top.toString()+'px')}) + storeFocalPoint(); + } + function updateResult() { + base.result = { + cropX: Math.floor(parseInt(base.$image.css('left'))/base.workingPercent*-1), + cropY: Math.floor(parseInt(base.$image.css('top'))/base.workingPercent*-1), + cropW: Math.round(base.options.targetWidth/base.workingPercent), + cropH: Math.round(base.options.targetHeight/base.workingPercent), + mustStretch: (base.minPercent > 1) + }; + base.options.onChange.call(base.image, base.result); + } + function handeImageLoad() { + initializeDimensions(); + } + function handleMouseDown(event) { + event.preventDefault(); //some browsers do image dragging themselves + base.isDragging = true; + base.dragMouseCoords = {x: event.pageX, y: event.pageY}; + base.dragImageCoords = {x: parseInt(base.$image.css('left')), y: parseInt(base.$image.css('top'))} + } + function handleMouseUp() { + base.isDragging = false; + } + function handleMouseMove(event) { + if(base.isDragging) { + var xDif = event.pageX - base.dragMouseCoords.x; + var yDif = event.pageY - base.dragMouseCoords.y; + var newLeft = fillContainer((base.dragImageCoords.x + xDif), base.$image.width(), base.options.targetWidth); + var newTop = fillContainer((base.dragImageCoords.y + yDif), base.$image.height(), base.options.targetHeight); + base.$image.css({'left' : (newLeft.toString()+'px'), 'top' : (newTop.toString()+'px')}); + storeFocalPoint(); + updateResult(); + } + } + function handleMouseEnter() { + if(base.options.smartControls) base.$frame.find('.jwc_controls').fadeIn('fast'); + } + function handleMouseLeave() { + if(base.options.smartControls) base.$frame.find('.jwc_controls').fadeOut('fast'); + } + + base.init(); + }; + + $.jWindowCrop.defaultOptions = { + targetWidth: 320, + targetHeight: 180, + zoomSteps: 10, + loadingText: 'Loading...', + smartControls: true, + showControlsOnStart: true, + onChange: function() {}, + buttons: [{class:'jwc_zoom_in',name:'Zoom In', function:'zoomIn'},{class:'jwc_zoom_out',name:'Zoom Out', function:'zoomOut'}], + customButtons:[] + }; + + $.fn.jWindowCrop = function(options){ + return this.each(function(){ + (new $.jWindowCrop(this, options)); + }); + }; + + $.fn.getjWindowCrop = function(){ + return this.data("jWindowCrop"); + }; +})(jQuery); +