最近一个项目有图片裁剪并上传的需求(无需兼容IE低版本浏览器),因产品框架比较老,页面使用react、vue等框架的话,迁移成本较高,故无法直接使用这些框架中的组件。google后,找到了一个适合的第三方组件cropper.js,一个jQuery插件,使用简单。
你可能也有类似需求但不想去研究组件源码,在这里分享一下简单实现方法:
目录
- 先上demo代码
- 插件的使用
- 参考文档链接
先上demo代码
<!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;
}
</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="http://cp01-ocean-400.epc.baidu.com:8082/doc/pic/item/b812c8fcc3cec3fdcd4e084dd688d43f87942791.jpg">
</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">
<div class="img-container">
<img src="http://cp01-ocean-400.epc.baidu.com:8082/doc/pic/item/b812c8fcc3cec3fdcd4e084dd688d43f87942791.jpg" alt="" id="photo">
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary submitImgBtn">提交</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, modal){
var $image = img;
var $modal = modal;
var options = {
aspectRatio: 1, // 纵横比
viewMode: 2 // 可选的显示模式
};
// 模态框隐藏后需要保存的数据对象
var saveData = {};
var blobURL;
$modal.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);
});
}
$('.submitImgBtn').on('click', function () {
$('#photo').cropper('getCroppedCanvas',{
width:300,
height:300
}).toBlob(function(blob){
var fd = new FormData();
fd.append("file", blob ,"file_"+Date.parse(new Date())+".png");
$.ajax({
url: "/user/api/editorimg", // 图片服务器地址
type: "POST",
data: fd,
processData: false, // 不处理数据
contentType: false // 不设置内容类型
}).done(function (data) {
var imgData = JSON.parse(data);
if (imgData && imgData.link) {
// 防止裂图,延迟赋值操作
setTimeout(() => {
$('#user-photo').attr('src', imgData.link);
$('#changeModal').modal('hide');
}, 300);
}
});
});
});
$(function(){
initCropperInModal($('#photo'),$('#changeModal'));
});
</script>
</body>
</html>
demo中写死了一个图片地址,可根据自己需要修改。图片裁剪后上传时,需要一个图片接收的地址,不写或者没有更改demo中url的话,裁剪完无法上传图片,会报错,请注意。
下面开始讲解插件具体使用。
插件的使用
因为这次需求需要在弹窗中进行裁剪,方便起见,我使用了bootstrap模态框.
依赖:
- jQuery [https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js]
- bootstrap [https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js]
- FormData (将裁剪后的图片作为file上传到服务器)
引用:
<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">
<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>
基础html结构
<button class="btn btn-primary" data-target="#changeModal" data-toggle="modal">打开</button><br/>
<div class="user-photo-box">
<img id="user-photo" src="http://cp01-ocean-400.epc.baidu.com:8082/doc/pic/item/b812c8fcc3cec3fdcd4e084dd688d43f87942791.jpg">
</div>
user-photo元素为裁切图片前后显示的dom元素,可设置初始默认图片,裁剪完成后进行替换。
bootstrap模态框结构
<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">
<div class="img-container">
<img src="http://cp01-ocean-400.epc.baidu.com:8082/doc/pic/item/b812c8fcc3cec3fdcd4e084dd688d43f87942791.jpg" alt="" id="photo">
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary submitImgBtn">提交</button>
<button class="btn btn-close" aria-hidden="true" data-dismiss="modal">取消</button>
</div>
</div>
</div>
</div>
注意基础html中button中data-target属性值与模态框id值一致。
img-container中的img元素的src,为弹窗show时显示的图片。项目中,根据点击button时获取应该显示的原始图片地址赋值给img-container中img的src。
关键的关键
裁剪上擦的整个操作逻辑为:
点击button -> 弹出模态框 -> 调整裁剪样式后,点提交 -> 图片上传服务器 -> 成功后赋值最新图片url -> 关闭模态框
弹出模态框
- 关联button和modal的id
- 监听
shown.bs.modal
事件,模态框show的时候,初始化cropper
提交
通过getCroppedCanvas
获取裁剪后图片,利用toBlob
转为blob,通过FormData
的append()方法,
formData.append(name, value, filename);
将图片blob对象添加到formData对象中,然后,利用ajax上传到服务器
图片赋值
刚生成图片url时,有时候图片可能还没有完成上传到服务器,所以直接拿url赋值,很有可能裂图,故此处延迟赋值显示
关闭模态框
监听hidden.bs.modal
事件,存储图片信息,并将之前初始化的cropper销毁。
至此,一个简单的裁剪上传的组件开发完成。
快动起手来,试一下吧。【实践是检验真理的唯一标准】