Jcrop 整合 FileAPI 圖像裁剪上傳

Jcrop是一款優秀的jQuery插件,能夠很是方便地實現圖像裁剪,並且功能十分的強大。javascript

通常的狀況下,圖像裁剪的實現要通過兩次圖像上傳,第一次將圖片上傳到後臺,後臺返回一個連接,經過這個連接在本地實現預覽。第二次將圖片自己以及裁剪參數上傳到後臺,後臺進行裁剪,並保存在服務器。也就是說第一次的上傳是沒必要要的,用戶萬一中途取消了操做,那第一次的操做就徹底成了無用操做。並且增長了網絡的消耗,形成了沒必要要的浪費。通常這種狀況下,咱們會考慮第二次不進行上傳而使用第一次上傳的圖片,但這增長了技術難度,並且形成了更多的Exceptions的可能。事實css

上有更好的選擇,那就是FileAPI,它不進行上傳,圖片的預覽是經過將圖片加載到本地瀏覽器緩存實現的。咱們經過FileAPI獲取必要的參數,在用戶「下定決心」使用該圖的時候再進行上傳,能夠極大的下降多餘消耗,加強用戶體驗。html

要實現圖像裁剪上傳,首先要實現圖像本地預覽的功能。定義一個priviewImage.js文件,方便複用:html5

function previewImage(file, callback) {
	/*
	 * file:file控件 prvid: 圖片預覽容器
	 */
	/*if (file[0].fileSize() > 3 * FileAPI.MB) {
		alert("The uploading file size must less than 3MB!");
		return;
	}*/
	var tip = "Expect jpg or png or gif!"; // 設定提示信息
	var filters = {
		"jpeg" : "/9j/4",
		"gif" : "R0lGOD",
		"png" : "iVBORw"
	}
	if (window.FileReader) { // html5方案
		for (var i = 0, f; f = file.files[i]; i++) {
			var fr = new FileReader();
			fr.onload = function(e) {
				var src = e.target.result;
				if (!validateImg(src)) {
					alert(tip);
				} else {
					showPrvImg(src);
				}
			}
			fr.readAsDataURL(f);
		}
	} else { // 降級處理
		if (!/\.jpg$|\.png$|\.gif$/i.test(file.value)) {
			alert(tip);
		} else {
			showPrvImg(file.value);
		}
	}

	function validateImg(data) {
		var pos = data.indexOf(",") + 1;
		for ( var e in filters) {
			if (data.indexOf(filters[e]) === pos) {
				return e;
			}
		}
		return null;
	}

	function showPrvImg(src) {
		callback(src);
	}
}

經過callback能夠拿到字節碼形式的圖片,將其設爲img標籤的src屬性,瀏覽器便可以顯示出來。如下是一個例子:java

<div>
	<p>預覽:</p>
	<div id="previewBox">
		<img src="" id="previewImage" alt="預覽頭像">
	</div>
</div>
previewImage(file, function(src) {
				$("#previewImage").attr("src", src);}

如今來描述下Jcrop圖像裁剪上傳的基本流程:jquery

第一步:用戶點擊fileinput,選擇本地圖片,並經過FileAPI將該文件加載到瀏覽器緩存,最後造成網頁上的本地預覽圖片;ajax

第二步:Jcrop針對預覽圖片進行初始化,關於初始化的具體方法,我會在後面說到。這裏有一個難題,事實上解決方案是一個選擇器的問題,後面詳細說明,關於Jcrop的詳細使用方法,能夠自行百度,網上有不少的相關介紹;json

第三步:經過Jcrop將用戶的裁剪數據捕捉到hiddeninput中,這個即是Jcrop的核心,因此不須要咱們作過多的考慮;瀏覽器

第四步:用戶決定是應用操做仍是放棄操做。若放棄,則將DOM重置,若應用,則用ajaxFileUpload上傳圖片。緩存

如今來詳細說明各步驟的實現:

首先是文件的加載,須要的依賴有jQuery.js,Jcrop.js,ajaxFileUpload.js以及咱們先前定義的previewImage.js:

<link rel="stylesheet" href="css/jquery.Jcrop.min.css" type="text/css">
<script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="js/jquery.Jcrop.min.js"></script>
<script type="text/javascript" src="js/previewImage.js"></script>
<script type="text/javascript" src="js/ajaxfileupload.js"></script>

基本的DOM模型:

<div>
	<input id="myImage" name="myImage" type="file" onchange="initImgForm(this)">
	<button  type="button" id="resetImgBtn">取消選擇</button>		
	<button type="button" id="imgBtn">確認修改</button>
	<input type="hidden" id="offsetX" name="offsetX" value="0">
	<input type="hidden" id="offsetY" name="offsetY" value="0">
	<input type="hidden" id="width" name="width" value="120">
	<input type="hidden" id="height" name="height" value="120">
</div>

說到這裏,我多嘴一句,button元素在使用的時候最好指定一下type="button",由於它在和form元素組合使用的時候,若不指定屬性,在某些瀏覽器中會觸發form的submit事件,形成一些沒必要要的錯誤。DOM還有一部分,預覽窗格:

<div>
	<p>預覽:</p>
	<div id="previewBox">
		<img src="" id="previewImage" alt="預覽頭像">
	</div>
</div>

當用戶點擊fileinput的時候,將會調用initImgForm方法,完成圖片預覽以及Jcrop的初始化。Jcrop出事化的關鍵在於$.children()方法,直接針對父元素"#previewImage"會出現錯誤,同時也不可對其子元素<img>調用$.Jcrop方法,也會出現錯誤。

<script type="text/javascript">
		var JcropApi, boundx, boundy;

		function initImgForm(file) {
			/* 驗證文件大小還未實現,服務器端最大Size 3MB,參閱 previewImage.js*/
			previewImage(file, function(src) {
				$("#previewImage").attr("src", src);
				$("#previewBox").children().Jcrop({
					onChange : showPreview,
					onSelect : showPreview,
					minSize : [ 120, 120 ],
					maxSize : [ 400, 400 ],
					aspectRatio : 1
				}, function() {
					var bounds = this.getBounds();
					boundx = bounds[0];
					boundy = bounds[1];
					JcropApi = this;
				});
			});

		}

		function showPreview(c) {
			var w = $("#previewImage").width();
			var h = $("#previewImage").height();
			var rx = w / c.w;
			var ry = h / c.h;

			$("#previewImage").css({
				width : Math.round(rx * w) + "px",
				height : Math.round(ry * h) + "px",
				marginLeft : "-" + Math.round(rx * c.x) + "px",
				matginTop : "-" + Math.round(ry * c.y) + "py"
			});

			$("#offsetX").val(c.x);
			$("#offsetY").val(c.y);
			$("#width").val(c.w);
			$("#height").val(c.h);
		}


		$("#resetImgBtn").on("click", function() {
			resetImg();
		});

		$("#imgBtn").on("click", function() {
			var params = {};
			params.offsetX = $("#offsetX").val();
			params.offsetY = $("#offsetY").val();
			params.width = $("#width").val();
			params.height = $("#height").val();

			$.ajaxFileUpload({
				url : "...",//定義你的上傳路徑
				secureurl : false,
				fileElementId : "myImage",
				data : params,
				dataType : "json",
				success : function(json) {
					if (json.status) {
						$("#currentImage").attr("src", json.imgsrc);
						resetImg();
						alert(json.message);
					} else {
						alert(json.message);
					}
				},
				error : function() {
					alert("請求失敗");
				}
			});
		});

		function resetImg() {
			$("#previewBox").empty();
			var img = "<img id=\"previewImage\" src=\"\" alt=\"預覽頭像\">";
			$("#previewBox").append(img);
			$("#myImage").val("");
			JcropApi.destroy();
		}
	</script>
相關文章
相關標籤/搜索