JAVA + js 实现 头像上传及裁剪功能

我想大家对头像上传功能在陌生不过了把,每个人都应该用过,当然,从不更改头像的大侠除外,写到这里,我突然想到我的CSDN用户也没有头像,于是,我到设置里面准备去看看CSDN的头像上传功能是怎样的,可是我弄了半天都没搞定,提示说高版本浏览器不支持预览,难道只有IE6才支持?难得吐槽一下,不知道是我人品问题还是没用对。如图:



准备工作

好了,废话不多说了,一般常用的头像上传有两种(据我所知):

普通的文件上传

普通文件上传莫非就是,给你一个选择文件选择按钮,你选择好文件后,剩下的事情你就不管了,后台会把你上传的图片按一定的比例缩放,或者无任何处理,或其他操作,这种方式的好处坏处显而易见,前后台的实现相对来说比较简单,可是用户体验就不是这么满意了,我以前也遇到过这种,不但自己需要找到大概合适大小比例的图片,有事还得自己修改裁剪,然后再传上去,最后结果并不会让我满意,我不得不重新在去做一遍这些繁琐的操作!

带预览裁剪功能的上传:

现在很多用户体验还不错的网站或软件都采用这种方法,最常用的实现就是用的flash,用户上传一张图片,马上就可以自己选取需要的部分,而且还带有及时的预览效果,体验非常不错。


步入正题,最近项目需要,有个地方需要用户上传头像,本来按照产品设计,直接一个选择框,用户选择图片后上传就搞定!这种方法不说用户,就连我开发人员都觉得真心难用,于是我决定弄一个可以预览裁剪上传头像的功能,下面是用到的一款js的图片裁剪插件,性能还算行几乎兼容所有的浏览器。


Jcrop  http://deepliquid.com/content/Jcrop.html


实现原理

当我没接触到这个功能之前,以为这有多神秘多神秘,其实就是两个原图的img标签,其中一个是让你选择预览范围,一个让你看到你选择后的效果,利用Draggable和Resizable特性在原图上创建出一个选择框,然后再按照你选择的范围按照一定的比例和算法让效果图那个img只显示你选择的那一部分,最后把你最后选择的范围坐标以及大小传给后台,后台按照这个范围裁剪相应的图片即可!


具体用法

首先引入相应的js/css文件

[html]  view plain copy
  1. <script src="js/jquery.min.js"></script>  
  2. <script src="js/jquery.Jcrop.min.js"></script>  
  3. <link rel="stylesheet" href="css/jquery.Jcrop.css" type="text/css" />  


然后写入一个image标签,

[html]  view plain copy
  1. <img src="flowers.jpg" id="target" />  


最后给img标签添加可裁剪功能
[javascript]  view plain copy
  1. <script language="Javascript">  
  2.     jQuery(function($) {  
  3.         $('#target').Jcrop();  
  4.     });  
  5. </script>  


效果如下:



如果想预览你选择后的图片,再写入一个img标签

[html]  view plain copy
  1. <img src="flowers.jpg" id="preview" />  

代码改成

[javascript]  view plain copy
  1. $(function(){  
  2.   
  3.     $('#target').Jcrop({  
  4.         onChange: showPreview,  
  5.         onSelect: showPreview,  
  6.         aspectRatio: 1  
  7.     });  
  8.   
  9. });  
当选择框改变,将会执行下面的函数

[html]  view plain copy
  1. function showPreview(coords)  
  2. {  
  3.     var rx = 100 / coords.w;  
  4.     var ry = 100 / coords.h;  
  5.   
  6.     $('#preview').css({  
  7.         width: Math.round(rx * 300) + 'px',  
  8.         height: Math.round(ry * 300) + 'px',  
  9.         marginLeft: '-' + Math.round(rx * coords.x) + 'px',  
  10.         marginTop: '-' + Math.round(ry * coords.y) + 'px'  
  11.     });  
  12. }  

这样,id为preview将只会显示你选择的范围的图片




与JAVA后台结合

前台实现其实很简单,Jcrop下载下来已经有完整的Demo可以运行,用法也很简单,最麻烦的就是后台了,我们可以通过回调函数showPreview得到选择框的x,y,width,height,然后传到后台按照坐标裁剪图片即可,官方是这种说的,可问题来了,我们得到的x,y,w,h只是相对于被缩小后的id为target的img标签的,假设一张1024x768的图,target的大小肯定是固定的,图中为504x374,所以得到的x,y,h,w是基于此比例来的,如果传到后台你用这个坐标来裁剪原图,肯定有问题,这个问题纠结了我很久,我想过通过一定的比例算法来计算实际的x,y是多少,但一直都没找到传到后台的坐标和实际要裁剪的坐标有什么关系,我网上查了很多人说也是直接通过传过来的x,y等参数直接生成新的图片,可生成的图片完全和我选择的不一样,我也想过把图片先压缩成target一样大,然后xy就正确了,但是看到preview里的效果图了吗,那是在原图上选择后的效果,后来我发现preview不就是我要的效果吗,于是打开firebug研究了一下




通过样式我们看到,图片被放大到758x561,并且左外边距和上外边距分别设置成了-529和-261,于是我明白了,后台按照一样的思路不就行了吗?先把图片转成758x561,然后在按照x:528 y:261的坐标裁剪一定的大小,不就是最后要的图片么,


后台用到的java代码方法

[java]  view plain copy
  1. /** 
  2.     *  缩放后裁剪图片方法 
  3.     * @param srcImageFile 源文件 
  4.     * @param x  x坐标 
  5.     * @param y  y坐标 
  6.     * @param destWidth 最终生成的图片宽 
  7.     * @param destHeight 最终生成的图片高 
  8.     * @param finalWidth  缩放宽度 
  9.     * @param finalHeight  缩放高度 
  10.     */  
  11.    public static void abscut(String srcImageFile, int x, int y, int destWidth,  
  12.                              int destHeight,int finalWidth,int finalHeight) {  
  13.        try {  
  14.            Image img;  
  15.            ImageFilter cropFilter;  
  16.            // 读取源图像  
  17.            BufferedImage bi = ImageIO.read(new File(srcImageFile));  
  18.            int srcWidth = bi.getWidth(); // 源图宽度  
  19.            int srcHeight = bi.getHeight(); // 源图高度  
  20.   
  21.            if (srcWidth >= destWidth && srcHeight >= destHeight) {  
  22.                Image image = bi.getScaledInstance(finalWidth, finalHeight,Image.SCALE_DEFAULT);//获取缩放后的图片大小  
  23.                cropFilter = new CropImageFilter(x, y, destWidth, destHeight);  
  24.                img = Toolkit.getDefaultToolkit().createImage(  
  25.                        new FilteredImageSource(image.getSource(), cropFilter));  
  26.                BufferedImage tag = new BufferedImage(destWidth, destHeight,  
  27.                        BufferedImage.TYPE_INT_RGB);  
  28.                Graphics g = tag.getGraphics();  
  29.                g.drawImage(img, 00null); // 绘制截取后的图  
  30.                g.dispose();  
  31.                // 输出为文件  
  32.                ImageIO.write(tag, "JPEG"new File(srcImageFile));  
  33.            }  
  34.        } catch (Exception e) {  
  35.            e.printStackTrace();  
  36.        }  
  37.    }  

转载于:https://my.oschina.net/huewenhua/blog/681590

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值