仿淘宝头像上传功能(三)——兼容 IE6 浏览器。
前两篇目录:
之前的这两篇虽然实现了功能,但不兼容低版本浏览器,而且有些浏览器还会死机,所以现在重新做了个新的。
现已在 IE6,IE10,IE11,谷歌测试通过。
这次使用了这两个插件:
Jquery:1.11.2
上图文件插件:ajaxFileUpload
裁剪插件:imgAreaSelect
1.文件上传需要使用到 file 表单,但 file 表单样式太难看,需要进行自定义。
由于在IE下需要手动点击 file 表单才有效果,所以,无法使用 onclick 事件!!
解决办法就是使用样式,覆盖在 file 表单上传,当点击该样式的时候,实际上点击的是 file 表单。
2.ajaxFileUpload 插件的各种版本太多,这里给出自己使用的一个版本。
先直接给出JS源码了:
//////////////////////////////////////////////////////////////// // 上传头像JS //上传头像插件:ajaxFileUpload //裁剪插件:imgAreaSelect /////////////////////////////////////////////////////////////// //上传文件按钮表单 ID。 var inputFileId = "fileupload_input"; //原图片显示 ID。 var sourceImageId = "photo"; //裁剪大图显示 ID。 var bigImageId = "cut1"; //裁剪中图显示 ID。 var centerImageId = "cut2"; //裁剪小图显示 ID。 var smallImageId = "cut3"; //临时图片(隐藏)。 var hiddenImage = "test"; //保存裁剪框左上角 X 坐标的表单。 var inputX = "X"; //保存裁剪框左上角 Y 坐标的表单。 var inputY = "Y"; //保存裁剪框宽度的表单。 var inputWidth = "Width"; //保存裁剪框高度的表单。 var inputHeight = "Height"; //提交按钮表单。 var submitButtonId = "btnAjaxSubmit"; //上传图片文件 URL。 var fileUploadUrl = "/user/icon/upload"; //提交裁剪坐标信息并保存图片的 URL。 var submitUrl = "/user/upload"; var hasFile = false; var isSelect = false; var imgArea = null; //初始化选择控件 function InitSelect() { imgArea = $('#' + sourceImageId).imgAreaSelect({ x1: 0, y1: 0, x2: 10, y2: 10, maxWidth: 300, maxHeight: 300, aspectRatio: '1:1', instance: true, persistent: true, //resizable: true, show: true, handles: true, onSelectEnd: preview }); } function preview(img, selection) { //获取图片链接到缩略图 var cut1 = $("#" + bigImageId); var cut2 = $("#" + centerImageId); var cut3 = $("#" + smallImageId); Zoom(img, cut1, selection, 180, 180); Zoom(img, cut2, selection, 50, 50); Zoom(img, cut3, selection, 30, 30); isSelect = true; $("#" + inputX).val(selection.x1); $("#" + inputY).val(selection.y1); $("#" + inputWidth).val(selection.width); $("#" + inputHeight).val(selection.height); CleanDisabled(); } //缩放预览 function Zoom(source, imgCut, selection, X, Y) { var imgurl = $(source).attr("src"); var sWidth = $(source).width(); var sHight = $(source).height(); $(imgCut).attr("src", imgurl); var scaleX = X / (selection.width || 1); var scaleY = Y / (selection.height || 1); $(imgCut).css({ width: Math.round(scaleX * sWidth) + 'px', height: Math.round(scaleY * sHight) + 'px', marginLeft: '-' + Math.round(scaleX * selection.x1) + 'px', marginTop: '-' + Math.round(scaleY * selection.y1) + 'px' }); } //重设原图宽高 function resetImg() { try { var source = $("#" + sourceImageId); var sWidth = $("#" + hiddenImage).width(); var sHight = $("#" + hiddenImage).height(); if (sWidth > sHight) { $(source).attr("width", 300); $(source).removeAttr("height"); } else { $(source).attr("height", 300); $(source).removeAttr("width"); } } catch (ex) { //showErr("截图程序异常"); } } //默认图片选择区域 function setDefault_Selection() { var x = $("#" + hiddenImage).width(); var y = $("#" + hiddenImage).height(); var scale = 0.0; var x1, y1, x2, y2 = 0; if (x > y) { scale = 300 / x; x = 300; y = scale * y; } else { scale = 300 / y; y = 300; x = scale * x; } var rx = x / 2; var ry = y / 2; var length = 70; x1 = rx - length; y1 = ry - length; x2 = rx + length, y2 = ry + length; imgArea.setSelection(x1, y1, x2, y2); imgArea.update(); preview($("#" + sourceImageId), imgArea.getSelection()); } //图片上传预览 function previewImage(file) { ////只有高版本浏览器可用,可以直接使用本地图片预览。 //if (file.files && file.files[0]) { // if (file.files[0].type != "image/jpeg") { // showErr("仅支持JPG图片文件,且文件小于3M"); // return; // } // if (file.files[0].size > 3145728) { // showErr("仅支持JPG图片文件,且文件小于3M"); // $(file).attr("src", ""); // return; // } // var img = document.getElementById('photo'); // var reader = new FileReader(); // reader.onload = function (evt) { // img.src = evt.target.result; // $("#test").attr("src", evt.target.result); // //延迟加载 // setTimeout(function () { // hasFile = true; // resetImg(); // InitSelect(); // setDefault_Selection(); // }, 200); // } // reader.readAsDataURL(file.files[0]); //} //else // return; /*低版本浏览器兼容*/ var selection = $("#" + sourceImageId).imgAreaSelect({ instance: true }).getSelection(); $.ajaxFileUpload({ url: fileUploadUrl, secureuri: false, fileElementId: inputFileId, //文件上传域的ID data: selection, dataType: 'json', success: function (data, status) //服务器成功响应处理函数 { imgClear(); //图片上传成功后,返回包含原图 URL 的 Json 对象。 $("#" + sourceImageId).attr("src", data.Image + "?num=" + Math.random()); $("#" + hiddenImage).attr("src", data.Image); //延迟加载 setTimeout(function () { hasFile = true; resetImg(); InitSelect(); setDefault_Selection(); }, 200); }, error: function (data, status, e) { //showErr("头像加载失败,请重试或者联系管理员"); } }); } function imgClear() { $("#" + sourceImageId).attr("style", ""); $("#" + sourceImageId).attr("src", ""); $("#" + bigImageId).attr("src", ""); $("#" + centerImageId).attr("src", ""); $("#" + smallImageId).attr("src", ""); } //取消禁用。 function CleanDisabled() { $("#" + submitButtonId).removeAttr("style"); $("#" + submitButtonId).removeAttr("disabled"); } //禁用按钮。 function SetDisabled() { $("#" + submitButtonId).attr("style", "background-color:#f39898;"); $("#" + submitButtonId).attr("disabled", "disabled"); } $("#" + submitButtonId).click(function () { $.ajax({ type: "POST", url: submitUrl, data: $(this).parent().serialize(), dataType: 'json', success: function (data) { if (data.Status > 0) { //showSuc("头像上传成功!"); //$("#currentIcon").attr("src", data.BigIcon); //$("#nav-top-icon").attr("src", data.SmallIcon); } }, error: function () { //showErr("头像上传异常,请重试或者联系管理员"); } }); });
HTML:
<div class="boxbar headbox"> <div class="title">修改头像</div> <div class="content"> <div class="upload_btn"> <form id="fm" method="post" action="/user/icon/upload" enctype="multipart/form-data"> <span id="fileupload-content" class="btn_sc"> <span>上传本地相片</span> <input type="file" id="fileupload_input" name="fileInput" onchange="previewImage(this);" /> </span> </form> <span class="tip">仅支持JPG图片文件,且文件小于3M</span> <img id="test" src="" hidden="hidden" style="display: none;" /> </div> <div class="pic_box"> <div id="img-preview" class="pic_left" style="overflow: hidden;position:relative;"> <img id="photo" src="" /> </div> <div class="pic_line"></div> <div class="pic_con"> <p class="tip">您上传的头像会自动生成三种尺寸,请注意中小尺寸的头像是否清晰</p> <div id="preview_box_200" class="big_pic" style="overflow: hidden;position:relative;"> <img id="cut1" style="position: relative;" /> </div> <div class="pic_cc">大头像尺寸,180x180像素</div> </div> <div class="pic_right"> <div id="preview_box_50" class="midd_pic" style="overflow: hidden;position:relative;"> <img id="cut2" style="position: relative; width: 50px; height: 50px;" src="" /> </div> <div class="pic_cc"> 中尺寸头像50x50像素 <p>(自动生成)</p> </div> <div id="preview_box_small" class="small_pic" style="overflow: hidden;position:relative;"> <img id="cut3" style="position: relative; width: 30px; height: 30px;" /> </div> <div class="pic_cc"> 小尺寸头像30x30像素 <p>(自动生成)</p> </div> </div> </div> <form id="userIconForm" method="POST"> <input id="X" name="X" type="hidden" /> <input id="Y" name="Y" type="hidden" /> <input id="Width" name="Width" type="hidden" /> <input id="Height" name="Height" type="hidden" /> <button id="btnAjaxSubmit" class="btn_tj" type="button" style="background-color:#f39898" disabled="disabled">保 存</button> </form> </div> </div>
这里给出使用的插件源码
ajaxFileUpload
jQuery.extend({ createUploadIframe: function (id, uri) { //create frame var frameId = 'jUploadFrame' + id; var iframeHtml = '<iframe id="' + frameId + '" name="' + frameId + '" style="position:absolute; top:-9999px; left:-9999px"'; if (window.ActiveXObject) { if (typeof uri == 'boolean') { iframeHtml += ' src="' + 'javascript:false' + '"'; } else if (typeof uri == 'string') { iframeHtml += ' src="' + uri + '"'; } } iframeHtml += ' />'; jQuery(iframeHtml).appendTo(document.body); return jQuery('#' + frameId).get(0); }, createUploadForm: function (id, fileElementId, data) { //create form var formId = 'jUploadForm' + id; var fileId = 'jUploadFile' + id; var form = jQuery('<form action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>'); if (data) { for (var i in data) { jQuery('<input type="hidden" name="' + i + '" value="' + data[i] + '" />').appendTo(form); } } var oldElement = jQuery('#' + fileElementId); var newElement = jQuery(oldElement).clone(); jQuery(oldElement).attr('id', fileId); jQuery(oldElement).before(newElement); jQuery(oldElement).appendTo(form); //set attributes jQuery(form).css('position', 'absolute'); jQuery(form).css('top', '-1200px'); jQuery(form).css('left', '-1200px'); jQuery(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 = new Date().getTime() var form = jQuery.createUploadForm(id, s.fileElementId, (typeof (s.data) == 'undefined' ? false : s.data)); 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 { jQuery(io).remove(); jQuery(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 form = jQuery('#' + formId); jQuery(form).attr('action', s.url); jQuery(form).attr('method', 'POST'); jQuery(form).attr('target', frameId); if (form.encoding) { jQuery(form).attr('encoding', 'multipart/form-data'); } else { jQuery(form).attr('enctype', 'multipart/form-data'); } jQuery(form).submit(); //提交file域值不清空(原理:提交后把对象再复制回来,达到不清空的目的) var oldElement = jQuery('#jUploadFile' + id, form); var newElement = jQuery('#' + s.fileElementId); jQuery(newElement).replaceWith(oldElement); jQuery(oldElement).attr('id', s.fileElementId); } catch (e) { jQuery.handleError(s, xml, null, e); } jQuery('#' + frameId).load(uploadCallback); return { abort: function () { } }; }, //修正JQ1.6以上版本去除handleError的BUG handleError: function (s, xhr, status, e) { if (s.error) { s.error.call(s.context || s, xhr, status, e); } if (s.global) { (s.context ? jQuery(s.context) : jQuery.event).trigger("ajaxError", [xhr, s, e]); } }, 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. //修正一直提示ERROR的BUG type==json if (type == "json") //eval("data = \" " + data + " \" "); eval("data = " + data); // evaluate scripts within html if (type == "html") jQuery("<div>").html(data).evalScripts(); return data; } })