2014-05-13 17:23:47  浏览:2401

jQuery Jcrop Ajax 上传 裁剪图片

jQuery仿QQ Ajax上传文件+Jcrop照片剪裁插件,如果浏览器支持html5,会有一个上传进度条。

本文只提供前端代码,图片处理代码,自行百度。

第一步、页面引入必要的css和js(文件在本文最后,提供下载地址,供学习使用

<link rel="stylesheet" type="text/css" href="css/open_platform.css" />
<link rel="stylesheet" type="text/css" href="css/open_qq_agreement.css" />
<link rel="stylesheet" type="text/css" href="css/confirm_by_dialog.css" />
<link rel="stylesheet" type="text/css" href="css/smoothness/jquery-ui-1.9.0.custom.min.css" />
<script type="text/javascript"  src="js/jquery.js"></script>
<script type="text/javascript"  src="js/jquery-ui-1.9.0.custom.min.js"></script>
<script type="text/javascript"  src="js/qzfl_for_qzone.js"></script>
<script type="text/javascript"  src="js/open_v2.js"></script>
<script type="text/javascript"  src="js/fileupload.js"></script>

第二步、写html代码,一个上传按钮和一个预览图


<div class="div_btn img_upload_panel">
					<input type="hidden" name="face_path" value="" />
					<p class="pic" >
						<img src="image/default_100.jpg" id="icon_img" />
					</p>
					<div class="clear"></div> 
        		<br />
        		<p><input type="button" value="上传图片" class="file_icon_upload_btn"/></p>
        		<br />
        		</div>
第三步、给上传按钮绑定上传事件



<script type="text/javascript" >
$(document).ready(function(){
	//图标上传
	$(".file_icon_upload_btn").click(function(){
	    var post_url ="uploadify.json?type=icon",
	    desc="选择一个255x255,大小1MB以内,png/jpg 格式的图片",
	    pf_id=1,_flag="255_255",_size=1024*1024;
	    var _this=$(this);
		  OP_COMMON.upload.showUpload(post_url, 
		            function(ret) {
			  		//上传回调函数//
			  		$("#icon_img").attr("src",ret.filePath);
		            $(_this).val("更改");
		            },
		            desc, _size, false,_flag, {
		                customContent: '<input type="hidden" name="pf" value="' + pf_id + '" />'
		            });
	});
});
</script>






示例截图

文件上传核心js

fileupload.js


OP_COMMON = {
    url: {
        default_img: ""
    },
    dialog_msg: function(msg) {
        parent.QZFL.dialog.create('提示', '<p style="padding:40px 20px 0; line-height:1.8em;">' + msg + '</p>', {
            width: 300,
            height: 120,
            showMask: true
        });
    },
    OP_TIPS: {
        icon_16: {
            title: "应用小图标",
            info: [{
                desc: "16×16应用图标会出现在平台应用列表。以空间为例。平台应用中心的各类应用排行榜:",
                img: ""
            }]
        },
        icon_100: {
            title: "应用大图标",
            left: -50,
            info: [{
                desc: "100×100应用图标会出现在平台推广类Feeds中,以空间平台为例:",
                img: ""
            },
            {
                img: ""
            }]
        }
    },
    util: {
        reg_exps: {
            email: /^[0-9A-Za-z-\_.]+@[0-9A-Za-z-\_]+(.[0-9A-Za-z-\_]+)+$/,
            url: /^http(s)*://[w-]+(.[w-]+)+(:d+)?(/[w.%-]+)*/?$/i,
            url_parm_hash: /^http(s)*://[w-]+(.[w-]+)+(:d+)?(/[?#/-_.!~*'()w%&=]*$)?/i,
            phone: /^([0-9]+-)*[0-9]+$/,
            mobile_phone: /^1d{10}$/,
            uin: /^[1-9][0-9]{4,9}$/,
            common: /^[0-9a-zA-Zu4E00-u9FA5uF900-uFA2D]+$/,
            company_idcard: /^[0-9]{10,20}$/,
            person_idcard: /^[0-9xX]{18}$/,
            passport: /^[0-9a-zA-Z]+$/,
            lazy: /^[^<>'"]+$/,
            human_name: /^[a-zA-Zu4E00-u9FA5uF900-uFA2D][a-zA-Zu4E00-u9FA5uF900-uFA2Ds]*$/,
            human_name_cn_no_nec: /^([u4E00-u9FA5]{2,5}|.{0,0})$/,
            sensetive: /^[^'"<>]+$/,
            num: /(^[1-9][0-9]*$)|(^0$)/,
            num_positive: /^[1-9][0-9]*$/
        },
        showMask: function(zIndex, win) {
            var ind = arguments.callee.ind || 1000,
            zIndex = zIndex || 100,
            style,
            width,
            height;
            win = win || top;
            arguments.callee.ind = ++ind;
            width = Math.max(win.QZFL.dom.getClientWidth(), win.QZFL.dom.getScrollWidth());
            height = Math.max(win.QZFL.dom.getClientHeight(), win.QZFL.dom.getScrollHeight());
            style = 'position:absolute;left:0;top:0;background-color:#000;width:' + width + 'px;height:' + height + 'px;z-index:' + zIndex + ';visibility:hidden;';
            var el = win.QZFL.dom.createElementIn("div", win.document.body, false, {
                id: "op_mask_" + ind,
                style: style,
                "class": "op_mask"
            });
            win.$e(el).setStyle({
                "opacity": 0.4,
                "visibility": "visible"
            });
            return ind;
        },
        hideMask: function(ind, win) {
            win = win || top;
            win.document.body.removeChild(win.document.getElementById("op_mask_" + ind));
        },
        validate_tip: function(el, type, msg) {
            var $tip = $e('.j_open_validate_tip', el.parentNode.parentNode);
            if ("error" == type) {
                $tip.addClass("form_panel_msg_advise").setHtml('<b class="form_tips nopass"><i class="ico ico_tips"></i>' + (msg ? msg: '') + '</b>').setStyle("display", "block");
            } else if ("succ" == type) {
                $tip.removeClass("form_panel_msg_advise").setHtml('<b class="form_tips pass"><i class="ico ico_tips"></i>' + (msg ? msg: '') + '</b>').setStyle("display", "block");
            } else {
                $tip.removeClass("form_panel_msg_advise").setHtml('<i class="ico ico_tips"></i>' + (msg ? msg: '')).setStyle("display", "block");
            }
        },
        water_mark: {
            show: function(el, msg) {
                if (!QZFL.string.trim(el.value)) {
                    el.value = msg || el.getAttribute("water_mark");
                    el.style.color = "#999";
                    el._ever_focused = false;
                } else {
                    el._ever_focused = true;
                }
            },
            hide: function(el) {
                el.value = "";
                el.style.color = "#000";
            }
        },
        set_value: function(el, val) {
            el.value = val;
            el.style.color = "#000";
            el._ever_focused = true;
        },
        form_validate: function(fn_suc) {
            var _this = this;
            var _validate = function(onblur) {
                var input = this,
                val = this.value;
                val = val.replace(/s+$/, "");
                if (! (_this.reg_exps[this.getAttribute("validate")] && _this.reg_exps[this.getAttribute("validate")].test(val))) {
                    if (0 == QZFL.string.trim(val).length) {
                        if (onblur) {
                            _this.water_mark.show(this);
                        } else {
                            _this.validate_tip(this, "error", "该项不能为空");
                        }
                    } else {
                        _this.validate_tip(this, "error", this.getAttribute("validate_tip"));
                    }
                    return false;
                } else {
                    if ("function" == typeof fn_suc) {
                        if (false === fn_suc(_this, input, onblur)) {
                            return false;
                        }
                    } else {
                        _this.validate_tip(this, "succ");
                    }
                    return true;
                }
            };
            QZFL.each(document.forms, 
            function(f) {
                f._validate = function() {
                    var ret = true;
                    $e('[validate]', this).each(function() {
                        if (!this._ever_focused) {
                            this.value = "";
                        }
                        if (!this.disabled && !_validate.call(this)) {
                            ret = false;
                        }
                    });
                    return ret;
                }
                f = null;
            });
            $e('[validate]').each(function() {
                this.onfocus = function() { ! this._ever_focused && _this.water_mark.hide(this);
                    this._ever_focused = true;
                    _this.validate_tip(this, "hide");
                }
                this.onblur = function() {
                    _validate.call(this, true);
                }
            });
        },
        getStrLen: function(str) {
            return Math.ceil(str.replace(/[^x00-xff]/g, 'TS').length / 2);
        }
    },
    upload: {
        _uploadIframe: null,
        _dialog: null,
        apc_upload_id:null,
        post_url:null,
        dimension:"",
        isprocessing:false,
        showUpload: function(post_url, suc_fn, desc, type_param, no_size,dimension, opt) {
            if (this._dialog) {
                return;
            }
            //document.domain='mofing.com';
            OP_COMMON.upload.dimension=dimension;
            OP_COMMON.upload.post_url=post_url;
            if(post_url.indexOf("?")!=-1){
            	post_url=post_url+"&act=frame";
            }else{
            	post_url=post_url+"?act=frame";
            }
            var name = "文件";
            if (this._uploadIframe == null) {
                var iframe = $('#__FormTargetFrame');
                if (iframe.length==0) {
                    iframe = document.createElement('iframe');
                    iframe.border = iframe.width = iframe.height = 0;
                    iframe.id = '__FormTargetFrame';
                    iframe.name = '__FormTargetFrame';
                    document.body.appendChild(iframe);
                    if (window.frames) {
                        window.frames['__FormTargetFrame'].name = '__FormTargetFrame';
                    }
                }
                this._uploadIframe = iframe;
            }
            this._uploadIframe.callback = function(ret) {
                var _d = null;
            	OP_COMMON.upload.isprocessing=false;
                QZFL.widget.msgbox.hide();
                $( "#upload_file_process" ).hide();
                if (0 == ret.error || true == ret.result) {
                    OP_COMMON.upload.closeUpload();
                    QZFL.widget.msgbox.show(ret.message || "上传成功",4, 2000);
                    suc_fn && suc_fn(ret);
                } else {
                    var op_mask_ind = OP_COMMON.util.showMask(6500);
                    var crop=[];
                    var buttonConfigs=[{
                        type: QZFL.dialog.BUTTON_TYPE.Normal,
                        text: '重新上传',
                        tips: '重新上传',
                        clickFn: function() {
                            _d.unload();
                            _d = null;
                        }
                    },
                    {
                        type: QZFL.dialog.BUTTON_TYPE.Cancel,
                        text: '取消',
                        tips: '取消',
                        clickFn: function() {
                            OP_COMMON.upload.closeUpload();
                            _d = null;
                        }
                    }];
                    //固定尺寸的图片,才允许切割
                    if(ret.error==7 && OP_COMMON.upload.dimension != ""){
                    	QZFL.css.insertCSSLink("./css/jquery.Jcrop.css");
                    	ret.message+="或者裁剪图片";
	                    crop={
	                       	 type: QZFL.dialog.BUTTON_TYPE.Cancel,
	                         text: '裁剪图片',
	                         tips: '裁剪图片',
	                         clickFn: function() {
	                             _d.cropImage(ret.filePath);
	                         }
	                    };
	                    buttonConfigs.unshift(crop);
                    }
                    _d = parent.QZFL.dialog.create("提示", '<p style="padding:30px 25px 0; line-height:22px; color:#f30;">上传失败:' + ret.message + '</p>', {
                        showMask: false,
                        'width': 320,
                        'height': 100,
                        buttonConfig:buttonConfigs
                    });
                    _d.cropImage=function(url){
                    	//打开裁剪窗口
                    	 OP_COMMON.upload.cropImage(url);
                    	_d = null;
                    };
                    _d.onUnload = function() {
                        OP_COMMON.util.hideMask(op_mask_ind);
                    };
                }
            };
            var timestamp=new Date().getTime();
            OP_COMMON.upload.apc_upload_id=V.util.getToken()+"_"+timestamp;
            var html = ['<div style="text-align:left; padding-top:37px;">',
                        '<form method="post" action="' + post_url + '" enctype="multipart/form-data" target="__FormTargetFrame" id="formUpload">',
                        (no_size ? '': '<input type="hidden" name="imagesize" value="' + type_param+ '"/>'),  
                        '<input type="hidden" name="dimension" value="',  dimension, '" />', 
                        '<input type="hidden" name="g_tk" value="', V.util.getToken(), '" />', 
                        ' <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" id="progress_key"  value="'+OP_COMMON.upload.apc_upload_id+'"/>',
                        '<input type="hidden" name="token" value="', V.util.getToken(), '" />',
                        '<input type="hidden" name="appid" value="', parseInt(V.util.getUrlParam("appid")), '" />',
                        (opt && opt.customContent) || '', 
                        '<div id="divUploadForm" style="height:100px;">',
                        '<div style="padding:0px 35px;">',
                        '<div id="upload_file_process"><div class="progress-label">Loading...</div></div>', '<p style="color:#000;">' + desc + '</p>', 
                        '<input name="file" type="file" style="width:300px;padding:4px 0;margin-top:18px;background-color:#fff;" id="formUploadFile"/>', 
                        '</div>', '</div>', '<div class="layer_opensns_confirm_bt">', 
                        '<button type="submit" onclick="return (window.frames[0].OP_COMMON || OP_COMMON).upload.startProgress();" >确定</button>', 
                        '<button type="button" onclick="(window.frames[0].OP_COMMON || OP_COMMON).upload.closeUpload(); ">取消</button>',
                        '</div>', '</form>', '</div>'].join('');
            var win = QZFL.userAgent.ie == 6 ? window: parent;
            var dialog = win.QZFL.dialog.create('上传' + name, html, 400, 174);
            var maskID = win.QZFL.maskLayout.create();
            dialog.onUnload = QZFL.object.bind(this, 
            function() {
                win.QZFL.maskLayout.remove(maskID);
                this._dialog = null;
            });
            this._dialog = dialog;
        },
        closeUpload: function() {
            this._dialog && this._dialog.unload();
        },
        cropImage:function(url_obj){
        	$.getScript("./js/jquery.Jcrop.js",function(){
        		url="./"+url_obj;
        		var i_width, i_height;
        		$("<img/>") // 在内存中创建一个img标记
			    .attr("src", url)
			    .load(function() {
			    	i_width = this.width;
			        i_height = this.height;
					var w2=500;
					var h2=500;
					
					if(OP_COMMON.upload.dimension=="" || i_width<s_width || i_height<s_height){
						QZFL.widget.msgbox.show("图片太小或者尺寸不规则,无法裁剪!",3, 2000);
						//alert("");
						return false;
					}
					var size_arr = OP_COMMON.upload.dimension.split("_");
					var s_width=size_arr[0];
					var s_height=size_arr[1];
					
					if(i_width>i_height){
						 h2=w2*i_height/i_width;
					}else{
						w2=h2/i_height*i_width;
					}
	        		var html='<div class="crop_main" id="id_crop_main" style="padding-left: 20px;"><img id="image_crop_panel" src="'+url+'" style="width:'+w2+'px;height:'+h2+'px"/><span id="crop_preview_box" class="crop_preview"><img id="crop_preview" src="'+url+'" /></span></div>';
	        		var win = QZFL.userAgent.ie == 6 ? window: parent;
	        		var cropdialog = win.QZFL.dialog.create('裁剪图片' , html,  {
	                    showMask: false,
	                    'width': w2+200,
	                    'height':h2+20,
	                    buttonConfig: [{
	                        type: QZFL.dialog.BUTTON_TYPE.Normal,
	                        text: '保存图片',
	                        tips: '保存图片',
	                        clickFn: function() {
	                            //提交裁剪
	                        	 QZFL.widget.msgbox.show("正在努力裁剪中...", 6, 10*1024*1024);
	                        	$("#crop_form").submit();	
	                        	setTimeout(function(){cropdialog.unload();},500);
	                        }
	                    }, {
	                        type: QZFL.dialog.BUTTON_TYPE.Cancel,
	                        text: '取消',
	                        tips: '取消',
	                        clickFn: function() {
	                            OP_COMMON.upload.closeUpload();
	                            _d = null;
	                        }
	                    }]});
	        		//增加表单
	        		$("#id_crop_main").append('<div style="display:none;"><form action="cropimage.html" method="post" target="__FormTargetFrame" id="crop_form">'+
	        				'<input type="hidden" name="filepath" value="'+url_obj+'"/>'+
	        				'<input type="hidden" name="s_width" value="'+w2+'"/>'+
	        				'<input type="hidden" name="s_height" value="'+h2+'"/>'+
	        				'<input type="hidden" id="x" name="x" value="0"/><input type="hidden" id="y" name="y"  value="0"/>'+
	        				'<input type="hidden" id="w" name="w"  value="'+s_width+'"/><input type="hidden" id="h" name="h"  value="'+s_height+'"/> <input type="sumbit" value="确认剪裁" id="crop_submit" /></form></div>');
	        		 $("#image_crop_panel").Jcrop({
	        			onChange:OP_COMMON.upload.showPreview,
	        			onSelect:OP_COMMON.upload.showPreview,
	        			aspectRatio:1,
	        			allowSelect:!1,
	        			setSelect: [0,s_width,s_height,0]
	        		});	
			    }) ;
    		});
        },
         showPreview:function(coords){
			if(parseInt(coords.w) > 0){
				$("#id_crop_main #x").val(coords.x);
				$("#id_crop_main #y").val(coords.y);
				$("#id_crop_main #w").val(coords.w);
				$("#id_crop_main #h").val(coords.h);
				//计算预览区域图片缩放的比例,通过计算显示区域的宽度(与高度)与剪裁的宽度(与高度)之比得到
				var rx = $("#crop_preview_box").width() / coords.w; 
				var ry = $("#crop_preview_box").height() / coords.h;
				//通过比例值控制图片的样式与显示
				$("#crop_preview").css({
					width:Math.round(rx * $("#image_crop_panel").width()) + "px",	//预览图片宽度为计算比例值与原图片宽度的乘积
					height:Math.round(rx * $("#image_crop_panel").height()) + "px",	//预览图片高度为计算比例值与原图片高度的乘积
					marginLeft:"-" + Math.round(rx * coords.x) + "px",
					marginTop:"-" + Math.round(ry * coords.y) + "px"
				});
			}
		},
        startProgress:function(){
        	//检查是否选择了文件
        	var ff = $("form#formUpload #formUploadFile").val();
        	if(!ff){
        		QZFL.widget.msgbox.show("请选择文件!",3, 2000);
        		return false;
        	}
        	if(OP_COMMON.upload.isprocessing){
        		return false;
        	}
        	OP_COMMON.upload.isprocessing=true;
        	//如果支持html5,则显示进度条,否则直接进入表单
        	var isallow=OP_COMMON.uploadprogress.allowbrowser();
        	 if(isallow){
        		 OP_COMMON.uploadprogress.xmlHttp=OP_COMMON.uploadprogress.createXHR();
        		 $( "#upload_file_process" ).show();
        		 setTimeout(function(){
        			 OP_COMMON.uploadprogress.progress();
        		 }, 1000);
        		 $( "#upload_file_process" ).progressbar({
        			 value: false,
        			 change: function() {
        				 $(".progress-label" ).text( $(this).progressbar( "value" ) + "%" );
        			 }
        		 });
        		 $(".progress-label" ).show();
        		 return false;
        	 }else{
        		 //打开loading
        		 QZFL.widget.msgbox.show("正在努力上传...", 6, 10*1024*1024);
        		 return true;
        	 }
        }
    },
    init: function(data) {
        if (data.tips) {
            QZFL.each(data.tips, 
            function() {
                var t = this;
                QZFL.dom.createElementIn("div", $('j_top_caution'), false, {
                    "class": 0 == t.type ? "fn_hint": "fn_hint fn_hint_success",
                    "innerHTML": '<i class="' + (0 == t.type ? 'ico ico_hint_advise': 'ico ico_hint_success') + '"></i> <p>' + t.content + '</p>'
                });
            });
        }
    },
    uploadprogress:{
        xmlHttp:null,
        allowbrowser:function(){
        	var bro={
	        	"msie":10,
	        	"safari":5.02,
	        	"mozilla":4,
	        	"webkit":6
        	};
        	var version=parseFloat($.browser.version);
        	if ($.browser.safari) {
        		 return version>=bro.safari;
        	}else if($.browser.msie){
        		return version>=bro.msie;
        	}else if($.browser.mozilla){
        		return version>=bro.mozilla;
        	}else if($.browser.webkit){
        		return version>=bro.webkit;
        	}
        	return false;
        },
        Try : {
        		  these: function() {
        		    var returnValue;
        		    for (var i = 0; i < arguments.length; i++) {
        		      var lambda = arguments[i];
        		      try {
        		        returnValue = lambda();
        		        break;
        		      } catch (e) {}
        		    }
        		    return returnValue;
        		  }
        		},
    	createXHR:function(){
    		return OP_COMMON.uploadprogress.Try.these(
    				function() {return new XMLHttpRequest();}
    		) || false;
    	},
    	progress:function(id){
    		var xmlHttp=OP_COMMON.uploadprogress.xmlHttp;
    		var fd = new FormData();
    		//formUpload
    		fd.append("file", document.getElementById('formUploadFile').files[0]);
    		fd.append("g_tk", document.getElementsByName('g_tk')[0].value);
    		fd.append("token", document.getElementsByName('token')[0].value);
    		fd.append("imagesize", document.getElementsByName('imagesize')[0].value);
    		fd.append("dimension", document.getElementsByName('dimension')[0].value);
    		xmlHttp.upload.addEventListener("progress", OP_COMMON.uploadprogress.listeners.uploadProgress, false);
    		xmlHttp.addEventListener("load", OP_COMMON.uploadprogress.listeners.uploadComplete, false);
    		xmlHttp.addEventListener("error", OP_COMMON.uploadprogress.listeners.uploadFailed, false);
    		xmlHttp.addEventListener("abort", OP_COMMON.uploadprogress.listeners.uploadCanceled, false);
    		xmlHttp.open("POST",OP_COMMON.upload.post_url);
    		xmlHttp.send(fd);   
    	},
    	listeners:{
    		uploadProgress:function(evt){
    			  if (evt.lengthComputable) {
    		          var percentComplete = Math.round(evt.loaded * 100 / evt.total);
    		          $( "#upload_file_process" ).progressbar("value",percentComplete);
    		      }
    		},
    		uploadComplete:function(evt){
    			//直接调用表单回调函数
    			//json转换
    			var result= jQuery.parseJSON(evt.target.responseText);
    			OP_COMMON.upload._uploadIframe.callback(result);
    			 //alert(evt.target.responseText);
    		},
    		uploadFailed:function(evt){
    			//alert("There was an error attempting to upload the file.");
    		},
    		uploadCanceled:function(evt){
    			//alert("The upload has been canceled by the user or the browser dropped the connection.");
    		}
    	}
    },
    bind_events: function() {
        QZFL.event.delegate(document.body, '[_op_tip]', 'mouseover', 
        function() {
            var opts = OP_COMMON.OP_TIPS[this.getAttribute("_op_tip")];
            parent.openTips.show(this, opts, window);
        });
        QZFL.event.delegate(document.body, '[_op_tip]', 'mouseout', 
        function() {
            parent.openTips.hide(window);
        });
    }
};


示例:http://www.cjblog.org/uploadcrop/index.html


源码下载:http://www.cjblog.org/uploadcrop/uploadcrop.rar

非常感谢 张鑫旭 提供的Jcrop插件

返回首页