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

Wesley13
• 阅读 720

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

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

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

准备工作

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

普通的文件上传:

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

带预览裁剪功能的上传:

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

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

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

实现原理

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

具体用法

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

[html]  view plain copy

效果如下:

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

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

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

[html]  view plain copy

  1. <img src="flowers.jpg" id="preview" />

代码改成

[javascript]  view plain copy

  1. $(function(){

  2. $('#target').Jcrop({

  3. onChange: showPreview,

  4. onSelect: showPreview,

  5. aspectRatio: 1

  6. });

  7. });

当选择框改变,将会执行下面的函数

[html]  view plain copy

  1. function showPreview(coords)

  2. {

  3. var rx = 100 / coords.w;

  4. var ry = 100 / coords.h;

  5. $('#preview').css({

  6. width: Math.round(rx * 300) + 'px',

  7. height: Math.round(ry * 300) + 'px',

  8. marginLeft: '-' + Math.round(rx * coords.x) + 'px',

  9. marginTop: '-' + Math.round(ry * coords.y) + 'px'

  10. });

  11. }

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

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

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

与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研究了一下

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

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

通过样式我们看到,图片被放大到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. if (srcWidth >= destWidth && srcHeight >= destHeight) {

  21. Image image = bi.getScaledInstance(finalWidth, finalHeight,Image.SCALE_DEFAULT);//获取缩放后的图片大小

  22. cropFilter = new CropImageFilter(x, y, destWidth, destHeight);

  23. img = Toolkit.getDefaultToolkit().createImage(

  24. new FilteredImageSource(image.getSource(), cropFilter));

  25. BufferedImage tag = new BufferedImage(destWidth, destHeight,

  26. BufferedImage.TYPE_INT_RGB);

  27. Graphics g = tag.getGraphics();

  28. g.drawImage(img, 0, 0, null); // 绘制截取后的图

  29. g.dispose();

  30. // 输出为文件

  31. ImageIO.write(tag, "JPEG", new File(srcImageFile));

  32. }

  33. } catch (Exception e) {

  34. e.printStackTrace();

  35. }

  36. }

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Docker 部署SpringBoot项目不香吗?
  公众号改版后文章乱序推荐,希望你可以点击上方“Java进阶架构师”,点击右上角,将我们设为★“星标”!这样才不会错过每日进阶架构文章呀。  !(http://dingyue.ws.126.net/2020/0920/b00fbfc7j00qgy5xy002kd200qo00hsg00it00cj.jpg)  2
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这