原文:https://segmentfault.com/a/1190000012344970

插件介绍

这是一个我在写以前的项目的途中发现的一个国人写的jQuery图像裁剪插件,当时想实现用户资料的头像上传功能,并且能够预览图片,和对图片进行简单的裁剪、旋转,花了不少时间才看到了这个插件,感觉功能挺全面,代码实现起来也挺简单,再加上用的是Bootstrap,对移动端操作也有适配,于是就用了。现在稍微有点时间就记录一下,方便以后再用的时候查阅。另外也有对应的js版本。

官方文档(英文)

兼容性

兼容所有支持了Canvas的浏览器(IE9+),一小部分功能例外,具体请查看官方文档。

得到裁剪到的图像的canvas,如果没有裁剪,那么就返回的是整个原图图像的canvas。

这是最重要的一个方法,通过这个方法就可以得到裁剪后的图像,再使用toDataURL()得到base64 dataURL(不指定格式的话会是png格式)或者toBlob()得到Blob,然后就可以很轻松地将图片上传至服务器上或者显示在某个img标签中了。例如:

  1. // 转换为png格式的dataURL
  2. var dataURL = $().cropper('getCroppedCanvas', {
  3. width:100,
  4. height:100
  5. }).toDataURL('image/png');
  6.  
  7. // 转换为Blob后显示在img标签中
  8. var URL = window.URL || window.webkitURL;
  9. $().cropper('getCroppedCanvas', {
  10. width:100,
  11. height:100
  12. }).toBlob(function (blob) {
  13. $().attr('src',URL.createObjectURL(blob));
  14. });

简单实例

在页面直接使用cropper

接下来只是实现一个简单的功能:网页中可以上传图片,然后对图片进行裁剪,点击确定后会显示出裁剪后的图片。

代码如下:

  1. <!DOCTYPE html>
  2. <html lang="zh-cn">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>裁剪图片</title>
  6. <link href="https://cdn.bootcss.com/cropper/3.1.3/cropper.min.css" rel="stylesheet">
  7. <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
  8. <style>
  9. .row{
  10. margin-bottom: 5px;
  11. }
  12. #photo {
  13. max-width: 100%;
  14. }
  15. .img-preview {
  16. width: 100px;
  17. height: 100px;
  18. overflow: hidden;
  19. }
  20. button {
  21. margin-top:10px;
  22. }
  23. #result {
  24. width: 150px;
  25. height: 150px;
  26. }
  27. </style>
  28. </head>
  29. <body>
  30. <div class="container">
  31. <div class="row">
  32. <div class="col-sm-12 text-center">
  33. <label for="input" class="btn btn-danger" id="">
  34. <span>选择图片</span>
  35. <input type="file" id="input" class="sr-only">
  36. </label>
  37. </div>
  38. </div>
  39. <div class="row">
  40. <div class="col-sm-6 col-sm-offset-2">
  41. <img src="" id="photo">
  42. </div>
  43. <div class="col-sm-2">
  44. <div>
  45. <p>
  46. 预览(100*100):
  47. </p>
  48. <div class="img-preview">
  49. </div>
  50. </div>
  51. <button class="btn btn-primary" onclick="crop()">裁剪图片</button>
  52. <div>
  53. <br/>
  54. <p>
  55. 结果:
  56. </p>
  57. <img src="" alt="裁剪结果" id="result">
  58. </div>
  59. </div>
  60. </div>
  61. </div>
  62. <!-- Scripts -->
  63. <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
  64. <script src="https://cdn.bootcss.com/cropper/3.1.3/cropper.min.js"></script>
  65. <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  66. <script>
  67. // 修改自官方demo的js
  68. var initCropper = function (img, input){
  69. var $image = img;
  70. var options = {
  71. aspectRatio: 1, // 纵横比
  72. viewMode: 2,
  73. preview: '.img-preview' // 预览图的class名
  74. };
  75. $image.cropper(options);
  76. var $inputImage = input;
  77. var uploadedImageURL;
  78. if (URL) {
  79. // 给input添加监听
  80. $inputImage.change(function () {
  81. var files = this.files;
  82. var file;
  83. if (!$image.data('cropper')) {
  84. return;
  85. }
  86. if (files && files.length) {
  87. file = files[0];
  88. // 判断是否是图像文件
  89. if (/^image\/\w+$/.test(file.type)) {
  90. // 如果URL已存在就先释放
  91. if (uploadedImageURL) {
  92. URL.revokeObjectURL(uploadedImageURL);
  93. }
  94. uploadedImageURL = URL.createObjectURL(file);
  95. // 销毁cropper后更改src属性再重新创建cropper
  96. $image.cropper('destroy').attr('src', uploadedImageURL).cropper(options);
  97. $inputImage.val('');
  98. } else {
  99. window.alert('请选择一个图像文件!');
  100. }
  101. }
  102. });
  103. } else {
  104. $inputImage.prop('disabled', true).addClass('disabled');
  105. }
  106. }
  107. var crop = function(){
  108. var $image = $('#photo');
  109. var $target = $('#result');
  110. $image.cropper('getCroppedCanvas',{
  111. width:300, // 裁剪后的长宽
  112. height:300
  113. }).toBlob(function(blob){
  114. // 裁剪后将图片放到指定标签
  115. $target.attr('src', URL.createObjectURL(blob));
  116. });
  117. }
  118. $(function(){
  119. initCropper($('#photo'),$('#input'));
  120. });
  121. </script>
  122. </body>
  123. </html>

  

在bootstrap模态框中使用cropper

虽然在模态框中可以像上面一样使用cropper,甚至我以前写的项目也是跟上面一样,但是这次整理的时候突然发现了一个bug:当隐藏模态框后调整浏览器大小(甚至按f12),再打开模态框后cropper的容器会改变,导致难以使用。于是,我在GitHub中翻找了issue,在官方的example中找到了对应的解决方法。但其实这个解决方法也是一种暴力解法,即模态框隐藏后销毁cropper,打开后重新创建cropper,可能会有别的方法,因为不确定会不会有别的bug,所以暂时还是用官方的方法比较好。

代码如下:

  1. <!DOCTYPE html>
  2. <html lang="zh-cn">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>上传头像</title>
  6. <link href="https://cdn.bootcss.com/cropper/3.1.3/cropper.min.css" rel="stylesheet">
  7. <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
  8. <style type="text/css">
  9. body{
  10. text-align: center;
  11. }
  12. #user-photo {
  13. width:300px;
  14. height:300px;
  15. margin-top: 10px;
  16. }
  17. #photo {
  18. max-width:100%;
  19. max-height:350px;
  20. }
  21. .img-preview-box {
  22. text-align: center;
  23. }
  24. .img-preview-box > div {
  25. display: inline-block;;
  26. margin-right: 10px;
  27. }
  28. .img-preview {
  29. overflow: hidden;
  30. }
  31. .img-preview-box .img-preview-lg {
  32. width: 150px;
  33. height: 150px;
  34. }
  35. .img-preview-box .img-preview-md {
  36. width: 100px;
  37. height: 100px;
  38. }
  39. .img-preview-box .img-preview-sm {
  40. width: 50px;
  41. height: 50px;
  42. border-radius: 50%;
  43. }
  44. </style>
  45. </head>
  46. <body>
  47. <button class="btn btn-primary" data-target="#changeModal" data-toggle="modal">打开</button><br/>
  48. <div class="user-photo-box">
  49. <img id="user-photo" src="">
  50. </div>
  51. </div>
  52. <div class="modal fade" id="changeModal" tabindex="-1" role="dialog" aria-hidden="true">
  53. <div class="modal-dialog">
  54. <div class="modal-content">
  55. <div class="modal-header">
  56. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
  57. <h4 class="modal-title text-primary">
  58. <i class="fa fa-pencil"></i>
  59. 更换头像
  60. </h4>
  61. </div>
  62. <div class="modal-body">
  63. <p class="tip-info text-center">
  64. 未选择图片
  65. </p>
  66. <div class="img-container hidden">
  67. <img src="" alt="" id="photo">
  68. </div>
  69. <div class="img-preview-box hidden">
  70. <hr>
  71. <span>150*150:</span>
  72. <div class="img-preview img-preview-lg">
  73. </div>
  74. <span>100*100:</span>
  75. <div class="img-preview img-preview-md">
  76. </div>
  77. <span>30*30:</span>
  78. <div class="img-preview img-preview-sm">
  79. </div>
  80. </div>
  81. </div>
  82. <div class="modal-footer">
  83. <label class="btn btn-danger pull-left" for="photoInput">
  84. <input type="file" class="sr-only" id="photoInput" accept="image/*">
  85. <span>打开图片</span>
  86. </label>
  87. <button class="btn btn-primary disabled" disabled="true" onclick="sendPhoto();">提交</button>
  88. <button class="btn btn-close" aria-hidden="true" data-dismiss="modal">取消</button>
  89. </div>
  90. </div>
  91. </div>
  92. </div>
  93. <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
  94. <script src="https://cdn.bootcss.com/cropper/3.1.3/cropper.min.js"></script>
  95. <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  96. <script type="text/javascript">
  97. var initCropperInModal = function(img, input, modal){
  98. var $image = img;
  99. var $inputImage = input;
  100. var $modal = modal;
  101. var options = {
  102. aspectRatio: 1, // 纵横比
  103. viewMode: 2,
  104. preview: '.img-preview' // 预览图的class名
  105. };
  106. // 模态框隐藏后需要保存的数据对象
  107. var saveData = {};
  108. var URL = window.URL || window.webkitURL;
  109. var blobURL;
  110. $modal.on('show.bs.modal',function () {
  111. // 如果打开模态框时没有选择文件就点击“打开图片”按钮
  112. if(!$inputImage.val()){
  113. $inputImage.click();
  114. }
  115. }).on('shown.bs.modal', function () {
  116. // 重新创建
  117. $image.cropper( $.extend(options, {
  118. ready: function () {
  119. // 当剪切界面就绪后,恢复数据
  120. if(saveData.canvasData){
  121. $image.cropper('setCanvasData', saveData.canvasData);
  122. $image.cropper('setCropBoxData', saveData.cropBoxData);
  123. }
  124. }
  125. }));
  126. }).on('hidden.bs.modal', function () {
  127. // 保存相关数据
  128. saveData.cropBoxData = $image.cropper('getCropBoxData');
  129. saveData.canvasData = $image.cropper('getCanvasData');
  130. // 销毁并将图片保存在img标签
  131. $image.cropper('destroy').attr('src',blobURL);
  132. });
  133. if (URL) {
  134. $inputImage.change(function() {
  135. var files = this.files;
  136. var file;
  137. if (!$image.data('cropper')) {
  138. return;
  139. }
  140. if (files && files.length) {
  141. file = files[0];
  142. if (/^image\/\w+$/.test(file.type)) {
  143.  
  144. if(blobURL) {
  145. URL.revokeObjectURL(blobURL);
  146. }
  147. blobURL = URL.createObjectURL(file);
  148.  
  149. // 重置cropper,将图像替换
  150. $image.cropper('reset').cropper('replace', blobURL);
  151.  
  152. // 选择文件后,显示和隐藏相关内容
  153. $('.img-container').removeClass('hidden');
  154. $('.img-preview-box').removeClass('hidden');
  155. $('#changeModal .disabled').removeAttr('disabled').removeClass('disabled');
  156. $('#changeModal .tip-info').addClass('hidden');
  157.  
  158. } else {
  159. window.alert('请选择一个图像文件!');
  160. }
  161. }
  162. });
  163. } else {
  164. $inputImage.prop('disabled', true).addClass('disabled');
  165. }
  166. }
  167.  
  168. var sendPhoto = function(){
  169. $('#photo').cropper('getCroppedCanvas',{
  170. width:300,
  171. height:300
  172. }).toBlob(function(blob){
  173. // 转化为blob后更改src属性,隐藏模态框
  174. $('#user-photo').attr('src',URL.createObjectURL(blob));
  175. $('#changeModal').modal('hide');
  176. });
  177. }
  178.  
  179. $(function(){
  180. initCropperInModal($('#photo'),$('#photoInput'),$('#changeModal'));
  181. });
  182. </script>
  183. </body>
  184. </html>

  

使用cropper来上传图片到服务器

由于cropper可以得到两种裁剪后图片的数据(即blob和dataURL),所以对应的上传到后台也会有两种方法,在这里我只写一种使用ajax上传base64 dataURL的,另一种方法如果有兴趣,可以自己尝试。

页面中,将上面的sendPhoto方法改为:

  1. var sendPhoto = function () {
  2. // 得到PNG格式的dataURL
  3. var photo = $('#photo').cropper('getCroppedCanvas', {
  4. width: 300,
  5. height: 300
  6. }).toDataURL('image/png');
  7.  
  8. $.ajax({
  9. url: '上传地址', // 要上传的地址
  10. type: 'post',
  11. data: {
  12. 'imgData': photo
  13. },
  14. dataType: 'json',
  15. success: function (data) {
  16. if (data.status == 0) {
  17. // 将上传的头像的地址填入,为保证不载入缓存加个随机数
  18. $('.user-photo').attr('src', '头像地址?t=' + Math.random());
  19. $('#changeModal').modal('hide');
  20. } else {
  21. alert(data.info);
  22. }
  23. }
  24. });
  25. }

  后台中,Java的主要代码如下:(使用了jdk8的Base64,,如果是低版本请自行替换)

  1. /**
  2. * 将Base64位编码的图片进行解码,并保存到指定目录
  3. */
  4. public static void decodeBase64DataURLToImage(String dataURL, String path, String imgName) throws IOException {
  5. // 将dataURL开头的非base64字符删除
  6. String base64 = dataURL.substring(dataURL.indexOf(",") + 1);
  7. FileOutputStream write = new FileOutputStream(new File(path + imgName));
  8. byte[] decoderBytes = Base64.getDecoder().decode(base64);
  9. write.write(decoderBytes);
  10. write.close();
  11. }

  

【jQuery插件分享】Cropper——一个简单方便的图片裁剪插件的更多相关文章

  1. Cropper – 简单的 jQuery 图片裁剪插件

    Cropper 是一个简单的 jQuery 图像裁剪插件.它支持选项,方法,事件,触摸(移动),缩放,旋转.输出的裁剪数据基于原始图像大小,这样你就可以用它们来直接裁剪图像. 如果你尝试裁剪跨域图像, ...

  2. Croppic – 免费开源的 jQuery 图片裁剪插件

    Croppic 这款开源的 jQuery 图片裁剪插件能够满足网站开发人员各种不同的使用需要.只需要简单的上传图片,就可以实现你想要的图像缩放和裁剪功能.因为使用了 HTML5 FormData  对 ...

  3. 5 款最新的 jQuery 图片裁剪插件

    这篇文章主要介绍最新的 5 款 jQuery 图片裁剪插件,可以帮助你轻松的实现你网站需要的图像裁剪功能. Cropit Cropit 是一个 jQuery 插件,支持图像裁剪和缩放功能.Cropit ...

  4. jQuery 图片裁剪插件 Jcrop

    Jcrop是一个jQuery图片裁剪插件,它能为你的WEB应用程序快速简单地提供图片裁剪的功能.特点如下: 对所有图片均unobtrusively(无侵入的,保持DOM简洁) 支持宽高比例锁定 支持 ...

  5. 基于jQuery功能非常强大的图片裁剪插件

    今天我们要来介绍一款基于jQuery功能非常强大的图片裁剪插件,这款jQuery图片裁剪插件可以选择裁剪框的尺寸比例,可以设置高宽尺寸,同时可以设置图片翻转角度,当然也支持图片的缩放,裁剪框也可以用鼠 ...

  6. 制作一个简单的WPF图片浏览器

    原文:制作一个简单的WPF图片浏览器 注:本例选自MSDN样例,并略有改动.先看效果: 这里实现了以下几个功能:1.  对指定文件夹下所有JPG文件进行预览2.  对选定图片进行旋转3.  对选定图片 ...

  7. 开源JS图片裁剪插件

    开源JS图片裁剪插件 一.总结 一句话总结: 要用点赞最高的插件,这样适用性最好,效果最好,出问题的概率也最低,这里电脑端和手机端都可以用的建议用 cropper.js 二.5款好用的开源JS图片裁剪 ...

  8. 头像截图上传三种方式之一(一个简单易用的flash插件)(asp.net版本)

    flash中有版权声明,不适合商业开发.这是官网地址:http://www.hdfu.net/ 本文参考了http://blog.csdn.net/yafei450225664/article/det ...

  9. 【UI插件】开发一个简单日历插件(上)

    前言 最近开始整理我们的单页应用框架了,虽然可能比不上MVVM模式的开发效率,也可能没有Backbone框架模块清晰,但是好歹也是自己开发出来 而且也用于了这么多频道的东西,如果没有总结,没有整理,没 ...

随机推荐

  1. Angular 4.x 修仙之路

    参考:https://segmentfault.com/a/1190000008754631 一个Angular4的博客教程目录

  2. 值类型的TryParse

    值类型(Struct(如:DateTime).基本类型(如:double).枚举类型)的TryParse方法,通常可使用该方法将“字符串”转换为当前类型,并out出.比如:日期格式的字符串   转换为 ...

  3. JavaScript 打印Div内容

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Untitled Page& ...

  4. word2016_统计字数

    统计字数 审阅->字数统计

  5. proxy-target-class 作用

    该属性值默认为false,表示使用JDK动态代理织入增强;当值为true时,表示使用CGLib动态代理织入增强;但是,即使设置为false,如果目标类没有生命接口, 则Spring将自动使用CGLib ...

  6. 进程上下文频繁切换导致load average过高

    一.问题现象 现网有两台虚拟机主机95%的cpu处于idle状态,内存使用率也不是特别高,而主机的load average达到了40多. 二.问题分析 先在主机上通过top.free.ps.iosta ...

  7. 在 Bash on Ubuntu 上安装Nginx

    前言 Win10 上的 Bash on Ubuntu 是个很好用的玩具,让windows开发环境下的人能无缝操练Linux,但是涉及到网络部分还是有很多要该进的地方,比如Nginx的安装就遇到了问题. ...

  8. Git 分布式版本控制的常见命令

    Git 的作用:  (1)方便多人协同开发; (2)方便版本控制 Git 分布式版本控制的主要区域及命令图,下面会详细讲解: 创建项目并将切换至项目目录下 1. 创建本地仓库:  git init  ...

  9. 随手写的一个检测php连接mysql的小脚本

    最近偶然接触到一点点的php开发,要用到mysql数据库,由于mysql和php版本的关系,php5里面连接函数有mysql_connect(),mysqli_connect()两种,php7中又使用 ...

  10. URL中不应出现汉字

    浏览器会在跳转时,先将汉字编译成 Unicode,然后跳转,导致hash值改变两次,相当于history 中 加入了两次URL