1. 程式人生 > >js+java實現的頭像上傳和裁剪,完美相容各種瀏覽器

js+java實現的頭像上傳和裁剪,完美相容各種瀏覽器

1.前端剪下效果使用jquery+js+div+css實現

其中有個js圖片剪下外掛叫ImgCropper,吃外掛與jquery外掛一起使用會有bug,被我修改後能相容jquery了

如果需要了解更多關於ImgCropper外掛使用,請檢視原始碼或百度看例子吧

下面是我修改後的ImgCropper+Resize+Drag的整合程式碼,使用時只需將程式碼打包後,通過script標籤引用即可

var isIE = (document.all) ? true : false;

var isIE6 = isIE && ([/MSIE (\d)\.0/i.exec(navigator.userAgent)][0][1] == 6);

var $getElem = function (id) {
	return "string" == typeof id ? document.getElementById(id) : id;
};

var Class = {
	create: function() {
		return function() { this.initialize.apply(this, arguments); }
	}
}

var Extend = function(destination, source) {
	for (var property in source) {
		destination[property] = source[property];
	}
}

var Bind = function(object, fun) {
	return function() {
		return fun.apply(object, arguments);
	}
}

var BindAsEventListener = function(object, fun) {
	var args = Array.prototype.slice.call(arguments).slice(2);
	return function(event) {
		return fun.apply(object, [event || window.event].concat(args));
	}
}

var CurrentStyle = function(element){
	return element.currentStyle || document.defaultView.getComputedStyle(element, null);
}

function addEventHandler(oTarget, sEventType, fnHandler) {
	if (oTarget.addEventListener) {
		oTarget.addEventListener(sEventType, fnHandler, false);
	} else if (oTarget.attachEvent) {
		oTarget.attachEvent("on" + sEventType, fnHandler);
	} else {
		oTarget["on" + sEventType] = fnHandler;
	}
};

function removeEventHandler(oTarget, sEventType, fnHandler) {
    if (oTarget.removeEventListener) {
        oTarget.removeEventListener(sEventType, fnHandler, false);
    } else if (oTarget.detachEvent) {
        oTarget.detachEvent("on" + sEventType, fnHandler);
    } else {
        oTarget["on" + sEventType] = null;
    }
};

//圖片切割
var ImgCropper = Class.create();
ImgCropper.prototype = {
  //容器物件,控制層,圖片地址
  initialize: function(container, handle, url, options) {
	this._Container = $getElem(container);//容器物件
	this._layHandle = $getElem(handle);//控制層
	this.Url = url;//圖片地址

	this._layBase = this._Container.appendChild(document.createElement("img"));//底層
	this._layCropper = this._Container.appendChild(document.createElement("img"));//切割層
	this._layCropper.onload = Bind(this, this.SetPos);
	//用來設定大小
	this._tempImg = document.createElement("img");
	this._tempImg.onload = Bind(this, this.SetSize);

	this.SetOptions(options);

	this.Opacity = Math.round(this.options.Opacity);
	this.Color = this.options.Color;
	this.Scale = !!this.options.Scale;
	this.Ratio = Math.max(this.options.Ratio, 0);
	this.Width = Math.round(this.options.Width);
	this.Height = Math.round(this.options.Height);

	//設定預覽物件
	var oPreview = $getElem(this.options.Preview);//預覽物件
	if(oPreview){
		oPreview.style.position = "relative";
		oPreview.style.overflow = "hidden";
		this.viewWidth = Math.round(this.options.viewWidth);
		this.viewHeight = Math.round(this.options.viewHeight);
		//預覽圖片物件
		this._view = oPreview.appendChild(document.createElement("img"));
		this._view.style.position = "absolute";
		this._view.onload = Bind(this, this.SetPreview);
	}
	//設定拖放
	this._drag = new Drag(this._layHandle, { Limit: true, onMove: Bind(this, this.SetPos), Transparent: true });
	//設定縮放
	this.Resize = !!this.options.Resize;
	if(this.Resize){
		var op = this.options, _resize = new Resize(this._layHandle, { Max: true, onResize: Bind(this, this.SetPos) });
		//設定縮放觸發物件
		op.RightDown && (_resize.Set(op.RightDown, "right-down"));
		op.LeftDown && (_resize.Set(op.LeftDown, "left-down"));
		op.RightUp && (_resize.Set(op.RightUp, "right-up"));
		op.LeftUp && (_resize.Set(op.LeftUp, "left-up"));
		op.Right && (_resize.Set(op.Right, "right"));
		op.Left && (_resize.Set(op.Left, "left"));
		op.Down && (_resize.Set(op.Down, "down"));
		op.Up && (_resize.Set(op.Up, "up"));
		//最小範圍限制
		this.Min = !!this.options.Min;
		this.minWidth = Math.round(this.options.minWidth);
		this.minHeight = Math.round(this.options.minHeight);
		//設定縮放物件
		this._resize = _resize;
	}
	//設定樣式
	this._Container.style.position = "relative";
	this._Container.style.overflow = "hidden";
	this._layHandle.style.zIndex = 200;
	this._layCropper.style.zIndex = 100;
	this._layBase.style.position = this._layCropper.style.position = "absolute";
	this._layBase.style.top = this._layBase.style.left = this._layCropper.style.top = this._layCropper.style.left = 0;//對齊
	//初始化設定
	this.Init();
  },
  //設定預設屬性
  SetOptions: function(options) {
    this.options = {//預設值
		Opacity:	50,//透明度(0到100)
		Color:		"",//背景色
		Width:		0,//圖片高度
		Height:		0,//圖片高度
		//縮放觸發物件
		Resize:		false,//是否設定縮放
		Right:		"",//右邊縮放物件
		Left:		"",//左邊縮放物件
		Up:			"",//上邊縮放物件
		Down:		"",//下邊縮放物件
		RightDown:	"",//右下縮放物件
		LeftDown:	"",//左下縮放物件
		RightUp:	"",//右上縮放物件
		LeftUp:		"",//左上縮放物件
		Min:		false,//是否最小寬高限制(為true時下面min引數有用)
		minWidth:	50,//最小寬度
		minHeight:	50,//最小高度
		Scale:		false,//是否按比例縮放
		Ratio:		0,//縮放比例(寬/高)
		//預覽物件設定
		Preview:	"",//預覽物件
		viewWidth:	0,//預覽寬度
		viewHeight:	0//預覽高度
    };
    Extend(this.options, options || {});
  },
  //初始化物件
  Init: function() {
	//設定背景色
	this.Color && (this._Container.style.backgroundColor = this.Color);
	//設定圖片
	this._tempImg.src = this._layBase.src = this._layCropper.src = this.Url;
	//設定透明
	if(isIE){
		this._layBase.style.filter = "alpha(opacity:" + this.Opacity + ")";
	} else {
		this._layBase.style.opacity = this.Opacity / 100;
	}
	//設定預覽物件
	this._view && (this._view.src = this.Url);
	//設定縮放
	if(this.Resize){
		with(this._resize){
			Scale = this.Scale; Ratio = this.Ratio; Min = this.Min; minWidth = this.minWidth; minHeight = this.minHeight;
		}
	}
  },
  //設定切割樣式
  SetPos: function() {
	//ie6渲染bug
	if(isIE6){ with(this._layHandle.style){ zoom = .9; zoom = 1; }; };
	//獲取位置引數
	var p = this.GetPos();
	//按拖放物件的引數進行切割
	this._layCropper.style.clip = "rect(" + p.Top + "px " + (p.Left + p.Width) + "px " + (p.Top + p.Height) + "px " + p.Left + "px)";
	//設定預覽
	this.SetPreview();
  },
  //設定預覽效果
  SetPreview: function() {
	if(this._view){
		//預覽顯示的寬和高
		var p = this.GetPos(), s = this.GetSize(p.Width, p.Height, this.viewWidth, this.viewHeight), scale = s.Height / p.Height;
		//按比例設定引數
		var pHeight = this._layBase.height * scale, pWidth = this._layBase.width * scale, pTop = p.Top * scale, pLeft = p.Left * scale;
		//設定預覽物件
		with(this._view.style){
			//設定樣式
			width = pWidth + "px"; height = pHeight + "px"; top = - pTop + "px "; left = - pLeft + "px";
			//切割預覽圖
			clip = "rect(" + pTop + "px " + (pLeft + s.Width) + "px " + (pTop + s.Height) + "px " + pLeft + "px)";
		}
	}
  },
  //設定圖片大小
  SetSize: function() {
	var s = this.GetSize(this._tempImg.width, this._tempImg.height, this.Width, this.Height);
	//設定底圖和切割圖
	this._layBase.style.width = this._layCropper.style.width = s.Width + "px";
	this._layBase.style.height = this._layCropper.style.height = s.Height + "px";
	//設定拖放範圍
	this._drag.mxRight = s.Width; this._drag.mxBottom = s.Height;
	//設定縮放範圍
	//if(this.Resize){ this._resize.mxRight = s.Width; this._resize.mxBottom = s.Height; }
	/*2015-9-6 15:45:16修改by wqj*/
	if(this.Resize){ this._resize.mxRight = Math.round(s.Width); this._resize.mxBottom = Math.round(s.Height); }
  },
  //獲取當前樣式
  GetPos: function() {
	with(this._layHandle){
		return { Top: offsetTop, Left: offsetLeft, Width: offsetWidth, Height: offsetHeight }
	}
  },
  //獲取尺寸
  GetSize: function(nowWidth, nowHeight, fixWidth, fixHeight) {
	var iWidth = nowWidth, iHeight = nowHeight, scale = iWidth / iHeight;
	//按比例設定
	if(fixHeight){ iWidth = (iHeight = fixHeight) * scale; }
	if(fixWidth && (!fixHeight || iWidth > fixWidth)){ iHeight = (iWidth = fixWidth) / scale; }
	//返回尺寸物件
	return { Width: iWidth, Height: iHeight }
  }
};
//拖放程式
var Drag = Class.create();
Drag.prototype = {
  //拖放物件
  initialize: function(drag, options) {
	this.Drag = $getElem(drag);//拖放物件
	this._x = this._y = 0;//記錄滑鼠相對拖放物件的位置
	this._marginLeft = this._marginTop = 0;//記錄margin
	//事件物件(用於繫結移除事件)
	this._fM = BindAsEventListener(this, this.Move);
	this._fS = Bind(this, this.Stop);

	this.SetOptions(options);

	this.Limit = !!this.options.Limit;
	this.mxLeft = parseInt(this.options.mxLeft);
	this.mxRight = parseInt(this.options.mxRight);
	this.mxTop = parseInt(this.options.mxTop);
	this.mxBottom = parseInt(this.options.mxBottom);

	this.LockX = !!this.options.LockX;
	this.LockY = !!this.options.LockY;
	this.Lock = !!this.options.Lock;

	this.onStart = this.options.onStart;
	this.onMove = this.options.onMove;
	this.onStop = this.options.onStop;

	this._Handle = $getElem(this.options.Handle) || this.Drag;
	this._mxContainer = $getElem(this.options.mxContainer) || null;

	this.Drag.style.position = "absolute";
	//透明
	if(isIE && !!this.options.Transparent){
		//填充拖放物件
		with(this._Handle.appendChild(document.createElement("div")).style){
			width = height = "100%"; backgroundColor = "#fff"; filter = "alpha(opacity:0)"; fontSize = 0;
		}
	}
	//修正範圍
	this.Repair();
	addEventHandler(this._Handle, "mousedown", BindAsEventListener(this, this.Start));
  },
  //設定預設屬性
  SetOptions: function(options) {
	this.options = {//預設值
		Handle:			"",//設定觸發物件(不設定則使用拖放物件)
		Limit:			false,//是否設定範圍限制(為true時下面引數有用,可以是負數)
		mxLeft:			0,//左邊限制
		mxRight:		9999,//右邊限制
		mxTop:			0,//上邊限制
		mxBottom:		9999,//下邊限制
		mxContainer:	"",//指定限制在容器內
		LockX:			false,//是否鎖定水平方向拖放
		LockY:			false,//是否鎖定垂直方向拖放
		Lock:			false,//是否鎖定
		Transparent:	false,//是否透明
		onStart:		function(){},//開始移動時執行
		onMove:			function(){},//移動時執行
		onStop:			function(){}//結束移動時執行
	};
	Extend(this.options, options || {});
  },
  //準備拖動
  Start: function(oEvent) {
	if(this.Lock){ return; }
	this.Repair();
	//記錄滑鼠相對拖放物件的位置
	this._x = oEvent.clientX - this.Drag.offsetLeft;
	this._y = oEvent.clientY - this.Drag.offsetTop;
	//記錄margin
	this._marginLeft = parseInt(CurrentStyle(this.Drag).marginLeft) || 0;
	this._marginTop = parseInt(CurrentStyle(this.Drag).marginTop) || 0;
	//mousemove時移動 mouseup時停止
	addEventHandler(document, "mousemove", this._fM);
	addEventHandler(document, "mouseup", this._fS);
	if(isIE){
		//焦點丟失
		addEventHandler(this._Handle, "losecapture", this._fS);
		//設定滑鼠捕獲
		this._Handle.setCapture();
	}else{
		//焦點丟失
		addEventHandler(window, "blur", this._fS);
		//阻止預設動作
		oEvent.preventDefault();
	};
	//附加程式
	this.onStart();
  },
  //修正範圍
  Repair: function() {
	if(this.Limit){
		//修正錯誤範圍引數
		this.mxRight = Math.max(this.mxRight, this.mxLeft + this.Drag.offsetWidth);
		this.mxBottom = Math.max(this.mxBottom, this.mxTop + this.Drag.offsetHeight);
		//如果有容器必須設定position為relative或absolute來相對或絕對定位,並在獲取offset之前設定
		!this._mxContainer || CurrentStyle(this._mxContainer).position == "relative" || CurrentStyle(this._mxContainer).position == "absolute" || (this._mxContainer.style.position = "relative");
	}
  },
  //拖動
  Move: function(oEvent) {
	//判斷是否鎖定
	if(this.Lock){ this.Stop(); return; };
	//清除選擇
	window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
	//設定移動引數
	var iLeft = oEvent.clientX - this._x, iTop = oEvent.clientY - this._y;
	//設定範圍限制
	if(this.Limit){
		//設定範圍引數
		var mxLeft = this.mxLeft, mxRight = this.mxRight, mxTop = this.mxTop, mxBottom = this.mxBottom;
		//如果設定了容器,再修正範圍引數
		if(!!this._mxContainer){
			mxLeft = Math.max(mxLeft, 0);
			mxTop = Math.max(mxTop, 0);
			mxRight = Math.min(mxRight, this._mxContainer.clientWidth);
			mxBottom = Math.min(mxBottom, this._mxContainer.clientHeight);
		};
		//修正移動引數
		iLeft = Math.max(Math.min(iLeft, mxRight - this.Drag.offsetWidth), mxLeft);
		iTop = Math.max(Math.min(iTop, mxBottom - this.Drag.offsetHeight), mxTop);
	}
	//設定位置,並修正margin
	if(!this.LockX){ this.Drag.style.left = iLeft - this._marginLeft + "px"; }
	if(!this.LockY){ this.Drag.style.top = iTop - this._marginTop + "px"; }
	//附加程式
	this.onMove();
  },
  //停止拖動
  Stop: function() {
	//移除事件
	removeEventHandler(document, "mousemove", this._fM);
	removeEventHandler(document, "mouseup", this._fS);
	if(isIE){
		removeEventHandler(this._Handle, "losecapture", this._fS);
		this._Handle.releaseCapture();
	}else{
		removeEventHandler(window, "blur", this._fS);
	};
	//附加程式
	this.onStop();
  }
};
//縮放程式
var Resize = Class.create();
Resize.prototype = {
  //縮放物件
  initialize: function(obj, options) {
	this._obj = $getElem(obj);//縮放物件

	this._styleWidth = this._styleHeight = this._styleLeft = this._styleTop = 0;//樣式引數
	this._sideRight = this._sideDown = this._sideLeft = this._sideUp = 0;//座標引數
	this._fixLeft = this._fixTop = 0;//定位引數
	this._scaleLeft = this._scaleTop = 0;//定位座標

	this._mxSet = function(){};//範圍設定程式
	this._mxRightWidth = this._mxDownHeight = this._mxUpHeight = this._mxLeftWidth = 0;//範圍引數
	this._mxScaleWidth = this._mxScaleHeight = 0;//比例範圍引數

	this._fun = function(){};//縮放執行程式

	//獲取邊框寬度
	var _style = CurrentStyle(this._obj);
	this._borderX = (parseInt(_style.borderLeftWidth) || 0) + (parseInt(_style.borderRightWidth) || 0);
	this._borderY = (parseInt(_style.borderTopWidth) || 0) + (parseInt(_style.borderBottomWidth) || 0);
	//事件物件(用於繫結移除事件)
	this._fR = BindAsEventListener(this, this.Resize);
	this._fS = Bind(this, this.Stop);

	this.SetOptions(options);
	//範圍限制
	this.Max = !!this.options.Max;
	this._mxContainer = $getElem(this.options.mxContainer) || null;
	this.mxLeft = Math.round(this.options.mxLeft);
	this.mxRight = Math.round(this.options.mxRight);
	this.mxTop = Math.round(this.options.mxTop);
	this.mxBottom = Math.round(this.options.mxBottom);
	//寬高限制
	this.Min = !!this.options.Min;
	this.minWidth = Math.round(this.options.minWidth);
	this.minHeight = Math.round(this.options.minHeight);
	//按比例縮放
	this.Scale = !!this.options.Scale;
	this.Ratio = Math.max(this.options.Ratio, 0);

	this.onResize = this.options.onResize;

	this._obj.style.position = "absolute";
	!this._mxContainer || CurrentStyle(this._mxContainer).position == "relative" || (this._mxContainer.style.position = "relative");
  },
  //設定預設屬性
  SetOptions: function(options) {
    this.options = {//預設值
		Max:		false,//是否設定範圍限制(為true時下面mx引數有用)
		mxContainer:"",//指定限制在容器內
		mxLeft:		0,//左邊限制
		mxRight:	9999,//右邊限制
		mxTop:		0,//上邊限制
		mxBottom:	9999,//下邊限制
		Min:		false,//是否最小寬高限制(為true時下面min引數有用)
		minWidth:	50,//最小寬度
		minHeight:	50,//最小高度
		Scale:		false,//是否按比例縮放
		Ratio:		0,//縮放比例(寬/高)
		onResize:	function(){}//縮放時執行
    };
    Extend(this.options, options || {});
  },
  //設定觸發物件
  Set: function(resize, side) {
	var resize = $getElem(resize), fun;
	if(!resize) return;
	//根據方向設定
	switch (side.toLowerCase()) {
	case "up" :
		fun = this.Up;
		break;
	case "down" :
		fun = this.Down;
		break;
	case "left" :
		fun = this.Left;
		break;
	case "right" :
		fun = this.Right;
		break;
	case "left-up" :
		fun = this.LeftUp;
		break;
	case "right-up" :
		fun = this.RightUp;
		break;
	case "left-down" :
		fun = this.LeftDown;
		break;
	case "right-down" :
	default :
		fun = this.RightDown;
	};
	//設定觸發物件
	addEventHandler(resize, "mousedown", BindAsEventListener(this, this.Start, fun));
  },
  //準備縮放
  Start: function(e, fun, touch) {
	//防止冒泡(跟拖放配合時設定)
	e.stopPropagation ? e.stopPropagation() : (e.cancelBubble = true);
	//設定執行程式
	this._fun = fun;
	//樣式引數值
	this._styleWidth = this._obj.clientWidth;
	this._styleHeight = this._obj.clientHeight;
	this._styleLeft = this._obj.offsetLeft;
	this._styleTop = this._obj.offsetTop;
	//四條邊定位座標
	this._sideLeft = e.clientX - this._styleWidth;
	this._sideRight = e.clientX + this._styleWidth;
	this._sideUp = e.clientY - this._styleHeight;
	this._sideDown = e.clientY + this._styleHeight;
	//top和left定位引數
	this._fixLeft = this._styleLeft + this._styleWidth;
	this._fixTop = this._styleTop + this._styleHeight;
	//縮放比例
	if(this.Scale){
		//設定比例
		this.Ratio = Math.max(this.Ratio, 0) || this._styleWidth / this._styleHeight;
		//left和top的定位座標
		this._scaleLeft = this._styleLeft + this._styleWidth / 2;
		this._scaleTop = this._styleTop + this._styleHeight / 2;
	};
	//範圍限制
	if(this.Max){
		//設定範圍引數
		var mxLeft = this.mxLeft, mxRight = this.mxRight, mxTop = this.mxTop, mxBottom = this.mxBottom;
		//如果設定了容器,再修正範圍引數
		if(!!this._mxContainer){
			mxLeft = Math.max(mxLeft, 0);
			mxTop = Math.max(mxTop, 0);
			mxRight = Math.min(mxRight, this._mxContainer.clientWidth);
			mxBottom = Math.min(mxBottom, this._mxContainer.clientHeight);
		};
		//根據最小值再修正
		mxRight = Math.max(mxRight, mxLeft + (this.Min ? this.minWidth : 0) + this._borderX);
		mxBottom = Math.max(mxBottom, mxTop + (this.Min ? this.minHeight : 0) + this._borderY);
		//由於轉向時要重新設定所以寫成function形式
		this._mxSet = function(){
			this._mxRightWidth = mxRight - this._styleLeft - this._borderX;
			this._mxDownHeight = mxBottom - this._styleTop - this._borderY;
			this._mxUpHeight = Math.max(this._fixTop - mxTop, this.Min ? this.minHeight : 0);
			this._mxLeftWidth = Math.max(this._fixLeft - mxLeft, this.Min ? this.minWidth : 0);
		};
		this._mxSet();
		//有縮放比例下的範圍限制
		if(this.Scale){
			this._mxScaleWidth = Math.min(this._scaleLeft - mxLeft, mxRight - this._scaleLeft - this._borderX) * 2;
			this._mxScaleHeight = Math.min(this._scaleTop - mxTop, mxBottom - this._scaleTop - this._borderY) * 2;
		};
	};
	//mousemove時縮放 mouseup時停止
	addEventHandler(document, "mousemove", this._fR);
	addEventHandler(document, "mouseup", this._fS);
	if(isIE){
		addEventHandler(this._obj, "losecapture", this._fS);
		this._obj.setCapture();
	}else{
		addEventHandler(window, "blur", this._fS);
		e.preventDefault();
	};
  },
  //縮放
  Resize: function(e) {
	//清除選擇
	window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
	//執行縮放程式
	this._fun(e);
	//設定樣式,變數必須大於等於0否則ie出錯
	with(this._obj.style){
		width = this._styleWidth + "px"; height = this._styleHeight + "px";
		top = this._styleTop + "px"; left = this._styleLeft + "px";
	}
	//附加程式
	this.onResize();
  },
  //縮放程式
  //上
  Up: function(e) {
	this.RepairY(this._sideDown - e.clientY, this._mxUpHeight);
	this.RepairTop();
	this.TurnDown(this.Down);
  },
  //下
  Down: function(e) {
	this.RepairY(e.clientY - this._sideUp, this._mxDownHeight);
	this.TurnUp(this.Up);
  },
  //右
  Right: function(e) {
	this.RepairX(e.clientX - this._sideLeft, this._mxRightWidth);
	this.TurnLeft(this.Left);
  },
  //左
  Left: function(e) {
	this.RepairX(this._sideRight - e.clientX, this._mxLeftWidth);
	this.RepairLeft();
	this.TurnRight(this.Right);
  },
  //右下
  RightDown: function(e) {
	this.RepairAngle(
		e.clientX - this._sideLeft, this._mxRightWidth,
		e.clientY - this._sideUp, this._mxDownHeight
	);
	this.TurnLeft(this.LeftDown) || this.Scale || this.TurnUp(this.RightUp);
  },
  //右上
  RightUp: function(e) {
	this.RepairAngle(
		e.clientX - this._sideLeft, this._mxRightWidth,
		this._sideDown - e.clientY, this._mxUpHeight
	);
	this.RepairTop();
	this.TurnLeft(this.LeftUp) || this.Scale || this.TurnDown(this.RightDown);
  },
  //左下
  LeftDown: function(e) {
	this.RepairAngle(
		this._sideRight - e.clientX, this._mxLeftWidth,
		e.clientY - this._sideUp, this._mxDownHeight
	);
	this.RepairLeft();
	this.TurnRight(this.RightDown) || this.Scale || this.TurnUp(this.LeftUp);
  },
  //左上
  LeftUp: function(e) {
	this.RepairAngle(
		this._sideRight - e.clientX, this._mxLeftWidth,
		this._sideDown - e.clientY, this._mxUpHeight
	);
	this.RepairTop(); this.RepairLeft();
	this.TurnRight(this.RightUp) || this.Scale || this.TurnDown(this.LeftDown);
  },
  //修正程式
  //水平方向
  RepairX: function(iWidth, mxWidth) {
	iWidth = this.RepairWidth(iWidth, mxWidth);
	if(this.Scale){
		var iHeight = this.RepairScaleHeight(iWidth);
		if(this.Max && iHeight > this._mxScaleHeight){
			iHeight = this._mxScaleHeight;
			iWidth = this.RepairScaleWidth(iHeight);
		}else if(this.Min && iHeight < this.minHeight){
			var tWidth = this.RepairScaleWidth(this.minHeight);
			if(tWidth < mxWidth){ iHeight = this.minHeight; iWidth = tWidth; }
		}
		this._styleHeight = iHeight;
		this._styleTop = this._scaleTop - iHeight / 2;
	}
	this._styleWidth = iWidth;
  },
  //垂直方向
  RepairY: function(iHeight, mxHeight) {
	iHeight = this.RepairHeight(iHeight, mxHeight);
	if(this.Scale){
		var iWidth = this.RepairScaleWidth(iHeight);
		if(this.Max && iWidth > this._mxScaleWidth){
			iWidth = this._mxScaleWidth;
			iHeight = this.RepairScaleHeight(iWidth);
		}else if(this.Min && iWidth < this.minWidth){
			var tHeight = this.RepairScaleHeight(this.minWidth);
			if(tHeight < mxHeight){ iWidth = this.minWidth; iHeight = tHeight; }
		}
		this._styleWidth = iWidth;
		this._styleLeft = this._scaleLeft - iWidth / 2;
	}
	this._styleHeight = iHeight;
  },
  //對角方向
  RepairAngle: function(iWidth, mxWidth, iHeight, mxHeight) {
	iWidth = this.RepairWidth(iWidth, mxWidth);
	if(this.Scale){
		iHeight = this.RepairScaleHeight(iWidth);
		if(this.Max && iHeight > mxHeight){
			iHeight = mxHeight;
			iWidth = this.RepairScaleWidth(iHeight);
		}else if(this.Min && iHeight < this.minHeight){
			var tWidth = this.RepairScaleWidth(this.minHeight);
			if(tWidth < mxWidth){ iHeight = this.minHeight; iWidth = tWidth; }
		}
	}else{
		iHeight = this.RepairHeight(iHeight, mxHeight);
	}
	this._styleWidth = iWidth;
	this._styleHeight = iHeight;
  },
  //top
  RepairTop: function() {
	this._styleTop = this._fixTop - this._styleHeight;
  },
  //left
  RepairLeft: function() {
	this._styleLeft = this._fixLeft - this._styleWidth;
  },
  //height
  RepairHeight: function(iHeight, mxHeight) {
	iHeight = Math.min(this.Max ? mxHeight : iHeight, iHeight);
	iHeight = Math.max(this.Min ? this.minHeight : iHeight, iHeight, 0);
	return iHeight;
  },
  //width
  RepairWidth: function(iWidth, mxWidth) {
	iWidth = Math.min(this.Max ? mxWidth : iWidth, iWidth);
	iWidth = Math.max(this.Min ? this.minWidth : iWidth, iWidth, 0);
	return iWidth;
  },
  //比例高度
  RepairScaleHeight: function(iWidth) {
	return Math.max(Math.round((iWidth + this._borderX) / this.Ratio - this._borderY), 0);
  },
  //比例寬度
  RepairScaleWidth: function(iHeight) {
	return Math.max(Math.round((iHeight + this._borderY) * this.Ratio - this._borderX), 0);
  },
  //轉向程式
  //轉右
  TurnRight: function(fun) {
	if(!(this.Min || this._styleWidth)){
		this._fun = fun;
		this._sideLeft = this._sideRight;
		this.Max && this._mxSet();
		return true;
	}
  },
  //轉左
  TurnLeft: function(fun) {
	if(!(this.Min || this._styleWidth)){
		this._fun = fun;
		this._sideRight = this._sideLeft;
		this._fixLeft = this._styleLeft;
		this.Max && this._mxSet();
		return true;
	}
  },
  //轉上
  TurnUp: function(fun) {
	if(!(this.Min || this._styleHeight)){
		this._fun = fun;
		this._sideDown = this._sideUp;
		this._fixTop = this._styleTop;
		this.Max && this._mxSet();
		return true;
	}
  },
  //轉下
  TurnDown: function(fun) {
	if(!(this.Min || this._styleHeight)){
		this._fun = fun;
		this._sideUp = this._sideDown;
		this.Max && this._mxSet();
		return true;
	}
  },
  //停止縮放
  Stop: function() {
	removeEventHandler(document, "mousemove", this._fR);
	removeEventHandler(document, "mouseup", this._fS);
	if(isIE){
		removeEventHandler(this._obj, "losecapture", this._fS);
		this._obj.releaseCapture();
	}else{
		removeEventHandler(window, "blur", this._fS);
	}
  }
};
2.頭像剪下頁面我也進行了一些部件,佈局樣式是參考了百度頭像上傳佈局,上傳圖片使用了ajaxFileUpload.js外掛

需要注意的是:

a.ajaxFileUpload外掛上傳圖片,服務端返回的json時,response需要設定contentType為text/html;charset=UTF-8,不然ajaxFileUpload外掛不會靜success回撥方法,除錯ajaxFileUpload可以看返回的json被加上了pre標籤,也可以在uploadHttpData屬性定義裡將pre標籤去除

b.使用ajaxFileUpload外掛時,還可能遇見一個錯誤就是jQuery.handleError 方法未定義,由於jquery1.4.2以後的版本都把這個方法去掉了,所以需要我們自己將1.4.1版本的handleError方法copy到jquery架包中或ajaxFileUpload架包中,我是copy到ajaxFileUpload架包中的

新增handleError方法後的ajaxFileUpload程式碼:

jQuery.extend({

    createUploadIframe: function(id, uri)
	{
			//create frame
            var frameId = 'jUploadFrame' + id;

            if(window.ActiveXObject) {
                var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />');
                if(typeof uri== 'boolean'){
                    io.src = 'javascript:false';
                }
                else if(typeof uri== 'string'){
                    io.src = uri;
                }
            }
            else {
                var io = document.createElement('iframe');
                io.id = frameId;
                io.name = frameId;
            }
            io.style.position = 'absolute';
            io.style.top = '-1000px';
            io.style.left = '-1000px';

            document.body.appendChild(io);

            return io
    },
    createUploadForm: function(id, fileElementId)
	{
		//create form
		var formId = 'jUploadForm' + id;
		var fileId = 'jUploadFile' + id;
		var form = $('<form  action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>');
		var oldElement = $('#' + fileElementId);
		var newElement = $(oldElement).clone();
		$(oldElement).attr('id', fileId);
		$(oldElement).before(newElement);
		$(oldElement).appendTo(form);
		//set attributes
		$(form).css('position', 'absolute');
		$(form).css('top', '-1200px');
		$(form).css('left', '-1200px');
		$(form).appendTo('body');
		return form;
    },

    ajaxFileUpload: function(s) {
        // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout
        s = jQuery.extend({}, jQuery.ajaxSettings, s);
        var id = s.fileElementId;
		var form = jQuery.createUploadForm(id, s.fileElementId);
		var io = jQuery.createUploadIframe(id, s.secureuri);
		var frameId = 'jUploadFrame' + id;
		var formId = 'jUploadForm' + id;
        // Watch for a new set of requests
        if ( s.global && ! jQuery.active++ )
		{
			jQuery.event.trigger( "ajaxStart" );
		}
        var requestDone = false;
        // Create the request object
        var xml = {}
        if ( s.global )
            jQuery.event.trigger("ajaxSend", [xml, s]);
        // Wait for a response to come back
        var uploadCallback = function(isTimeout)
		{
			var io = document.getElementById(frameId);
            try
			{
				if(io.contentWindow)
				{
					 xml.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null;
                	 xml.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document;

				}else if(io.contentDocument)
				{
					 xml.responseText = io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:null;
                	xml.responseXML = io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocument:io.contentDocument.document;
				}
            }catch(e)
			{
				jQuery.handleError(s, xml, null, e);
			}
            if ( xml || isTimeout == "timeout")
			{
                requestDone = true;
                var status;
                try {
                    status = isTimeout != "timeout" ? "success" : "error";
                    // Make sure that the request was successful or notmodified
                    if ( status != "error" )
					{
                        // process the data (runs the xml through httpData regardless of callback)
                        var data = jQuery.uploadHttpData( xml, s.dataType );
                        // If a local callback was specified, fire it and pass it the data
                        if ( s.success )
                            s.success( data, status );

                        // Fire the global callback
                        if( s.global )
                            jQuery.event.trigger( "ajaxSuccess", [xml, s] );
                    } else
                        jQuery.handleError(s, xml, status);
                } catch(e)
				{
                    status = "error";
                    jQuery.handleError(s, xml, status, e);
                }

                // The request was completed
                if( s.global )
                    jQuery.event.trigger( "ajaxComplete", [xml, s] );

                // Handle the global AJAX counter
                if ( s.global && ! --jQuery.active )
                    jQuery.event.trigger( "ajaxStop" );

                // Process result
                if ( s.complete )
                    s.complete(xml, status);

                jQuery(io).unbind()

                setTimeout(function()
									{	try
										{
											$(io).remove();
											$(form).remove();

										} catch(e)
										{
											jQuery.handleError(s, xml, null, e);
										}

									}, 100)

                xml = null

            }
        }
        // Timeout checker
        if ( s.timeout > 0 )
		{
            setTimeout(function(){
                // Check to see if the request is still happening
                if( !requestDone ) uploadCallback( "timeout" );
            }, s.timeout);
        }
        try
		{
           // var io = $('#' + frameId);
			var form = $('#' + formId);
			$(form).attr('action', s.url);
			$(form).attr('method', 'POST');
			$(form).attr('target', frameId);
            if(form.encoding)
			{
                form.encoding = 'multipart/form-data';
            }
            else
			{
                form.enctype = 'multipart/form-data';
            }
            $(form).submit();

        } catch(e)
		{
            jQuery.handleError(s, xml, null, e);
        }
        if(window.attachEvent){
            document.getElementById(frameId).attachEvent('onload', uploadCallback);
        }
        else{
            document.getElementById(frameId).addEventListener('load', uploadCallback, false);
        }
        return {abort: function () {}};

    },

    uploadHttpData: function( r, type ) {
        var data = !type;
        data = type == "xml" || data ? r.responseXML : r.responseText;
        // If the type is "script", eval it in global context
        if ( type == "script" )
            jQuery.globalEval( data );
        // Get the JavaScript object, if JSON is used.
        if ( type == "json" )
            eval( "data = " + data );
        // evaluate scripts within html
        if ( type == "html" )
            jQuery("<div>").html(data).evalScripts();
			//alert($('param', data).each(function(){alert($(this).attr('value'));}));
        return data;
    },
    handleError: function( s, xhr, status, e ) {
		// If a local callback was specified, fire it
		if ( s.error ) {
			s.error.call( s.context || s, xhr, status, e );
		}

		// Fire the global callback
		if ( s.global ) {
			(s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] );
		}
	}
});



頁面佈局如下

擷取頁面佈局原始碼

<pre name="code" class="html"><%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:set var="ctxPath" value="${pageContext.request.contextPath}" ></c:set>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>圖片裁剪及上傳</title>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<!--  <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />  -->
	<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
	<style type="text/css">
body,ul,li,h1,h2,h3,h4,h5,h6,p,form,dl,dt,dd,input,label,span,img{margin: 0px;padding: 0px; list-style:none outside none;}
body,button,input,select,textarea{font:12px/1.5 Tahoma,Helvetica,Arial,"宋體",sans-serif; color:#333;}
a{ text-decoration:none;color:#333;}
a:hover{text-decoration:none;color:#C00;}
.passPortraitWrapper{

}
.passPortraitBox{
	width:680px;
	margin:0px auto;
	padding:10px;
	overflow:hidden;
}
.passPortraitLeftSide{
	display:inline;
	float:left;
	width:440px;
}
.selectPortaitLabel{
	position:relative;
	padding-bottom:10px;
}
.portraitFile{
	height:38px;
	line-height:38px;
	width:130px;
	position:absolute;
	left:0px;
	overflow:hidden;
	font-size:24px;
	opacity: 0;
	filter: alpha(opacity=0);

}
.portraitBtn{
	height:38px;
	line-height:38px;
	width:130px;
	border: medium none;
	background: transparent url('${ctxPath}/resources/images/ImgCropper/crop_img_sprite.png') no-repeat scroll 0% 0%;

}
.selectPortraitBtn{
	background-position:0px 0px;
	color:#666;
}
.selectPortaitNote{
	display:inline-block;
	position:absolute;
	font-size:12px;
	height:24px;
	line-height:24px;
	color:#999;
	text-align:left;
	top: 8px;
	left: 140px;
}
.portraitFilePath{
	display:block;
	color:#999;
	line-height:20px;
}
.portraitBox{
	height:300px;
	width:440px;
	overflow:auto;
}
.portraitBG{
	height:300px;
	line-height:300px;
	width:400px;
	background:#E2E2E2 none repeat scroll 0% 0%;
	position:absolute;
}
.portraitLoad{
	height:16px;
	width:16px;
	font-size:0px;
	position:absolute;
	top:142px;
	left:192px;
	z-index:100;
}
.portraitPosition{
	position: relative;
	left: 50%;
	top: 50%;
}
.portraitSelection{
	width: 404px;
	height: 304px;
	position: absolute;
	top: -2px;
	left: -2px;
	cursor: crosshair;
	z-index: 290;
}
.portraitImg{

}
.okPortraitLabel{
	padding-top:10px;
	 position:relative;
}
.okPortraitBtn{
 background-position:0px -38px;
 color:#fefefe;
}
.okPortraitBtn_disable{
	background-position:0px -151px;
}
.passPortraitRightSide{
	display:inline;
	float:right;
	width:180px;
	height:390px;
	border-left:1px solid #E5E5E5;
	padding-left:36px;
	margin-left:10px;
	position:relative;
}
.portraitPreviewBox{
	position:absolute;
	top:0px;
}
.portraitPreviewLabel{
	height:38px;
	line-height:38px;
	font-size:14px;
	color:#666;
}
.portraitPreviewContent{
	height:160px;
	width:160px;
	border:1px dashed #000;
}
.portraitPresetBox{
	position:absolute;
	bottom:0px;
}
.portraitPresetLabel{
	height:38px;
	line-height:38px;
	font-size:14px;
	color:#666;
}
.portraitPresetContent{
	width:180px;
	height:80px;
	overflow:hidden;
	position:relative;
	border:1px solid #eee;
}
.portraitPresetUl{
	width:1000px;
}
.portraitPresetLi{
	height:80px;
	width:80px;
	float:left;
}
.portraitPresetArrowBox{
	width:180px;
	position:absolute;
	right:0px;
	top:0px;
}
.portraitPresetArrow{
	width:16px;
	height:16px;
	position:absolute;
}
.portraitPresetPrep{
	background:url('${ctxPath}/resources/images/ImgCropper/previous.png') no-repeat;
	left:0px;
	top:32px
}
.portraitPresetNext{
	background:url('${ctxPath}/resources/images/ImgCropper/next.png') no-repeat;
	right:0px;
	top:32px
}
.portraitPresetArrowBG{
	width:16px;
	height:80px;
	position:absolute;
	top:0px;
}
.portraitPresetPrepBG{
	background:#777;
	left:0px;
}
.portraitPresetNextBG{
	background:#777;
	right:0px;
}
.msg_content{
	height:20px;
	line-height:20px;
	text-align:left;
	color:#999;
	position:absolute;
	padding-left:20px;
	top:18px;
	left:140px;
}
.msg_icon{
	width:16px;
	height:16px;
	font-size:0px;
	position:absolute;
	top:2px;
	left:2px;
}
.msg_icon_ok{
	background:url('${ctxPath}/resources/images/icons/ok.gif') no-repeat;
}
.msg_icon_warning{
	background:url('${ctxPath}/resources/images/icons/warning.gif') no-repeat;
}
.msg_icon_info{
	background:url('${ctxPath}/resources/images/icons/info.gif') no-repeat;
}
.imgViewBG{
	height:300px;
	background:#E2E2E2;
	position:relative;
}
#imgView{
}
/*頁籤佈局開始*/
.tab_wrap{

}
.tab_nav_group{
	background:#ccc;
	overflow:hidden;
}
.tab_nav_ul{

}
.tab_nav_li{
	height:24px;
	line-height:24px;
	padding:0px 10px;
	border-right:1px solid #999;
	float:left;
	cursor:pointer;
}
.tab_nav_cuur{
	background:#fff;
}
.tab_content{
	overflow:hidden;
}
/*頁籤佈局結束*/
#rRightDown,#rLeftDown,#rLeftUp,#rRightUp,#rRight,#rLeft,#rUp,#rDown{
	position:absolute;
	background:#FFF;
	border: 1px solid #333;
	width: 6px;
	height: 6px;
	z-index:500;
	font-size:0;
	opacity: 0.5;
	filter:alpha(opacity=50);
}

#rLeftDown,#rRightUp{cursor:ne-resize;}
#rRightDown,#rLeftUp{cursor:nw-resize;}
#rRight,#rLeft{cursor:e-resize;}
#rUp,#rDown{cursor:n-resize;}
#rLeftDown{left:-4px;bottom:-4px;}
#rRightUp{right:-4px;top:-4px;}
#rRightDown{right:-4px;bottom:-4px;background-color:#00F;}
#rLeftUp{left:-4px;top:-4px;}
#rRight{right:-4px;top:50%;margin-top:-4px;}
#rLeft{left:-4px;top:50%;margin-top:-4px;}
#rUp{top:-4px;left:50%;margin-left:-4px;}
#rDown{bottom:-4px;left:50%;margin-left:-4px;}
#bgDiv{position:relative;}
#dragDiv{border:1px dashed #000; width:100px; height:100px; top:0px; left:0px; cursor:move;position:absolute; }
	</style>
	<!-- 匯入js架包 -->
	<script type="text/javascript" src="${ctxPath}/resources/js/jquery/jquery-1.9.1.js"></script>
	<script type="text/javascript" src="${ctxPath}/resources/js/ImgCropper/ImgCropper-integration.js" ></script>
	<script type="text/javascript" src="${ctxPath}/resources/js/util/ajaxFileUpload.js" ></script>
	<script type="text/javascript" src="${ctxPath}/resources/js/imgReady/imgReady.js" ></script>
	<script type="text/javascript">
		var requestObj = {
			attachAction:"${ctxPath}/uploadController?action=uploadAttach",
			clipAction:"${ctxPath}/uploadController?action=clipImg"
		};
		var backImage = {id:"",url:"",clipId:"",clipUrl:""};
		//頁籤標記
		var tabFlag = 0;
		var msgObj = {
		    '0': '成功上傳圖片',
		    '1': '圖片剪下成功',
		    '2': '請選擇裁剪區域',
		    '3': '請上傳正確格式圖片',
		    '4': '上傳檔案異常',
		    errnoErrno: 5,
		    successErrno: 0,
		    errnoPortraitMsg: '獲取圖片失敗',
		    errImgMsg: '請上傳正確格式圖片',
		    errCropMsg: '請選擇裁剪區域',
		    errUploadMsg: '上傳失敗'
		};
		var ic , scale = 1;
		/* function selectImgFile(){
			document.getElementById("fileImg").click();
		} */
		function uploadImg(file){
			var fileId = file.id;
			if(!validateImg(file)){
				return;
			}
			if(tabFlag == 0){
				$("#portraitLoad1").css("display","block");
				$("#bgDiv").css("display","none");
			}else{
				$("#portraitLoad2").css("display","block");
				$("#imgView").css("display","none");
			}
			 $.ajaxFileUpload({
			        url: requestObj.attachAction,
			        fileElementId: fileId,
			        dataType: 'json',
			        data: {},
			        success: function (m, l) {
			          if (m.errno == msgObj.successErrno) {
			        	  backImage.id = m.picId;
			        	  backImage.clipId = m.picId;
				          backImage.url = decodeURIComponent(decodeURIComponent(m.portraitUrl));
				          backImage.clipUrl = decodeURIComponent(decodeURIComponent(m.portraitUrl));
			      		if(tabFlag == 0){
			      			showCrop();
			      			$("#clip_ok").removeClass("okPortraitBtn_disable");
			      			$("#file_btn1").val("重新選擇");
			      		}else{
							showImgView();
							$("#upload_ok").removeClass("okPortraitBtn_disable");
							$("#file_btn2").val("重新選擇");
			      		}
			      		showPromptInfo(m.errno, "");

			          } else {
			            if (m.errno == 1) {
							showPromptInfo(m.errno, msgObj.errUploadMsg);
			            } else {
							showPromptInfo(m.errno, msgObj[m.errno] || msgObj.errUploadMsg);
			            }
			          }
			        }
			 });
		}
		function showCrop(){
			$("#portraitLoad1").css("display","none");
			var url = backImage.clipUrl;
			var containerWidth = 400;
			var containerHeight = 300;
			var widthScale = 1.0 ,heightScale = 1.0;
			//圖片在div中的高寬度
			var imgBoxHeight = 0,imgBoxWidth = 0;
			//圖片的實際高寬
			var imgHeight = 0;
			var imgWidth = 0;
			//載入圖片高度寬度
			imgReady(url,function(){
				imgHeight = this.height;
				imgWidth = this.width;
				if(imgHeight > 0 && imgWidth > 0){
					widthScale = containerWidth / imgWidth;
					heightScale = containerHeight / imgHeight;
				}
				if(widthScale >= heightScale){
					scale = heightScale;
				}else{
					scale = widthScale;
				}
				imgBoxHeight = Math.round(scale * imgHeight);
				imgBoxWidth = Math.round(scale * imgWidth);
				$("#bgDiv").width(imgBoxWidth);
				$("#bgDiv").height(imgBoxHeight);
				$("#bgDiv").css("margin-left",-imgBoxWidth / 2);
				$("#bgDiv").css("margin-top",-imgBoxHeight / 2);
				$("#bgDiv").css("display","block");

				var dragDivHtmlStr = ''+
										'<div id="dragDiv">'+
										  '<div id="rRightDown"> </div>'+
										  '<div id="rLeftDown"> </div>'+
										  '<div id="rRightUp"> </div>'+
										  '<div id="rLeftUp"> </div>'+
										  '<div id="rRight"> </div>'+
										  '<div id="rLeft"> </div>'+
										  '<div id="rUp"> </div>'+
										  '<div id="rDown"></div>'+
										'</div>';
				var dragDivObj = $(dragDivHtmlStr);
				$("#bgDiv").html("");
				$("#bgDiv").append(dragDivObj);
				//移除原有的img標籤
				$("#bgDiv").find("img").remove();
				$("#viewDiv").find("img").remove();
				ic = new ImgCropper("bgDiv", "dragDiv", url, {
					Width: imgBoxWidth, Height: imgBoxHeight , Color: "#FFF",
					Resize: true,
					Right: "rRight", Left: "rLeft", Up:	"rUp", Down: "rDown",
					RightDown: "rRightDown", LeftDown: "rLeftDown", RightUp: "rRightUp", LeftUp: "rLeftUp",
					Preview: "viewDiv", viewWidth: 160, viewHeight: 160
				});

			});

		}
		function showImgView(){
			$("#portraitLoad2").css("display","none");
			var url = backImage.url;
			var containerWidth = 400;
			var containerHeight = 300;
			var widthScale = 1.0 ,heightScale = 1.0;

			var imgBoxHeight = 0,imgBoxWidth = 0;
			//圖片的實際高寬
			var imgHeight = 0;
			var imgWidth = 0;
			//載入圖片高度寬度
			imgReady(url,function(){
				imgHeight = this.height;
				imgWidth = this.width;
				if(imgHeight > 0 && imgWidth > 0){
					widthScale = containerWidth / imgWidth;
					heightScale = containerHeight / imgHeight;
				}
				if(widthScale >= heightScale){
					scale = heightScale;
				}else{
					scale = widthScale;
				}
				imgBoxHeight = Math.round(scale * imgHeight);
				imgBoxWidth = Math.round(scale * imgWidth);
				$("#imgView").width(imgBoxWidth);
				$("#imgView").height(imgBoxHeight);
				$("#imgView").css("margin-left",-imgBoxWidth / 2);
				$("#imgView").css("margin-top",-imgBoxHeight / 2);
				$("#imgView").css("display","block");
				$("#imgView").html("");
				var img = $("<img src=''/>");
				img.attr("height",imgBoxHeight);
				img.attr("width",imgBoxWidth);
				img.attr("src",url);
				$("#imgView").append(img);
			});
		}
		function showPromptInfo(errno,msg){
			if(!msg){
				msg = msgObj[errno];
			}
			if(tabFlag == 0){
				$("#msg_content1").find("span").text(msg);
				$("#msg_content1").find("i").removeClass();
				$("#msg_content1").find("i").addClass("msg_icon");
				if(errno == msgObj.successErrno){
					$("#msg_content1").find("i").addClass("msg_icon_ok");
				}else if(errno == msgObj.errnoErrno){
					$("#msg_content1").find("i").addClass("msg_icon_warning");
				}else{
					$("#msg_content1").find("i").addClass("msg_icon_info");
				}
				$("#msg_content1").css("display","block");
				setTimeout("hiddenDiv('msg_content1')",1000);
			}else{
				$("#msg_content2").find("span").text(msg);
				$("#msg_content2").find("i").removeClass();
				$("#msg_content2").find("i").addClass("msg_icon");
				if(errno == msgObj.successErrno){
					$("#msg_content2").find("i").addClass("msg_icon_ok");
				}else if(errno == msgObj.errnoErrno){
					$("#msg_content2").find("i").addClass("msg_icon_warning");
				}else{
					$("#msg_content2").find("i").addClass("msg_icon_info");
				}
				$("#msg_content2").css("display","block");
				setTimeout("hiddenDiv('msg_content2')",1000);
			}
		}
		function hiddenDiv(divId){
			$("#"+divId).css("display","none");
		}
		//驗證圖片格式必須為jpg|jpeg|gif|png|bmp
		function validateImg (j) {
			h = j.value || '';
			if (/^.*?\.(jpg|jpeg|gif|png|bmp)$/.test(h.toLowerCase())) {
			  return true;
			} else {
			  showPromptInfo(msgObj.errnoErrno, msgObj.errImgMsg);
			  return false;
			}
		}
		//js程式碼
		$(document).ready(function(){
			//點選頁籤切換內容
			$(".tab_nav_li").click(function(){
				var contentId  = $(this).attr("cid");
				if($(this).attr("id") && $(this).attr("id").indexOf("1") != -1){
					tabFlag = 0 ;
				}else{
					tabFlag = 1;
				}
				$(".tab_content").css("display","none");
				$(".tab_nav_li").removeClass("tab_nav_cuur");
				$(this).addClass("tab_nav_cuur");
				$("#"+contentId).css("display","block");
			});
			$("#clip_ok").click(function(){
				if(!$(this).hasClass("okPortraitBtn_disable")){
					var clipWidth = 0 , clipHeight = 0;
					var clipTop = 0 , clipLeft = 0;
					if(ic){
						var posObj = ic.GetPos();
						clipTop = Math.round(posObj.Top / scale);
						clipLeft = Math.round(posObj.Left / scale);
						clipWidth = Math.round(posObj.Width / scale);
						clipHeight = Math.round(posObj.Height / scale);
						if(clipWidth < 1 || clipHeight < 1 ){
							showPromptInfo(2,"");
						}else{
							var picId = backImage.id;
							var clipSubmitData = {attachId:picId,x:clipLeft,y:clipTop,width:clipWidth,height:clipHeight};
							$.post(requestObj.clipAction, clipSubmitData, function(data){
								if(data){
									backImage.clipUrl = decodeURIComponent(decodeURIComponent(data.url));
									showPromptInfo(data.errno,"");
									$("#testImg").attr("src",backImage.clipUrl);
								}
							});
						}
					}else{
						showPromptInfo(5,"請先選擇需要剪下的圖片");
					}
				}
			});
			$("#upload_ok").click(function(){
				//判斷是否有
				if(!$(this).hasClass("okPortraitBtn_disable")){
					showPromptInfo(0,"圖片已儲存");
					$("#testImg").attr("src",backImage.clipUrl);
				}
			});
			$(".portraitLoad").css("display","none");
			$(".okPortraitBtn").addClass("okPortraitBtn_disable");
		});
	</script>
  </head>
  <body>
<div class="passPortraitWrapper">
	<div class="tab_wrap">
		<div class="tab_nav_group">
			<ul class="tab_nav_ul">
				<li  class="tab_nav_li tab_nav_cuur" id="tab_1" cid="clip_img">圖片剪下</li>
				<li  class="tab_nav_li" id="tab_2" cid="upload_img">圖片上傳</li>
			</ul>
		</div>
		<div class="tab_content_group">
			<div class="tab_content" style="display:block;" id="clip_img">
				<div  class="passPortraitBox">
						<div  class="passPortraitLeftSide">
							<div  class="selectPortaitLabel">
								<input type="file" name="file" id="fileImg" class="portraitFile"  onchange="uploadImg(this)"/>
								<input type="button"  class="portraitBtn selectPortraitBtn" id="file_btn1" value="選擇圖片" onclick=""/>
								<span  class="selectPortaitNote">支援jpg、jpeg、gif、png、bmp格式的圖片</span>
							</div>
							<div  id="imgPath" class="portraitFilePath"></div>
							<div  class="portraitBox">
								<div  class="portraitBG">
									<div id="portraitLoad1"  class="portraitLoad" >
										<img src="${ctxPath}/resources/images/loading/zoomloader.gif" height="16" width="16" />
									</div>
								  	<div style="display:none;" class="portraitPosition" id="bgDiv">
									</div>
								</div>
							</div>
							<div  class="okPortraitLabel" >
								<input type="button"   id="clip_ok" value="確定" class="portraitBtn okPortraitBtn okPortraitBtn_disable"/>
								<span class="msg_content" id="msg_content1" ><i class="msg_icon" ></i><span></span></span>
							</div>
						</div>
						<div  class="passPortraitRightSide">
							<div  class="portraitPreviewBox">
								<div class="portraitPreviewLabel">頭像預覽</div>
								<div  class="portraitPreviewContent" id="viewDiv"></div>
							</div>
						</div>
				</div>
			</div>
			<div class="tab_content" style="display:none;" id="upload_img">
				<div style="margin:0px auto;width:400px;padding:10px;">
					<div  class="selectPortaitLabel">
						<input type="file" name="file" id="fileImg2" class="portraitFile"  onchange="uploadImg(this)"/>
						<input type="button"  class="portraitBtn selectPortraitBtn" id="file_btn2" value="選擇圖片" onclick=""/>
						<span  class="selectPortaitNote">支援jpg、jpeg、gif、png、bmp格式的圖片</span>
					</div>
					<div class="imgViewBG" >
						<div id="portraitLoad2"  class="portraitLoad" >
								<img src="${ctxPath}/resources/images/loading/zoomloader.gif" height="16" width="16" />
						</div>
						<div id="imgView" style="display:none;position:absolute;z-index:200;background:#fff;left:50%;top:50%;"></div>
					</div>
					<div  class="okPortraitLabel">
							<input type="button"  value="確定" id="upload_ok"  class="portraitBtn okPortraitBtn okPortraitBtn_disable"/>
							<span class="msg_content" id="msg_content2" ><i class="msg_icon" ></i><span></span></span>
					</div>
				</div>
			</div>

		</div>
	</div>
		<div class="portraitParmDiv">

		</div>
	</div>
	<div style="clear:both;">
		<img src="" id="testImg" />
	</div>
	<script type="text/javascript">
/* 		var ic = new ImgCropper("bgDiv", "dragDiv", "http://images.cnblogs.com/cnblogs_com/cloudgamer/143727/r_xx2.jpg", {
			Width: 224, Height: 300, Color: "#000",
			Resize: true,
			Right: "rRight", Left: "rLeft", Up:	"rUp", Down: "rDown",
			RightDown: "rRightDown", LeftDown: "rLeftDown", RightUp: "rRightUp", LeftUp: "rLeftUp",
			Preview: "viewDiv", viewWidth: 160, viewHeight: 160
		}); */
	</script>
  </body>
</html>

3.由於上傳圖片成功後,頁面需要重新計算圖片的高寬,保證能放入400*300的div中,還是用一個計算圖片高寬的imgReady外掛,原始碼來至於網路

程式碼如下:

// 更新:
// 05.27: 1、保證回撥執行順序:error > ready > load;2、回撥函式this指向img本身
// 04-02: 1、增加圖片完全載入後的回撥 2、提高效能

/**
 * 圖片頭資料載入就緒事件 - 更快獲取圖片尺寸
 * @version 2011.05.27
 * @see     http://blog.phpdr.net/js-get-image-size.html
 * @param   {String}    圖片路徑
 * @param   {Function}  尺寸就緒
 * @param   {Function}  載入完畢 (可選)
 * @param   {Function}  載入錯誤 (可選)
 * @example imgReady('http://www.google.com.hk/intl/zh-CN/images/logo_cn.png', function () {
        alert('size ready: width=' + this.width + '; height=' + this.height);
    });
 */
var imgReady = (function () {
    var list = [], intervalId = null,

    // 用來執行佇列
    tick = function () {
        var i = 0;
        for (; i < list.length; i++) {
            list[i].end ? list.splice(i--, 1) : list[i]();
        };
        !list.length && stop();
    },

    // 停止所有定時器佇列
    stop = function () {
        clearInterval(intervalId);
        intervalId = null;
    };

    return function (url, ready, load, error) {
        var onready, width, height, newWidth, newHeight,
            img = new Image();

        img.src = url;

        // 如果圖片被快取,則直接返回快取資料
        if (img.complete) {
            ready.call(img);
            load && load.call(img);
            return;
        };

        width = img.width;
        height = img.height;

        // 載入錯誤後的事件
        img.onerror = function () {
            error && error.call(img);
            onready.end = true;
            img = img.onload = img.onerror = null;
        };

        // 圖片尺寸就緒
        onready = function () {
            newWidth = img.width;
            newHeight = img.height;
            if (newWidth !== width || newHeight !== height ||
                // 如果圖片已經在其他地方載入可使用面積檢測
                newWidth * newHeight > 1024
            ) {
                ready.call(img);
                onready.end = true;
            };
        };
        onready();

        // 完全載入完畢的事件
        img.onload = function () {
            // onload在定時器時間差範圍內可能比onready快
            // 這裡進行檢查並保證onready優先執行
            !onready.end && onready();

            load && load.call(img);

            // IE gif動畫會迴圈執行onload,置空onload即可
            img = img.onload = img.onerror = null;
        };

        // 加入佇列中定期執行
        if (!onready.end) {
            list.push(onready);
            // 無論何時只允許出現一個定時器,減少瀏覽器效能損耗
            if (intervalId === null) intervalId = setInterval(tick, 40);
        };
    };
})();

4.下面就是java服務端的servlet程式碼,服務端實現上傳使用commons-fileupload-1.2.2.jar,commons-io-2.0.1.jar

下面是servlet的程式碼:

package com.wqjweb.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import com.wqjweb.entry.Attachment;
import com.wqjweb.service.AttachmentService;
import com.wqjweb.util.date.DateUtil;
import com.wqjweb.util.file.FileUtil;
import com.wqjweb.util.image.ImgCutUtil;
import com.wqjweb.util.string.IDGenerator;
import com.wqjweb.util.string.StringUtil;
@Controller
public class UploadAttachController extends AutowiredHttpServlet {
	/**
	 *
	 */
	private static final long serialVersionUID = 1L;
	@Autowired
	private AttachmentService attachmentService;
	private ServletContext ctx;
	private String savePath;
	@Override
	public void init(ServletConfig config) throws ServletException {
		// 在web.xml中設定的一個初始化引數
		savePath = config.getInitParameter("savePath");
		ctx = config.getServletContext();
		super.init(config);
	}
	/**
	 * @return the attachmentService
	 */
	public AttachmentService getAttachmentService() {
		return attachmentService;
	}

	/**
	 * @param attachmentService the attachmentService to set
	 */
	public void setAttachmentService(AttachmentService attachmentService) {
		this.attachmentService = attachmentService;
	}

	@Override
	public void servlet(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		String action = StringUtil.trimStr(request.getParameter("action"));
		if("uploadAction".equals(action)){
			this.uploadAction(request, response);
		}else if("test".equals(action)){
			this.testResponse(request, response);
		}else if("uploadAttach".equals(action)){
			this.uploadAttach(request, response);
		}else if("getAttachFile".equals(action)){
			this.getAttachFile(request, response);
		}else if("getImageFile".equals(action)){
			this.getImageFile(request, response);
		}else if("testURLDecoder".equals(action)){
			this.testURLDecoder(request, response);
		}else if("clipImg".equals(action)){
			this.clipImg(request, response);
		}
	}

	private void uploadAction(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {

		DiskFileItemFactory factory = new DiskFileItemFactory();
		ServletFileUpload upload = new ServletFileUpload(factory);
		try{
			List<FileItem> fileItemList = upload.parseRequest(request);
			Iterator<FileItem> fileItemIter = fileItemList.iterator();
			while(fileItemIter.hasNext()){
				FileItem fileItem = fileItemIter.next();
				//判斷是否表單提交的引數
				if(fileItem.isFormField()){
					System.out.println("表單引數名:"+fileItem.getFieldName()+"屬性值:"+fileItem.getString("utf-8"));
				}else{
					if(!"".equals(fileItem.getName())){
						System.out.println("檔案大小:"+fileItem.getSize());
						System.out.println("檔案型別:"+fileItem.getContentType());
						System.out.println("檔名稱:"+fileItem.getName());
						String rootPath = ctx.getRealPath("/");
						System.out.println("專案根目錄:"+rootPath);
						File tempFile = new File(rootPath+savePath,fileItem.getName());
						//判斷父目錄是否存在,不存在就建立
						mkdir(tempFile.getParentFile());
						fileItem.write(tempFile);
						request.setAttribute("uploadMsg", "上傳檔案成功!");
						System.out.println("上傳成功!");
					}else{
						request.setAttribute("uploadMsg", "沒有選擇上傳檔案!");
						System.out.println("沒有選擇上傳檔案!");
					}
				}
			}
		}catch(Exception e){
			e.printStackTrace();
			request.setAttribute("uploadMsg", "上傳檔案失敗!");
		}
		Attachment attachment = new Attachment();
		attachment.setAttachName("測試2");
		attachment.setAttachPath("F:\\CC.txt");
		attachment.setAttachSize(20);
		attachment.setAttachSuffix("txt");
		attachment.setCreateDate(DateUtil.getCurrDateStr());
		attachment.setId(IDGenerator.getUniqueID());
		attachment.setUserId(IDGenerator.getUniqueID());
		int count = attachmentService.save(attachment);
		System.out.println("path:"+savePath);
		System.out.println("count:"+count);
		JSONObject jsonObj = new JSONObject();
		jsonObj.put("code", "100");
		jsonObj.put("msg", "上傳成功!");
		System.out.println(jsonObj.toString());
		response.getWriter().write(jsonObj.toString());
	}
	private void testURLDecoder(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		String testStr = StringUtil.trimStr(request.getParameter("testStr"));
		System.out.println(testStr);
		System.out.println(new String(testStr.getBytes("ISO8859_1"),"UTF-8"));
		System.out.println(URLDecoder.decode(testStr, "ISO8859_1"));
		System.out.println(URLDecoder.decode(testStr, "UTF-8"));
	}
	private void uploadAttach(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		DiskFileItemFactory factory = new DiskFileItemFactory();
		ServletFileUpload upload = new ServletFileUpload(factory);
		JSONObject resultJson = new JSONObject();

		try{
			List<FileItem> fileItemList = upload.parseRequest(request);
			Iterator<FileItem> fileItemIter = fileItemList.iterator();
			while(fileItemIter.hasNext()){
				FileItem fileItem = fileItemIter.next();
				//判斷是否表單提交的引數
				if(fileItem.isFormField()){
					System.out.println("表單引數名:"+fileItem.getFieldName()+"屬性值:"+fileItem.getString("utf-8"));
				}else{
					if(!"".equals(fileItem.getName())){
						System.out.println("檔案大小:"+fileItem.getSize());
						System.out.println("檔案型別:"+fileItem.getContentType());
						System.out.println("檔名稱:"+fileItem.getName());
						//表單上傳的文件名稱
						String pathName = fileItem.getName();
						String fileFullName = FileUtil.getFileFullName(pathName);
						String fileSimpleName = fileFullName;
						if(!"".equals(FileUtil.getFileSimpleName(fileFullName))){
							fileSimpleName = FileUtil.getFileSimpleName(fileFullName);
						}
						String rootPath = ctx.getRealPath("/");
						String filePath = rootPath+savePath + File.separator + fileFullName;
						System.out.println("檔案路徑:"+filePath);
						File tempFile = new File(filePath);
						Attachment attachment = new Attachment();
						attachment.setId(IDGenerator.getUniqueID());
						attachment.setAttachName(fileSimpleName);
						attachment.setAttachSuffix(FileUtil.getFileSuffix(fileFullName));
						attachment.setAttachPath(filePath);
						attachment.setCreateDate(DateUtil.getCurrDateStr());
						attachment.setUserId("10000");
						attachment.setAttachSize((int)fileItem.getSize());
						//判斷父目錄是否存在,不存在就建立
						mkdir(tempFile.getParentFile());
						fileItem.write(tempFile);
						int resultCount = this.attachmentService.save(attachment);
						if(resultCount > 0 ){
							resultJson.put("errno", "0");
							String portraitUrl  = request.getContextPath()+"/uploadController?action=getImageFile&attachId="+attachment.getId();
							try{
								portraitUrl = URLEncoder.encode(portraitUrl,"UTF-8");
							}catch(Exception e2){}
							resultJson.put("picId", attachment.getId());
							resultJson.put("portraitUrl", portraitUrl);

						}else{
							resultJson.put("errno", "5");
						}
					}
				}
			}
		}catch(Exception e){
			e.printStackTrace();
			resultJson.put("errno", "4");

		}
		System.out.println(resultJson.toString());
		renderHtml(response, resultJson.toString());
	}
	private void uploadAttachToJpg(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		DiskFileItemFactory factory = new DiskFileItemFactory();
		ServletFileUpload upload = new ServletFileUpload(factory);
		JSONObject resultJson = new JSONObject();

		try{
			List<FileItem> fileItemList = upload.parseRequest(request);
			Iterator<FileItem> fileItemIter = fileItemList.iterator();
			while(fileItemIter.hasNext()){
				FileItem fileItem = fileItemIter.next();
				//判斷是否表單提交的引數
				if(fileItem.isFormField()){
					System.out.println("