图片压缩和缩放的操作
操作背景
背景1
当前手机相机的像素极高,随便拍个照片都是尺寸3000*4000 px的,大小都在5M以上。
背景2
而服务器在接收图片时,为减轻服务器压力,一般对大小和尺寸是有限制的,比如限制尺寸为650*650 , 大小不得超过5M .
背景3
智能手机应用普及率极高,且手机照片在手机app里上传文件的使用越来越普遍。
- 这时就出现了矛盾。 用户想用手机上传
大照片,而服务器希望用户用小照片。 - 于是, 作为前端,就要
闪亮登场了, 我们可以让用户上传大照片,经过前端对图片尺寸的缩放和大小的压缩,让服务器接收到的是符合要求的小照片。既满足了用户,又满足了服务器,双赢!
知识结构
核心要点
- 输入框
input的onchange事件 FileReader文件阅读器img构造器Imagecanvas画图- 目标宽高的等比缩放处理
功能拓展
base64到blob形式的转换- 上传到服务器或云端
案例操作
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>压缩上传后的图片</title>
<style>
</style>
</head>
<body>
<label for="upload_img">
<span>上传图片 + </span>
</label>
<input type="file" id="upload_img" name="upload_img" style="display: none;" accept="image/jpeg">
<script>
var upload_img = document.querySelector('#upload_img');
upload_img.onchange = function() {
var pf = this.files;
console.log(pf[0]);
// pf[0]是刚才上传的图片,包含以下字段:
/*
{
lastModified: 1634548550629, // 最后修改日期的时间戳
lastModifiedDate: Mon Oct 18 2021 17:15:50 GMT+0800 (中国标准时间), // 最后修改的标准时间
name: "222大.jpg", // 图片名
size: 4824418, // 图片大小 单位字节
type: "image/jpeg", // 图片类型
webkitRelativePath: "", // 官方不建议使用的属性
} */
// 这里可以对上传的图片做一些基本处理
// 比如检查图片是否上传了
if(pf.length == 0) {
console.log('图片没上传呢');
return;
}
// 检查图片大小,比如不准超过5M
var MAX_IMG_SIZE = 5 * 1024 * 1024;
if(pf[0].size > MAX_IMG_SIZE) {
console.log('上传失败,图片大小不能超过5M!')
return;
}
// FileReader文件阅读器
var reader = new FileReader();
console.log('reader: ', reader);
// reader包含很多事件方法和值 比如
/*
error 上传出错
onabort 读取操作中断时触发
onerror 读取报错时触发
onload 读取完成后触发(成功了)
onloadend 读取结束时触发 成功和失败都会触发
onprogress 读取Blob时触发
readyState 0表示没有加载任何数据 1 数据正在加载 2 数据读取完成
result 根据读取方法, 返回不同格式的文件
*/
// 使用Image构造器,构造img的dom
var img = new Image();
// console.log('img: ', img);
/*
这里得到的img实例是一个img标签
可以直接操作自己的属性 比如
img.width
img.height
img.src
*/
// 设置一些需要用到的变量
var _duf; // canvas画布生成的base64格式的dataurl文件
var MAX_WIDTH = 650; // 最大宽度 这里以650为例
var MAX_HEIGHT = 650; // 最大高度
var upload_width; // 上传的原始宽度
var upload_height; // 上传的原始高度
var TARGET_WIDTH; // 目标宽度 即画到canvas上的最终宽度
var TARGET_HEIGHT; // 目标高度 即画到canvas上的最终高度
var fileType = pf[0].type; // 文件类型 后面会用到
var fileName = pf[0].name; // 文件名
// readAsDataURL是读取文件方式
// 读取文件后 reader的result属性中会包含一个data:URL格式的
// Base64字符串 以表示读取文件的内容
reader.readAsDataURL(pf[0]);
console.log('已读reader: ', reader);
/*
{
result: "data:image/jpeg;base64,/9j/4X3QRXhpZgAATU0AKgAAA..."
}
*/
// reader读取文件的事件
// FileReader是继承自e.target的 所以可以用e事件
reader.onload = function(e) {
// 把读取到的url给到img
img.src = e.target.result;
}
// 图片加载事件
img.onload = function() {
// 获取图片原始宽高
upload_width = this.width;
upload_height = this.height;
// console.log('图片原始尺寸: ', upload_width, upload_height);
// 进行等比缩放的操作
if(upload_width > MAX_WIDTH || upload_height > MAX_HEIGHT) {
if(upload_width / upload_height > MAX_WIDTH / MAX_HEIGHT) { // 上传的图片宽度较大
TARGET_WIDTH = MAX_WIDTH;
TARGET_HEIGHT = Math.floor(MAX_WIDTH * upload_height / upload_width);
} else { // 上传的图片 高度较大
TARGET_HEIGHT = MAX_HEIGHT;
TARGET_WIDTH = Math.floor(MAX_HEIGHT * upload_width/ upload_height);
}
} else {
TARGET_WIDTH = upload_width;
TARGET_HEIGHT = upload_height;
}
// TARGET_WIDTH TARGET_HEIGHT就是最终被压缩后的宽高
// console.log('target w h: ', TARGET_WIDTH, TARGET_HEIGHT);
// 开始用画布处理图片
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = TARGET_WIDTH;
canvas.height = TARGET_HEIGHT;
// 清除画布
context.clearRect(0, 0, TARGET_WIDTH, TARGET_HEIGHT);
// 把图片放到canvas上 注意这里画布大小 是最终图片的大小
context.drawImage(img, 0, 0, TARGET_WIDTH, TARGET_HEIGHT);
// toDataURL()返回的是一个包含图片展示的data:URL
// ()里可以为图片设定类型。默认是image/png格式
_duf = canvas.toDataURL(fileType);
console.log(_duf);
this.src = _duf;
// 这时的图片已经被压缩了,链接可以用了。
// 后续是上传到云端的介绍
// 转换成blob备用
var pf_n = baseToBlob(_duf);
// 调用云端接口
// xxx...
// 主要作用是生成一个完整的图片链接,方便应用
}
// 需要把base64形式的图片转换成blob形式的文件
// 固定写法
function baseToBlob(_duf) {
var base_arr = _duf.split(',');
var bstr = atob(base_arr[1]);
var n = bstr.length;
var u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type: fileType});
}
}
</script>
</body>
</html>
参考文档
- 文件阅读器
https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader - Image构造器
https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLImageElement/Image - 画布处理
https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/toDataURL - 图片处理1
https://blog.csdn.net/weixin_33755649/article/details/91377182?utm_source=app&app_version=4.15.0&code=app_1562916241&uLinkId=usr1mkqgl919blen - 图片处理2
https://blog.csdn.net/impossible1994727/article/details/89091940 - 图片处理3
https://blog.csdn.net/qq_41786458/article/details/90263201