canvas 缩放图片大小,canvas图片放大缩小的方法
问题来源
这个问题源于上传图片文件时,后台限制了2MB的大小,但设置相机拍照时,每分钟都超过2MB。为了不影响用户体验和功能需求,前端需要压缩尺寸,然后转移到后台。
思路分析
找了很多资料,发现只有画布可以压缩图片。
原理大致如下:1。首先将图片的file文件转换为baseURL 2,并创建一个image标签来接收文件以获取图片的宽度、高度和比例。3.创建画布canvas来设置画布的大小。4.在画布上画画。5.压缩画布以获得新的baseURL。6.将基本URL转换回文件。
前提的函数
将file文件转化为base64
/* * * * @ param {二进制文件流} file * @ param {回调函数,返回base64 } fn */function changefiletobaseurl(file,fn){//创建读取文件对象var fileReader=new fileReader();//如果文件未定义,则返回null if (file==undefined)返回fn(null);//读取文件file,结果为base64位filereader . readasdataurl(file);file reader . onload=function(){//将读取的base 64 var im gbase 64 data=this . result;fn(imgbase 64 data);} }将base64转化为文件流
/* * *将base64转换为file * @ param { base URL } dataurl * @ param {文件名}文件名* @ return {文件二进制流} */函数dataurlfile (dataurl,文件名){var arr=dataurl.split(,),mime=arr [0].);/)[1],bstr=atob(arr[1]),n=bstr.length,u8 arr=new uint 8 array(n);while(n-){ u8arr[n]=bstr . charcodeat(n);}返回新文件([u8arr],文件名,{ type:mime });}压缩方法
/***画布压缩图片* @param {参数obj} param * @param {文件二进制流} param.file必传* @param {目标压缩大小} param.targetSize不传初始赋值-1* @param {输出图片宽度}参数宽度不传初始赋值-1,等比缩放不用传高度* @param {输出图片名称} param。文件名不传初始赋值image* @param {压缩图片程度}参数质量不传初始赋值0.92。值范围0~1* @param {回调函数} param.succ必传*/功能按压(param){//如果没有回调函数就不执行if(param param.succ){ //如果文件没定义返回null if(param.file==undefined)返回参数。succ(空);//给参数附初始值参数。targetSize=param。hasownproperty( targetSize )?参数。targetsize:-1;参数。宽度=参数。hasownproperty( width )?参数。宽度:-1;参数。文件名=参数。hasownproperty( fileName )?参数。文件名:“图像”;参数。质量=参数。hasownproperty(质量)?参数质量:0.92;var _ this=this//得到文件类型var文件类型=param。文件。类型;//控制台。log(file type)//image/JPEG if(file type。( image )==-1){ console的索引。日志(请选择图片文件^_^);返回参数。succ(空);} //如果当前大小比目标大小小,直接输出var size=param。文件。尺寸;if(param。targetsize size){ return param。succ(参数。文件);} //读取文件文件,得到的结果为base64位changeFileToBaseURL(param.file,function(base64){ if(base64){ var Image=new Image();image . src=base 64 image . onload=function(){//获得长宽比例var scale=这个。宽度/这个。身高;//控制台。日志(刻度);//创建一个canvas var canvas=文档。createelement(“canvas”);//获取上下文var context=画布。获取上下文(“2d”);//获取压缩后的图片宽度,如果宽度为-1,默认原图宽度canvas.width=param.width==-1?这个。宽度:参数。宽度;//获取压缩后的图片高度,如果宽度为-1,默认原图高度canvas.height=param.width==-1?这个。高度:parse int(param。宽度/比例);//把图片绘制到帆布上面context.drawImage(image,0,0,canvas.width,canvas。身高);//压缩图片,获取到新的base 64 URL变量新图像数据=画布。toda taurl(fileType,param。质量);//将base64转化成文件流var result file=dataURLtoFile(new imagedata,param。文件名);//判断如果目标尺寸有限制且压缩后的图片大小比目标大小大,就弹出错误if(param.targetSize!=-1参数。targetsize结果文件。尺寸){控制台。日志(图片上传尺寸太大,请重新上传^_^);参数。succ(空);}else{ //返回文件流param.succ(结果文件);} } } });} }方法使用
文件的大小是按照字节,所以我们需要把要求的大小转化成字节。 1字节就是一字节就是1B,1KB=1024B,1MB=1024 * 1024B
输入类型= file id= file img class= file img ///图片文件上传获取url$(#fileImg ).on(change ,function(){ pressing({ file:this。files[0],targetSize:2 * 1024 * 1024,quality:0.5,width:600,succ:function(resultFile){ //如果不是空就是压缩成功if(结果文件){//TODO } })});问题总结
图片压缩程度
图片的压缩程度不太好确定,所以可以进行多次尝试,根据需求方的要求进行调整。改变目标图片的大小和清晰度都可以改变图片的压缩程度。
本来想做一个压缩图片的递归,直到图片大小符合期望
后来发现
如果目标尺寸比较小,无论图片怎么压缩,都会导致循环无法跳出,浪费资源。图像压缩几次,文件大小不会变,有时候还会变大,很奇怪。所以我放弃了递归。ios拍摄方向问题
因为ios调大了系统摄像头拍照,逆时针旋转了90度。我把图片压缩发送到后台后,发现图片的exif信息拍摄方向丢失,导致ios上传的图片逆时针旋转90度。这个问题安卓从来没有发现过。
目前我怀疑是base64转换成文件时丢失的。核实后在此补充。
@ version1.033542019-8-23354创建《使用canvas压缩图片大小》
燃_韵奇奇
这就是本文的全部内容。希望对大家的学习和支持有帮助。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。