当前位置: 首页 > news >正文

使用HTML5的canvas做图片剪裁

前言

图片裁剪上传,不仅是一个很贴合用户体验的功能,还能够统一特定图片尺寸,优化网站排版,一箭双雕。

需求就是那么简单,在浏览器里裁剪图片并上传到服务器。

我第一个想到的方法就是,将图片和裁剪参数(x,y,scale,rotate)一并上传给服务器,服务器来做图片处理,so easy。
但是,这并不符合潮流发展的方向:能在前端做的处理,就放前端做吧。
与潮流妥协的结果就是,前端越来越复杂。

一开始我并不认为浏览器能够读取并生成图片。想想看啊,要做"点击复制"的这样简单的功能,都需要借助 Flash 的浏览器,权限哪有那么大。

参阅各类网站,只要把图片放在本地处理的,基本上都借用了Flash。随便抄一个吧,没有API,就算能修改图片,上传路径都不知道怎么改。更关键的是,我对Flash一窍不通。

好在我们的网站已经完全抛弃了IE9以下的浏览器,只兼容现代HTML5浏览器。(连Opera和微软都开始走Webkit内核的路线了,潮流就是跟着Chrome走)只能寄希望与HTML5,于是钻研了一番,发现如下流程可行。

 

 

以下将对每个环节详解。

获取原图片 File 对象

每个图片文件处理的开始,都是由onchange事件开始

<script>
    function handler(e){
        var originPhoto = e.target.files[0]; // IE10+ 单文件上传取第一个
        window.originFileType = originPhoto.type; //暂存图片类型
        window.originFileName = originPhoto.name; //暂存图片名称
        ...
    }
</script>

<input type="file" name="demo" οnchange='handler(event)' accept="image/*" >
<img id="preview">
<button οnclick="cropAndUpload()">确定并上传</button>

初始化Cropper

在这里介绍一个非常好用的库 cropper.js 
https://github.com/fengyuanchen/cropper
生成遮罩、获取裁剪参数、输出canvas ... 而且绝对轻量级,压缩后的css和js代码只有30KB。他是基于JQuery的,引入JQuery可能还要再大点。不过现在哪个网站没有在用JQuery呢?
兼容IE9+,移动端体验良好,能够响应触摸缩放,拖动。以下是安卓4.4 原生浏览器中的预览图

function handler(event){
    ...
    var URL = window.URL || window.webkitURL , originPhotoURL;
    originPhotoURL = URL.createObjectURL(originPhoto);   //Base64
    $('#preview').cropper({
        aspectRatio: 1 / 1,                 // 固定裁剪比例1:1,裁剪后的图片为正方形
    }).cropper('replace', originPhotoURL);  // 动态设置图片预览
}

绘制Canvas

cropper.js 提供了生成Canvas的方法getCroppedCanvas,可以指定生成画布的大小。
或者根据getData获取裁剪信息(包括旋转和缩放)用ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)进行手动绘制。后者自由性高一点,但是既然有现成的方法,那么就直接用好了。

function cropAndUpload(){
    // 此处注意,生成的Canvas长宽比应与之前规定的裁剪比例一致
    // 否则生成的图片会有失真
    var size = {
        width:100,
        height:100
    }
    var croppedCanvas = $('#preview').cropper("getCroppedCanvas",size);  // 生成 canvas 对象
    var croppedCanvasUrl = croppedCanvas.toDataURL(originFileType); // Base64
    ...
}

应当注意的是widthheight的值并不推荐设置成固定值。裁剪框的大小可能是会超过100*100(比如500*500)的,而实际生成的图片却是100*100,这样的后果就是直接将一个500*500的高清图片,压缩成了100*100的失真图片。同样的,裁剪框小于100*100,生成的图片就会模糊。

Base64 转Blob对象

字符串转为二进制?(前端本来是个做页面的,现在也开始操作文件了。自从有了HTML5,就可以把浏览器当作一个操作系统了)官方并没有出DataURLtoBlob的方法,所以只能自己写一个,转化也挺简单:拆解文件类型,将字符数据转成16进制数据存数组,并用数据初始化一个Blob对象。

function dataURLtoBlob(dataurl) {
    var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while(n--){
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new Blob([u8arr], {type:mime});
}

function cropAndUpload(){
    ...
    var croppedBlob = dataURLtoBlob(croppedCanvasUrl);
    croppedBlob.name = originFileName; // Blob对象没有name
    // Upload(croppedBlob);
}

现在就可以像处理FileObject一样处理 这个blob对象了。

其实在最新的HTML5标准中是支持HTMLCanvasElement.toBlob(callback, mimeType, quality) 

croppedCanvas.toBlob(function(croppedBlob){
    // Upload(croppedBlob);
},originFileType)

原文作者来自 MaxLeap 团队_UX成员:John王

原文链接: https://blog.maxleap.cn/archives/705

转载于:https://www.cnblogs.com/iocool/p/6674484.html

相关文章:

  • java异常处理(Exception handing)机制
  • 四则运算 web 版
  • 201521123030 《Java程序设计》第7周学习总结
  • Ajax异步封装
  • 闭包与循环
  • iOS 字符串 MD5
  • 查看linux源代码的在线网站
  • Android入门:MVC模式(中)
  • Oracle中INSTR函数与SQL Server中CHARINDEX函数
  • 沟通和编程一样,也是一门艺术系列5(沟通的方向)
  • CSS实现Tab布局
  • Spring定时任务的几种实现(转)
  • Android Handler使用
  • django-rest-framework学习之Requests and Responses--2017年4月13日
  • LightOJ1245 Harmonic Number (II)
  • 实现windows 窗体的自己画,网上摘抄的,学习了
  • [数据结构]链表的实现在PHP中
  • git 常用命令
  • Sass 快速入门教程
  • Spring核心 Bean的高级装配
  • uni-app项目数字滚动
  • VuePress 静态网站生成
  • WePY 在小程序性能调优上做出的探究
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 对象管理器(defineProperty)学习笔记
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 少走弯路,给Java 1~5 年程序员的建议
  • 通过来模仿稀土掘金个人页面的布局来学习使用CoordinatorLayout
  • 在GitHub多个账号上使用不同的SSH的配置方法
  • 在weex里面使用chart图表
  • FaaS 的简单实践
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • $NOIp2018$劝退记
  • (1综述)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (附源码)python旅游推荐系统 毕业设计 250623
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (十)T检验-第一部分
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (四)Android布局类型(线性布局LinearLayout)
  • (算法)Game
  • (一)kafka实战——kafka源码编译启动
  • (转)visual stdio 书签功能介绍
  • (转载)跟我一起学习VIM - The Life Changing Editor
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • .Net6使用WebSocket与前端进行通信
  • .net分布式压力测试工具(Beetle.DT)
  • .NET开源全面方便的第三方登录组件集合 - MrHuo.OAuth
  • .sdf和.msp文件读取
  • .skip() 和 .only() 的使用
  • /3GB和/USERVA开关
  • /etc/sudoer文件配置简析
  • [ JavaScript ] JSON方法
  • [20171106]配置客户端连接注意.txt
  • [C puzzle book] types