分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 运营维护

【jQuery插件分享】Cropper——一个简单方便的图片裁剪插件

发布时间:2023-09-06 02:29责任编辑:傅花花关键词:jQuery

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

插件介绍

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

官方文档(英文)

  • jQuery

    • GitHub项目地址
    • 官方示例
  • js

    • GitHub项目地址

兼容性

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

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

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

// 转换为png格式的dataURLvar dataURL = $().cropper(‘getCroppedCanvas‘, { ???width:100, ???height:100}).toDataURL(‘image/png‘);// 转换为Blob后显示在img标签中var URL = window.URL || window.webkitURL;$().cropper(‘getCroppedCanvas‘, { ???width:100, ???height:100}).toBlob(function (blob) { ???$().attr(‘src‘,URL.createObjectURL(blob));});

简单实例

在页面直接使用cropper

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

代码如下:

<!DOCTYPE html><html lang="zh-cn"><head><meta charset="UTF-8"><title>裁剪图片</title><link href="https://cdn.bootcss.com/cropper/3.1.3/cropper.min.css" rel="stylesheet"><link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"><style> ???????.row{ ???????????margin-bottom: 5px; ???????} ???????#photo { ???????????max-width: 100%; ???????} ???????.img-preview { ???????????width: 100px; ???????????height: 100px; ???????????overflow: hidden; ???????} ???????button { ???????????margin-top:10px; ???????} ???????#result { ???????????width: 150px; ???????????height: 150px; ???????}</style></head><body><div class="container"> ???<div class="row"> ???????<div class="col-sm-12 text-center"> ???????????<label for="input" class="btn btn-danger" id=""> ???????????<span>选择图片</span> ???????????<input type="file" id="input" class="sr-only"> ???????????</label> ???????</div> ???</div> ???<div class="row"> ???????<div class="col-sm-6 col-sm-offset-2"> ???????????<img src="" id="photo"> ???????</div> ???????<div class="col-sm-2"> ???????????<div> ???????????????<p> ???????????????????预览(100*100): ???????????????</p> ???????????????<div class="img-preview"> ???????????????</div> ???????????</div> ???????????<button class="btn btn-primary" onclick="crop()">裁剪图片</button> ???????????<div> ???????????????<br/> ???????????????<p> ???????????????????结果: ???????????????</p> ???????????????<img src="" alt="裁剪结果" id="result"> ???????????</div> ???????</div> ???</div></div><!-- Scripts --><script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script><script src="https://cdn.bootcss.com/cropper/3.1.3/cropper.min.js"></script><script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script><script> ???????// 修改自官方demo的js ???????var initCropper = function (img, input){ ???????????var $image = img; ???????????var options = { ???????????????aspectRatio: 1, // 纵横比 ???????????????viewMode: 2, ???????????????preview: ‘.img-preview‘ // 预览图的class名 ???????????}; ???????????$image.cropper(options); ???????????var $inputImage = input; ???????????var uploadedImageURL; ???????????if (URL) { ???????????????// 给input添加监听 ???????????????$inputImage.change(function () { ???????????????????var files = this.files; ???????????????????var file; ???????????????????if (!$image.data(‘cropper‘)) { ???????????????????????return; ???????????????????} ???????????????????if (files && files.length) { ???????????????????????file = files[0]; ???????????????????????// 判断是否是图像文件 ???????????????????????if (/^image\/\w+$/.test(file.type)) { ???????????????????????????// 如果URL已存在就先释放 ???????????????????????????if (uploadedImageURL) { ???????????????????????????????URL.revokeObjectURL(uploadedImageURL); ???????????????????????????} ???????????????????????????uploadedImageURL = URL.createObjectURL(file); ???????????????????????????// 销毁cropper后更改src属性再重新创建cropper ???????????????????????????$image.cropper(‘destroy‘).attr(‘src‘, uploadedImageURL).cropper(options); ???????????????????????????$inputImage.val(‘‘); ???????????????????????} else { ?????????????????????????window.alert(‘请选择一个图像文件!‘); ?????????????????????} ?????????????????} ?????????????}); ???????????} else { ???????????????$inputImage.prop(‘disabled‘, true).addClass(‘disabled‘); ???????????} ???????} ???????var crop = function(){ ???????????var $image = $(‘#photo‘); ???????????var $target = $(‘#result‘); ???????????$image.cropper(‘getCroppedCanvas‘,{ ???????????????width:300, // 裁剪后的长宽 ???????????????height:300 ???????????}).toBlob(function(blob){ ???????????????// 裁剪后将图片放到指定标签 ???????????????$target.attr(‘src‘, URL.createObjectURL(blob)); ???????????}); ???????} ???????$(function(){ ???????????initCropper($(‘#photo‘),$(‘#input‘)); ???????}); ???</script></body></html>

  

在bootstrap模态框中使用cropper

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

代码如下:

<!DOCTYPE html><html lang="zh-cn"><head><meta charset="UTF-8"><title>上传头像</title><link href="https://cdn.bootcss.com/cropper/3.1.3/cropper.min.css" rel="stylesheet"><link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"><style type="text/css"> ???body{ ???????text-align: center; ???} ???#user-photo { ???????width:300px; ???????height:300px; ???????margin-top: 10px; ???} ???#photo { ???????max-width:100%; ???????max-height:350px; ???} ???.img-preview-box { ???????text-align: center; ???} ???.img-preview-box > div { ???????display: inline-block;; ???????margin-right: 10px; ???} ???.img-preview { ???????overflow: hidden; ???} ???.img-preview-box .img-preview-lg { ???????width: 150px; ???????height: 150px; ???} ???.img-preview-box .img-preview-md { ???????width: 100px; ???????height: 100px; ???} ???.img-preview-box .img-preview-sm { ???????width: 50px; ???????height: 50px; ???????border-radius: 50%; ???}</style></head><body><button class="btn btn-primary" data-target="#changeModal" data-toggle="modal">打开</button><br/><div class="user-photo-box"> ???<img id="user-photo" src=""></div></div><div class="modal fade" id="changeModal" tabindex="-1" role="dialog" aria-hidden="true"><div class="modal-dialog"> ???<div class="modal-content"> ???????<div class="modal-header"> ???????????<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> ???????????<h4 class="modal-title text-primary"> ???????????<i class="fa fa-pencil"></i> ???????????????????????更换头像 ???????????</h4> ???????</div> ???????<div class="modal-body"> ???????????<p class="tip-info text-center"> ???????????????未选择图片 ???????????</p> ???????????<div class="img-container hidden"> ???????????????<img src="" ?id="photo"> ???????????</div> ???????????<div class="img-preview-box hidden"> ???????????????<hr> ???????????????<span>150*150:</span> ???????????????<div class="img-preview img-preview-lg"> ???????????????</div> ???????????????<span>100*100:</span> ???????????????<div class="img-preview img-preview-md"> ???????????????</div> ???????????????<span>30*30:</span> ???????????????<div class="img-preview img-preview-sm"> ???????????????</div> ???????????</div> ???????</div> ???????<div class="modal-footer"> ???????????<label class="btn btn-danger pull-left" for="photoInput"> ???????????<input type="file" class="sr-only" id="photoInput" accept="image/*"> ???????????<span>打开图片</span> ???????????</label> ???????????<button class="btn btn-primary disabled" disabled="true" onclick="sendPhoto();">提交</button> ???????????<button class="btn btn-close" aria-hidden="true" data-dismiss="modal">取消</button> ???????</div> ???</div></div></div><script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script><script src="https://cdn.bootcss.com/cropper/3.1.3/cropper.min.js"></script><script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script><script type="text/javascript"> ???var initCropperInModal = function(img, input, modal){ ???????var $image = img; ???????var $inputImage = input; ???????var $modal = modal; ???????var options = { ???????????aspectRatio: 1, // 纵横比 ???????????viewMode: 2, ???????????preview: ‘.img-preview‘ // 预览图的class名 ???????}; ???????// 模态框隐藏后需要保存的数据对象 ???????var saveData = {}; ???????var URL = window.URL || window.webkitURL; ???????var blobURL; ???????$modal.on(‘show.bs.modal‘,function () { ???????????// 如果打开模态框时没有选择文件就点击“打开图片”按钮 ???????????if(!$inputImage.val()){ ???????????????$inputImage.click(); ???????????} ???????}).on(‘shown.bs.modal‘, function () { ???????????// 重新创建 ???????????$image.cropper( $.extend(options, { ???????????????ready: function () { ???????????????????// 当剪切界面就绪后,恢复数据 ???????????????????if(saveData.canvasData){ ???????????????????????$image.cropper(‘setCanvasData‘, saveData.canvasData); ???????????????????????$image.cropper(‘setCropBoxData‘, saveData.cropBoxData); ???????????????????} ???????????????} ???????????})); ???????}).on(‘hidden.bs.modal‘, function () { ???????????// 保存相关数据 ???????????saveData.cropBoxData = $image.cropper(‘getCropBoxData‘); ???????????saveData.canvasData = $image.cropper(‘getCanvasData‘); ???????????// 销毁并将图片保存在img标签 ???????????$image.cropper(‘destroy‘).attr(‘src‘,blobURL); ???????}); ???????if (URL) { ???????????$inputImage.change(function() { ???????????????var files = this.files; ???????????????var file; ???????????????if (!$image.data(‘cropper‘)) { ???????????????????return; ???????????????} ???????????????if (files && files.length) { ???????????????????file = files[0]; ???????????????????if (/^image\/\w+$/.test(file.type)) { ???????????????????????????if(blobURL) { ???????????????????????????URL.revokeObjectURL(blobURL); ???????????????????????} ???????????????????????blobURL = URL.createObjectURL(file); ???????????????????????????// 重置cropper,将图像替换 ???????????????????????$image.cropper(‘reset‘).cropper(‘replace‘, blobURL); ???????????????????????????// 选择文件后,显示和隐藏相关内容 ???????????????????????$(‘.img-container‘).removeClass(‘hidden‘); ???????????????????????$(‘.img-preview-box‘).removeClass(‘hidden‘); ???????????????????????$(‘#changeModal .disabled‘).removeAttr(‘disabled‘).removeClass(‘disabled‘); ???????????????????????$(‘#changeModal .tip-info‘).addClass(‘hidden‘); ???????????????????????} else { ???????????????????????window.alert(‘请选择一个图像文件!‘); ???????????????????} ???????????????} ???????????}); ???????} else { ???????????$inputImage.prop(‘disabled‘, true).addClass(‘disabled‘); ???????} ???} ???var sendPhoto = function(){ ???????$(‘#photo‘).cropper(‘getCroppedCanvas‘,{ ???????????width:300, ???????????height:300 ???????}).toBlob(function(blob){ ???????????// 转化为blob后更改src属性,隐藏模态框 ???????????$(‘#user-photo‘).attr(‘src‘,URL.createObjectURL(blob)); ???????????$(‘#changeModal‘).modal(‘hide‘); ???????}); ???} ???$(function(){ ???????initCropperInModal($(‘#photo‘),$(‘#photoInput‘),$(‘#changeModal‘)); ???});</script></body></html>

  

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

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

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

var sendPhoto = function () { ???// 得到PNG格式的dataURL ???var photo = $(‘#photo‘).cropper(‘getCroppedCanvas‘, { ???????width: 300, ???????height: 300 ???}).toDataURL(‘image/png‘); ???$.ajax({ ???????url: ‘上传地址‘, // 要上传的地址 ???????type: ‘post‘, ???????data: { ???????????‘imgData‘: photo ???????}, ???????dataType: ‘json‘, ???????success: function (data) { ???????????if (data.status == 0) { ???????????????// 将上传的头像的地址填入,为保证不载入缓存加个随机数 ???????????????$(‘.user-photo‘).attr(‘src‘, ‘头像地址?t=‘ + Math.random()); ???????????????$(‘#changeModal‘).modal(‘hide‘); ???????????} else { ???????????????alert(data.info); ???????????} ???????} ???});}

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

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

  

【jQuery插件分享】Cropper——一个简单方便的图片裁剪插件

原文地址:https://www.cnblogs.com/phoebeyue/p/10253882.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved