当前位置: 移动技术网 > IT编程>开发语言>JavaScript > node.js(express)中使用Jcrop进行图片剪切上传功能

node.js(express)中使用Jcrop进行图片剪切上传功能

2018年05月20日  | 移动技术网IT编程  | 我要评论
需求说明 简单来说就是要实现用户上传头像,并且要保存用户裁切后的部分作为用户头像。 第一步,选择图片:   第二步,在弹窗页面中展现并进行裁切: &nb

需求说明

简单来说就是要实现用户上传头像,并且要保存用户裁切后的部分作为用户头像。

第一步,选择图片:

image 

第二步,在弹窗页面中展现并进行裁切:

image 

第三步,点击“保存”,上传服务器。

实现过程

说来有点坎坷,相当于做了2遍,走了弯路。

第1遍是用户一选择图片,就进行了上传,然后返回一个地址,所以在弹层上展现的图片已经是服务器上的图片了,然后进行裁切,再保存。

第2遍找到的一个方法,是在第1遍做到裁切处理时候想到的,即弹层展现的是用户机器上选择的图片,不用先上传,但是用image/base64来展现的。这样就与服务器少了一次交互啊,并且服务器不用存储2遍图片,还提高了弹层展现速度,体验更好,所以是极好的。

说下碰到的主要技术点:

express框架不用多说,就是保存的时候post一下裁切后的base64数据,后台写个对应路由就好。
jquery也不用多说,页面展现控制与ajax提交。

html5/filereader/canvas,filereader用于将文件读取为数据,我们使用它的onload事件;canvas这个用作裁切移动时,实时重绘裁切后的图片(相当于实时预览,当然我是隐藏了,调试的时候可以让他display),可以隐藏,最后上传的其实就是这个canvas的base64数据。

jcrop plugin。这个是裁切插件,必须的了。下载与说明在这里。
其他就是base64字符串保存成图片了,这在服务端比较简单,直接用fs.writefile(filename,databuffer,function(err){});就好了。

具体代码

view页面,主要需要有一个上传控件,还有定义弹窗div以及用于重绘裁切范围图片的canvas,当然页面要引用相应的js插件和css等,主要:

<link rel="stylesheet" href="/css/jquery.jcrop.css" rel="external nofollow" >
<script src="/js/jquery.js"></script>
<script src="/js/jquery.jcrop.js"></script>
<!--上传控件-->
<input type="file" name="uploadimg1" id="uploadimg1">
<!--弹窗与裁切图-->
<div class="cover">
 <img id="img1" alt="">
 <button id="btnsave">保存</button>
</div>
<!--裁切范围重绘canvas-->
<canvas id="mycanva" width="200" height="200">

js/jquery,处理图片加载与裁切上传。

首先要监控上传控件的变化,因为我们这里没有按钮来触发,所以直接监控uploadimg1的change来触发。

$('#uploadimg1').on('change', function() {
 if (document.getelementbyid("uploadimg1").files.length === 0) {
  return;
 }
 var ofile = document.getelementbyid("uploadimg1").files[0];
 if (!ofile) {
  return;
 }
 var filename = ofile.name;
 var filesize = ofile.size;
 var filetype = filename.substring(filename.lastindexof('.'), filename.length).tolowercase();
 if (filetype != '.jpg' && filetype != '.jpeg' && filetype != '.gif' && filetype != '.png' && filetype != '.bmp') {
  alert("请选择jpg,png,gif,bmp格式的图片");
  return;
 }
 if (filesize > 2 * 1024 * 1024) {
  alert('最大支持2mb的图片');
  return;
 }
 var filereader = new filereader();
 filereader.readasdataurl(ofile);
 // 成功读取
 filereader.onload = function(e) {
  // 显示弹窗
  $('.cover').show();
  // 将弹窗中的图片路径设置为选择的图片的base64
  $('#img1').attr('src', e.target.result);
  // 裁切组件初始化
  initjcrop();
 };
});

裁切在弹窗一显示的时候就应该初始化:

function initjcrop() {
 $('#img1').jcrop({
  onchange: updatecoords,
  onselect: updatecoords,
  aspectratio: 1,
  boxwidth: 300,
  boxheight: 300
 }, function() {
  //弹窗中显示的图片尺寸 
  var bb = this.getbounds();
  var bwidth = number(bb[0]) / 2;
  var bheight = number(bb[1]) / 2;
  //设置初始选中裁切范围
  this.setselect([0, 0, bwidth, bheight]);
  //原始图片缩小比例
  try {
   wdthscale = $('#img1')["0"].width / 222;
   heightscale = $('#img1')["0"].height / 238;
  } catch (e) {}
  jcrop_api = this;
 });
}

非常重要的一个坑是,在此之前要定义全局变量jcrop_api,widthscale和heightscale,2个scale变量用于记录选择的原始图片尺寸与在弹窗上展现尺寸的缩小/放大比例的,比如选择的是1024x768的图片,但是弹窗上展现的范围是222x238,这就需要将缩小的倍数记录下来,在裁切的重绘canvas的时候要乘以这个倍数,否则裁切的范围就是在这个222x236尺寸上裁切的,而不是原始图片的尺寸上裁切的。而前面的jcrop_api变量用于重新选择图片时要将上一次的裁切初始化组件destroy掉。

jcrop组件中重要的事件:onchange和onselect,用于确定裁切范围的坐标(尺寸),因此也非常重要,其实重绘canvas就是在这里面完成的。

function updatecoords(c) {
 var img = document.getelementbyid('img1');
 var ctx = document.getelementbyid('mycanva').getcontext('2d');
 try {
  wdthscale = wdthscale === 1 ? $('#img1')["0"].width / 222 : wdthscale;
  heightscale = heightscale === 1 ? $('#img1')["0"].height / 238 : heightscale;
 } catch (e) { }

 //绘制canvas画布
 ctx.drawimage(img, c.x, c.y, c.w * wdthscale, c.h * heightscale, 0, 0, 200, 200);
}

另外就是处理保存按钮来,一个ajax来提交canvas形成的图片的base64字符串,后台接受保存就可以了。

 var data = document.getelementbyid('mycanva').todataurl();
 $.ajax({
  url: '/xxxx',
  type: 'post',
  datatype: 'json',
  cache: false,
  data: {
   'imgdata': data
  },
  success: function(res) {},
  error: function(err) {}
 });

这就是上传裁切(实时预览)的全部过程了。

以上所述是小编给大家介绍的node.js(express)中使用jcrop进行图片剪切上传功能,希望对大家有所帮助

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网