FileReader
HTML5
定义了FileReader
作为文件API
的重要成员用于读取文件,根据W3C
的定义,FileReader
接口提供了读取文件的方法和包含读取结果的事件模型。
创建实例
const reader = new FileReader();
方法
事件
Blod
Blob
是用来支持文件操作的。简单的说:在JS
中,有两个构造函数 File
和 Blob
, 而File
继承了所有Blob
的属性。
所以在我们看来,File
对象可以看作一种特殊的Blob
对象。
上面说了,File
对象是一种特殊的Blob
对象,那么它自然就可以直接调用Blob
对象的方法。让我们看一看Blob
具体有哪些方法,以及能够用它们实现哪些功能:
Canvas
中的ImageData
对象
ImageData
对象中存储着canvas
对象真实的像素数据,它包含以下几个只读属性:
width
:图片宽度,单位是像素height
:图片高度,单位是像素data
:Uint8ClampedArray
类型的一维数组,包含着RGBA
格式的整型数据,范围在 0 至 255 之间(包括 255)。
创建一个ImageData
对象
使用createImageData()
方法去创建一个新的,空白的ImageData
对象。
const myImageData = ctx.createImageData(width, height);
上面代码创建了一个新的具体特定尺寸的ImageData
对象。所有像素被预设为透明黑。
得到场景像素数据
为了获得一个包含画布场景像素数据的ImageData
对象,可以用getImageData()
方法:
const myImageData = ctx.getImageData(left, top, width, height);
在场景中写入像素数据
你可以用putImageData()
方法去对场景进行像素数据的写入。
ctx.putImageData(myImageData, dx, dy);
toDataURL
将canvas
转为 data URI
格式
const canvas = document.getElementById('canvas');
const dataURL = canvas.toDataURL();
console.log(dataURL);
具体实现
第一步:获取文件并读取文件
const handleUpload = (event) => {
let file = event.target.files[0];
let fileReader = new FileReader();
fileReader.onload = (e) => {
imgUrl.value = e.target.result
imageRef.value.onload = () => {
drawImage()
};
};
console.log(file)
fileReader.readAsDataURL(file);
}
第二步:绘制canvas
const drawImage = () => {
let image = imageRef.value;
let canvas = canvasRef.value;
let ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
let imageWidth = image.width;
let imageHeight = image.height;
ctx.drawImage(
image,
0,
0,
imageWidth,
imageHeight
)
}
第三步:裁剪图片
getImageData里的x、y、width、height就是在裁剪图片时选定范围后能获得的值,因为不是裁剪图片的重点,就不展开说了。
const crop = () => {
let canvas = canvasRef.value;
let ctx = canvas.getContext('2d');
const imageData = ctx.getImageData(x, y, width, height);
let avatarCanvas = document.createElement('canvas');
avatarCanvas.width = 100;
avatarCanvas.height = 100;
let avatarCtx = avatarCanvas.getContext('2d');
avatarCtx.putImageData(imageData, 0, 0);
let avatarDataUrl = avatarCanvas.toDataURL();
clipeUrl.value = avatarDataUrl
}
总结
裁剪图片不难,总结起来就是分为以下两步。
- 监听选择文件的onchange事件,选择完图片之后onchange回调里的参数能拿到file对象,然后实例FileReader,FileReader类用于读取文件,包含readAsDataURL方法异步读取文件内容,比如图片base64,onload事件文件读取成功完成时触发,这样就能拿到上传图片的base64,用这个base64去new Image在onload的时候去绘画canvas,用canvas的drawImage把图片画进去,这样完成了第一步。
- 在用户选定了裁剪范围裁剪之后,用canvas的getImageData传入x、y、width、height获取画布裁剪范围内的像素数据,再建一个canvas把刚才获取的像素数据putImageData进去,最后toDataURL就能拿到裁剪之后图片的base64了。