作者:回音爱Fred | 来源:互联网 | 2023-09-05 16:45
媒介图片裁剪上传,不仅是一个很贴合用户体验的功用,还能够一致特定图片尺寸,优化网站排版,一举两得。需求就是那末简朴,在浏览器里裁剪图片并上传到服务器。我第一个想到的要领就是,将图片
媒介
图片裁剪上传,不仅是一个很贴合用户体验的功用,还能够一致特定图片尺寸,优化网站排版,一举两得。
需求就是那末简朴,在浏览器里裁剪图片并上传到服务器。
我第一个想到的要领就是,将图片和裁剪参数(x,y,scale,rotate)一并上传给服务器,服务器来做图片处置惩罚,so easy。
然则,这并不相符潮水生长的方向:能在前端做的处置惩罚,就放前端做吧。
与潮水让步的效果就是,前端愈来愈庞杂。
一最先我并不认为浏览器能够读取并天生图片。想想看啊,要做”点击复制”的如许简朴的功用,都须要借助 Flash 的浏览器,权限哪有那末大。
参阅各种网站,只要把图片放在当地处置惩罚的,基本上都借用了Flash。随意抄一个吧,没有API,就算能修正图片,上传途径都不晓得怎么改。更症结的是,我对Flash一无所知。
幸亏我们的网站已完整扬弃了IE9以下的浏览器,只兼容当代HTML5浏览器。(连Opera和微软都最先走Webkit内核的线路了,潮水就是随着Chrome走)只能寄愿望与HTML5,因而研讨了一番,发明以下流程可行。
st=>start: 原图片 File 对象
e=>end: 上传裁剪后的Blob对象
op=>operation: 初始化Cropper 图片Base64预览
op1=>operation: 依据Cropper裁剪参数绘制Canvas(Base64)
op2=>operation: Base64转Blob对象
st->op->op1->op2->e
以下将对每一个环节详解。
猎取原图片 File 对象
每一个图片文件处置惩罚的最先,都是由onchange事宜最先
初始化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
...
}
应该注重的是width
和height
的值并不引荐设置成牢固值。裁剪框的大小多是会凌驾100100(比方500500)的,而现实天生的图片倒是100100,如许的效果就是直接将一个500500的高清图片,紧缩成了100100的失真图片。一样的,裁剪框小于100100,天生的图片就会隐约。
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