第一次写头像裁剪上传,原本想着直接本地预览裁剪再上传,可是时间有限,jquery.jcrop貌似并没有对 假设是ie下图片预览效果是滤镜做的 做出对应处理,也没有时间去改;仅仅好将就一下先把图片上传上去再预览
1.先看一下我引入的js
<script src="${adminBasePath}resources/js/jquery.1.8.3.js"></script> <script src="${adminBasePath}resources/js/layer.js"></script> <script src="${adminBasePath}resources/js/jquery.jcrop.js"></script> <script src="${adminBasePath}resources/js/ajaxfileupload.js"></script> <script src="${adminBasePath}resources/js/perview-image.js"></script>
2.当中perview-image.js是从一位友友哪里粘贴过去的,名字忘了不好意思;(由于我用的是require。所以这里没拆出来)
define(function() { return { timers : [], closeImg : { before : "", after : "" }, loading : "", fileImg : "", // 获取预览元素 getElementObject : function(elem) { if (elem.nodeType && elem.nodeType === 1) { return elem; } else { return document.getElementById(elem); } }, // 開始图片预览 beginPerview : function(/* 文件上传控件实例 */file, /* 须要显示的元素id或元素实例 */ perviewElemId,/* 上传页面所在的document对象 */dcmt,/* 文件后缀名 */fileSuf) { var imgSufs = ",jpg,jpeg,bmp,png,gif,"; var isImage = imgSufs.indexOf("," + fileSuf.toLowerCase() + ",") > -1;// 检查是否为图片 if (isImage) { this.imageOperation(file, perviewElemId, dcmt); } else { this.fileOperation(perviewElemId, fileSuf); } }, // 一般文件显示操作 fileOperation : function(/* 须要显示的元素id或元素实例 */perviewElemId,/* 文件后缀名 */ fileSuf) { var that=this; var preview_div = this.getElementObject(perviewElemId); var MAXWIDTH = preview_div.clientWidth; var MAXHEIGHT = preview_div.clientHeight; var img = document.createElement("img"); preview_div.appendChild(img); img.style.visibility = "hidden"; img.src = this.fileImg; img.onload = function() { var rect = that.clacImgZoomParam(MAXWIDTH, MAXHEIGHT, img.offsetWidth, img.offsetHeight); img.style.width = rect.width + 'px'; img.style.height = rect.height + 'px'; img.style.marginLeft = rect.left + 'px'; img.style.marginTop = rect.top + 'px'; img.style.visibility = "visible"; } var txtTop = 0 - (MAXHEIGHT * 2 / 3); $( '<div style="text-align:center; position:relative; z-index:100; color:#404040;font: 13px/27px Arial,sans-serif;"></div>') .text(fileSuf + "文件").css("top", txtTop + "px").appendTo( preview_div); }, // 图片预览操作 imageOperation : function(/* 文件上传控件实例 */file, /* 须要显示的元素id或元素实例 */ perviewElemId,/* 上传页面所在的document对象 */dcmt) { var that=this; for (var t = 0; t < this.timers.length; t++) { window.clearInterval(this.timers[t]); } this.timers.length = 0; var preview_div = this.getElementObject(perviewElemId); var MAXWIDTH = preview_div.clientWidth; var MAXHEIGHT = preview_div.clientHeight; if (file.files && file.files[0]) { // 此处为Firefox。Chrome以及IE10的操作 preview_div.innerHTML = ""; var img = document.createElement("img"); preview_div.appendChild(img); img.style.visibility = "hidden"; img.onload = function() { var rect = that.clacImgZoomParam(MAXWIDTH, MAXHEIGHT, img.offsetWidth, img.offsetHeight); img.style.width = rect.width + 'px'; img.style.height = rect.height + 'px'; img.style.marginLeft = rect.left + 'px'; img.style.marginTop = rect.top + 'px'; img.style.visibility = "visible"; } if(file.isURL){ img.src=file.files[0]; return false; } var reader = new FileReader(); reader.onload = function(evt) { img.src = evt.target.result; } reader.readAsDataURL(file.files[0]); } else {// 此处为IE6,7。8,9的操作 file.select(); file.blur(); var src = dcmt.selection.createRange().text; var div_sFilter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='scale',src='" + src + "')"; var img_sFilter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='image',src='" + src + "')"; preview_div.innerHTML = ""; var img = document.createElement("div"); preview_div.appendChild(img); img.style.filter = img_sFilter; img.style.visibility = "hidden"; img.style.width = "100%"; img.style.height = "100%"; function setImageDisplay() { var rect = that.clacImgZoomParam(MAXWIDTH, MAXHEIGHT, img.offsetWidth, img.offsetHeight); preview_div.innerHTML = ""; var div = document.createElement("div"); div.style.width = rect.width + 'px'; div.style.height = rect.height + 'px'; div.style.marginLeft = rect.left + 'px'; div.style.marginTop = rect.top + 'px'; div.style.filter = div_sFilter; preview_div.appendChild(div); } // 图片载入计数 var tally = 0; var timer = window.setInterval(function() { if (img.offsetHeight != MAXHEIGHT) { window.clearInterval(timer); setImageDisplay(); } else { tally++; } // 假设超过两秒钟图片还不能载入,就停止当前的轮询 if (tally > 20) { window.clearInterval(timer); setImageDisplay(); } }, 100); this.timers.push(timer); } }, // 按比例缩放图片 clacImgZoomParam : function(maxWidth, maxHeight, width, height) { var param = { width : width, height : height }; if (width > maxWidth || height > maxHeight) { var rateWidth = width / maxWidth; var rateHeight = height / maxHeight; if (rateWidth > rateHeight) { param.width = maxWidth; param.height = Math.round(height / rateWidth); } else { param.width = Math.round(width / rateHeight); param.height = maxHeight; } } param.left = Math.round((maxWidth - param.width) / 2); param.top = Math.round((maxHeight - param.height) / 2); return param; }, // 创建图片预览元素 createPreviewElement : function(/* 关闭图片名称 */name,/* 上传时的文件名称 */file, /* 预览时的样式 */ style) { var img = document.createElement("div"); img.title = file; img.style.overflow = "hidden"; for ( var s in style) { img.style[s] = style[s]; } var text = document.createElement("div"); text.style.width = style.width; text.style.overflow = "hidden"; text.style.textOverflow = "ellipsis"; text.style.whiteSpace = "nowrap"; text.innerHTML = file; var top = 0 - window.parseInt(style.width) - 15; var right = 0 - window.parseInt(style.width) + 14; var close = document.createElement("img"); close.setAttribute("name", name); close.src = this.closeImg.before; close.style.position = "relative"; close.style.top = top + "px"; close.style.right = right + "px"; close.style.cursor = "pointer"; var loadtop = (0 - window.parseInt(style.height)) / 2 - 26; var loadright = (0 - window.parseInt(style.width)) / 2 + 22; var imgloading = document.createElement("img"); imgloading.src = this.loading; imgloading.style.position = "relative"; imgloading.style.top = loadtop + "px"; imgloading.style.right = loadright + "px"; imgloading.style.display = "none"; var main = document.createElement("div"); main.appendChild(img); main.appendChild(text); main.appendChild(close); main.appendChild(imgloading); return main; }, // 获取预览区域 getPerviewRegion : function(elem) { var perview = $(this.getElementObject(elem)); if (!perview.find("ul").length) { var ul = document.createElement("ul"); ul.style.listStyleType = "none"; ul.style.margin = "0px"; ul.style.padding = "0px"; var div = document.createElement("div"); div.style.clear = "both"; perview.append(ul).append(div); return ul; } else { return perview.children("ul").get(0); } }, // 获取上传文件大小 getFileSize : function(/* 上传控件dom对象 */file, /* 上传控件所在的document对象 */ dcmt) { var fileSize; if (file.files && file.files[0]) { fileSize = file.files[0].size; } else { file.select(); var src = dcmt.selection.createRange().text; try { var fso = new ActiveXObject("Scripting.FileSystemObject"); var fileObj = fso.getFile(src); fileSize = fileObj.size; } catch (e) { return "error"; } } fileSize = ((fileSize / 1024) + "").split(".")[0]; return fileSize; } } });3.然后先看我前端的代码
<script type="text/html" id="upload_photo_tml"> <div class="upload-photo"> <div class="photo-lg-pre pre-img"> <div class="img-border" id="img-border"> </div> </div> <div class="photo-up-op"> <div class="photo-sm-pre" id="preview-pane"> <img src="${imgPath}header-img2.png" class="headimg-top" /> <div class="preview-container"> </div> </div> <div class="photo-up-btn" align="center"> <input type="file" name="userPhoto" id="userPhoto" /> <span class="file-button" id="upload-file-btn" data-id="userPhoto">选择图片</span> </div> </div> </div> </script>
$(document).on("click","#headImage",function(){ var index=layer.confirm($("#upload_photo_tml").html(), { title:"上传头像", btn: ['确定','取消'] //button }, function(){ if(opts.selectData.w==undefined) return false; //确定上传 type 为1 opts.uploadType=1; var data={ type:opts.uploadType, x:opts.selectData.x, y:opts.selectData.y, opts.selectData.w, height:opts.selectData.h }; if(opts.uploadData!=null){ data.paramString=encodeURI(JSON.stringify(opts.uploadData)); } ajaxfileupload.ajaxFileUpload({ url: opts.uploadPhotoURL, type: 'post', secureuri: false, // 一般设置为false data: data, fileElementId: "userPhoto", // 上传文件的id、name属性名 dataType: 'json', // 返回值类型,一般设置为json、application/json success: function(data, status) { if(data.responseCode&&data.responseCode==200){ $(opts.userHeadPhoto).attr("src",adminBasePath+data.fileURL+data.fileName); layer.alert("上传成功!",{icon:1}); }else{ layer.alert("上传失败!",{icon:2}); } }, error: function(data, status, e) { console.log(e); } }); }); }); $(document).on("change",'#userPhoto',function(e) { //假设仅仅是预览 type为0 opts.uploadType=0; $(".preview-container").html(""); var data={ type:opts.uploadType, x:0, y:0, 0, height:0 }; if(opts.uploadData!=null){ data.paramString=encodeURI(JSON.stringify(opts.uploadData)); } var loadingIndex=layer.load(0, {shade: false}); var userPhotoHTML=$("#userPhoto").prop("outerHTML"); ajaxfileupload.ajaxFileUpload({ url: opts.uploadPhotoURL, type: 'post', secureuri: false, // 一般设置为false data: data, fileElementId: "userPhoto", // 上传文件的id、name属性名 dataType: 'json', // 返回值类型,一般设置为json、application/json success: function(data, status) { opts.uploadType=1; opts.uploadData=data; perviewImage.imageOperation({files:[adminBasePath+data.fileURL+data.fileName+"?date="+ (new Date()).getTime()],isURL:true},"img-border",document); layer.close(loadingIndex); if(opts.jcrop_api!=null) opts.jcrop_api.destroy(); opts.xsize = $(opts.pcnt).width(); opts.ysize = $(opts.pcnt).height(); $('#img-border>img').Jcrop({ bgColor: "#ffffff", onChange: that._updatePreview, onSelect: that._updatePreview, aspectRatio: opts.xsize / opts.ysize },function(){ // var _w=$(".jcrop-holder>img").width(), // _h=$(".jcrop-holder>img").height(), // _wh=0; // if(_w>=_h) // _wh=_w; // else // _wh=_h; var bounds = this.getBounds(); opts.boundx = bounds[0]; opts.boundy = bounds[1]; opts.jcrop_api = this; //opts.jcrop_api.setSelect([0,0,_wh,_wh]); $(".preview-container").html($("#img-border").html()); $(".photo-up-btn").prepend(userPhotoHTML); }); }, error: function(data, status, e) { console.log(e); } }); }); //绘制选框 that._updatePreview = function(c) { var opts=that.opts; opts.selectData=c; if (parseInt(c.w) > 0) { var rx = opts.xsize / c.w; var ry = opts.ysize / c.h; $(opts.pimg).css({ width : Math.round(rx * opts.boundx) + 'px', height : Math.round(ry * opts.boundy) + 'px', marginLeft : '-' + Math.round(rx * c.x) + 'px', marginTop : '-' + Math.round(ry * c.y) + 'px' }); } };
4.然后是Controller层以及图片上传方法的代码
/** * 用户上传头像 * * @param type * 0表示暂时预览,1表示上传确认头像 * @return */ @ResponseBody @RequestMapping(value = "upload/userphoto", method = RequestMethod.POST) public void uploadUserphoto(Integer type, double x, double y, double width, double height) { JSONObject obj = new JSONObject(); try { String paramString = ""; JSONObject paj = null; if (null != getRequest().getParameter("paramString")) { paramString = URLDecoder.decode( getRequest().getParameter("paramString"), "UTF-8"); paj = (JSONObject) JSON.parse(paramString); } if (type == 1) { String url = getRequest().getSession().getServletContext() .getRealPath(paj.getString("fileURL")); String isOK = UploadImgUtil.cutImage( url + "\" + paj.getString("fileName"), paj.getString("fileURL"), paj.getString("fileName"), x, y, width, height); if (isOK.equals("y")) { String params = HttpRequestUtil.sendPost( "updateUserAvatar", "loginToken=" + getCookieUtil().getCookieValue("L_TOKEN") + "&userAvatar=" + paj.getString("fileURL") + paj.getString("fileName")); obj.put("responseCode", ((JSONObject) JSONObject .parse(params)).get("responseCode")); obj.put("fileURL", paj.getString("fileURL")); obj.put("fileName", paj.getString("fileName")); } else { obj.put("responseCode", "402"); obj.put("responseText", "上传失败"); } } else { obj = UploadImgUtil.uploadPhotoImgUrls(getRequest(), super .getUser().getId().toString(), paramString == "" ? "" : paj.getString("fileURL"), paramString == "" ? "" : paj.getString("fileName")); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); obj.put("responseCode", "402"); obj.put("responseText", "上传失败"); } writeHtml(obj.toJSONString()); }
<pre name="code" class="java">/** * 图片裁剪通用接口 * * @param src * 原图地址 * @param path * 存放路径 * @param name * 存放名称 * @param x * @param y * @param w * @param h * @throws IOException */ public static String cutImage(String src, String path, String name, double x, double y, double w, double h) throws IOException { Image img; ImageFilter cropFilter; String ext = getExtension(name); if (ext == null) ext = "jpg"; BufferedImage bi = ImageIO.read(new File(src)); double rate1 = ((double) bi.getWidth()) / (double) UPLOADPHOTOWIDTH + 0.1; double rate2 = ((double) bi.getHeight()) / (double) UPLOADPHOTOWIDTH + 0.1; // 依据缩放比率大的进行缩放控制 double rate = 0d; if (bi.getWidth() > UPLOADPHOTOWIDTH || bi.getHeight() > UPLOADPHOTOWIDTH) rate = rate1 > rate2 ?rate1 : rate2; else rate = rate1 < rate2 ? rate1 : rate2; BufferedImage tag; Image image = bi.getScaledInstance(bi.getWidth(), bi.getHeight(), Image.SCALE_DEFAULT); // 四个參数分别为图像起点坐标和宽高 // 即: CropImageFilter(int x,int y,int width,int height) cropFilter = new CropImageFilter( rate1 > 1 ?
(int) (x * rate) : (int) x, rate2 > 1 ?
(int) (y * rate) : (int) y, rate1 > 1 ? (int) (w * rate) : (int) w, rate2 > 1 ? (int) (h * rate) : (int) h); img = Toolkit.getDefaultToolkit().createImage( new FilteredImageSource(image.getSource(), cropFilter)); int type = BufferedImage.TYPE_INT_RGB; if ("gif".equalsIgnoreCase(ext) || "png".equalsIgnoreCase(ext)) { type = BufferedImage.TYPE_INT_ARGB; } int newWidth; int newHeight; // 推断是否是等比缩放 if ((w * rate) > 640 || (h * rate) > 640) { // 为等比缩放计算输出的图片宽度及高度 double rate3 = (w * rate) / (double) OUTPUTWIDTH + 0.1; double rate4 = (h * rate) / (double) OUTPUTWIDTH + 0.1; // 依据缩放比率大的进行缩放控制 double nrate = rate3 > rate4 ? rate3 : rate4; newWidth = (int) ((w * rate) / nrate); newHeight = (int) ((h * rate) / nrate); } else { newWidth = rate1 > 1 ? (int) (w * rate) : (int) w; // 输出的图片宽度 newHeight = rate2 > 1 ?
(int) (h * rate) : (int) h; // 输出的图片高度 } tag = new BufferedImage(newWidth, newHeight, type); Graphics2D g = (Graphics2D) tag.getGraphics(); g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.dispose(); g = tag.createGraphics(); tag = g.getDeviceConfiguration().createCompatibleImage(newWidth, newHeight, Transparency.TRANSLUCENT); g.dispose(); g = tag.createGraphics(); img = img.getScaledInstance(newWidth, newHeight, img.SCALE_AREA_AVERAGING); g.drawImage(img, 0, 0, null); // 绘制剪切后的图 g.dispose(); ImageIO.write(tag, "png", new File(src)); return "y"; } public static String getExtension(String srcImageFile) { String ext = null; if (srcImageFile != null && srcImageFile.lastIndexOf(".") > -1) { ext = srcImageFile.substring(srcImageFile.lastIndexOf(".") + 1); } return ext; }