利用canvas裁切图片,可任意缩放旋转图片进行裁

canvasClipImg

利用canvas裁切图片,可任意缩放旋转图片进行裁切,裁切预览,代码注释清晰,可根据需求自己二次开发。

一、功能描述

   canvas无线图片裁切功能,支持图片上传,裁切预览,图片任意角度旋转缩放裁切,异步上传图片。代码注释清晰。

二、注意事项

1.只需要关注位移,并非图片左上角的坐标,而是图片左右上下滑动的距离,后面缩放会将图片正常话。

2.图片初始时左上角与裁剪框对齐(方便计算初始偏移量值)。

3.图片旋转始终以图片中心做旋转,以图片中心点计算图片旋转是的左上角偏移量。(以其他点旋转也可以,但要始终以同一个点,不然计算偏移量很麻烦)。

4.图片缩放已图片左上角为中心缩放,旋转后的缩放也要以原始左上角缩放。(通过控制图片宽高可以实现始终以原始左上角做缩放)(以其他点缩放要始终保持一个点,不然偏移量计算会有问题)。

5.canvas不要绘制一整张等高等宽的图片,会比较耗时(即:画布宽高,图片宽高,canvas宽高一样,绘制整张高清图)。图片操作用样式控制,最后裁切,在canvas的上下文环境也就是画布中绘制整张图片没性能问题,只要在canvas标签中显示的图片是整张图片的部分就不会太耗性能。

6.canvas 的toBlob方法要做兼容处理。 搜索上传为实现,实现方式与本地图片类似,代码中有注释说明,页面的样式风格是项目中用到的样式风格。具体样式可自行设计。字体样式文件也是本项目用到的字体图标,与图片裁切功能关系不大。静态页中的裁剪框,可以用canvas画布画出一个,减少页面样式布局的复杂度(可参考alloy_finger项目中的图片裁切示例。)

三、关键代码

getSkewXY: function() { //获取画布需要的偏移量方法 var _this = this; //保证图片的缩放是已左上角为中心点,此处的缩放是通过控制图片的width值进行的,可以保证以左上角为中心的。 //缩放操作可以用scale,在手势插件中的scalex进行控制时,缩放的中心点是不定的,根据手势的变化而变化,无法进行计算, //如果此处的样式可以自己控制中心点,也可以用css中的scale进行缩放控制。 //暂时用了width属性进行了缩放控制(重点是要获取图片左上角相对于裁剪区的坐标位置) //图片缩放后的偏移量计算 var tempW = _this.naturalWidth * _this.initScale, tempH = _this.naturalHeight * _this.initScale, diagonal = Math.sqrt(tempW * tempW + tempH * tempH) / 2, //对角线长度的一半 //此处计算的是按照初始宽高计算旋转后的偏移量 tempX = tempW / 2 - Math.cos((_this.initRotate + _this.countRotate) * Math.PI / 180) * diagonal, tempY = tempH / 2 - Math.sin((_this.initRotate + _this.countRotate) * Math.PI / 180) * diagonal; return { x: _this.x + tempX, y: _this.y + tempY }; }    clipImg: function() {//裁切图片方法 var _this = this; if (!_this.imgObj) return; //canvas的宽高与裁剪框保持一致 var canvas = $('<canvas width="' + _this.clipWith + '" height="' + _this.clipHeight + '"></canvas>')[0], context = canvas.getContext('2d'); // 计算图片旋转时,左上角坐标相对画布圆点的偏移量 var temp = _this.getSkewXY(); //先平移在旋转 //canvas对象不变,画布平移,使得画布的左上角与图片位于同一个点,然后旋转画布,达到裁剪看中看到的图片部分与canvas绘制的部分一致 context.translate(temp.x, temp.y); //图片的旋转是按照图片中心点旋转,而画布旋转是基于左上角旋转,所以需要先计算偏移量,在旋转 //最终的结果要使得隐藏canvas窗口中的图片部分与页面中可视的裁剪框可见的图片部分保持一致,才能得到正确的裁剪图片 context.rotate(_this.countRotate * Math.PI / 180); //此处绘图,绘制图片起始点0,0,因为上面画布已经做了便宜,此处不需在处理。将图像绘制在调整后的画布上 context.drawImage(_this.imgObj, 0, 0, _this.naturalWidth * _this.initScale, _this.naturalHeight * _this.initScale); //预览裁切后的图像 $('#temp')[0].src = canvas.toDataURL(); // 将canvas裁切的图片已大对象的形式通过异步请求传给后台保存,与后台自行配合实现 //canvas.toBlob(function(blob){//canvas转换成大对象,作为文件存储 // var formData = new FormData(); // formData.append('pic', blob); // formData.append('lemmaId', _this.getQueryItem('lemmaId')); // formData.append('width', _this.clipWith); // formData.append('height',_this.clipHeight); // $.ajax({ // type: 'POST', // url: '/baike/wireless/edit', // data: formData, // dataType: 'json', // contentType: false, // processData: false, // cache: false, // success: function(data){ // }, // complete: function(){ // } // }); // }, 'image/jpeg', 0.85); } 四、参考资料

alloy_finger.js移动端小巧的手势库(代码库中有一个腾讯应用的图片上传示例,不过不支持图片旋转)

tansform.js与手势库在同一个项目下

版权声明:

1、该文章(资料)来源于互联网公开信息,我方只是对该内容做点评,所分享的下载地址为原作者公开地址。
2、网站不提供资料下载,如需下载请到原作者页面进行下载。