简言
记录下使用canvas来压缩图片的实现方式。
图片压缩
有的时候会遇到图片压缩的场景,我们可以使用canvas重新绘制图片,然后利用canvas的toDataURL()API导出base64数据实现图片压缩。
canvas图片压缩原理:
- canvas重新绘制图片可以控制绘制图片的大小,进而改变绘制图片的像素数据。
- canvas的toDataURL()API可以控制导出图片质量,改变图片的大小。
实现
我个人实现了一个简单的demo,你可以根据需要自行修改。
demo实现步骤:
- 获取图片
- 创建canvas和img元素,然后将img元素绘制到canvas上
- 使用canvas导出图片
- 提供下载
获取图片
获取图片主要是获取图片的地址。
我是用input元素获取图片,这样可以本地上传图片。
然后监听input的change事件获得文件对象(图片)。
<input type="file" accept="image/*" id="file">
绘制图片
使用canvas上下文的drawImage()方法绘制,方便控制大小。
具体参考:MDN的drawImage
const img = new Image()
img.src = fileBlob
img.onload = function (e) {
console.log(img, img.width, 'img');
const canvas = document.createElement('canvas')
canvas.width = img.width
canvas.height = img.height
const ctx = canvas.getContext('2d')
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
}
导出图片
利用canvas的toDataURL()API导出图片,它有两个参数:
- 参数1:导出类型
- 参数2:图片质量(0-1)1质量最高,0最差。
具体参考:MDN的toDataURL
data = canvas.toDataURL(imgType, 0.5)
图片下载
利用a链接下载。(适合大部分浏览器,兼容性自行实现)
download.onclick = function () {
console.log(data, 'data');
const a = document.createElement('a')
a.href = data
a.download = imgName
a.type = imgType
a.click()
}
源码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片压缩</title>
</head>
<body>
<div>
<input type="file" accept="image/*" id="file">
<div>
<div>
<span>压缩前:</span>
<span id="before-size"></span>
</div>
<div>
<span>压缩后:</span>
<span id="after-size"></span>
</div>
</div>
<div>
<button id="download">下载</button>
</div>
</div>
<script>
const file = document.getElementById('file')
const download = document.getElementById('download')
const beforeSize = document.getElementById('before-size')
const afterSize = document.getElementById('after-size')
let data = null // 压缩后的图片
let imgName = ''
let imgType = ''
file.onchange = function (e) {
console.log(e.target.files);
const files = e.target.files
for (let i = 0; i < files.length; i++) {
const file = files[i]
console.log(file, 'file');
imgName = file.name
imgType = file.type
beforeSize.innerHTML = file.size / 1024 + 'KB'
const fileBlob = URL.createObjectURL(file)
const img = new Image()
img.src = fileBlob
img.onload = function (e) {
console.log(img, img.width, 'img');
const canvas = document.createElement('canvas')
canvas.width = img.width
canvas.height = img.height
const ctx = canvas.getContext('2d')
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
data = canvas.toDataURL(imgType, 0.5)
console.log(getBase64Size(data, imgType), 'data.size');
afterSize.innerHTML = getBase64Size(data, imgType) + 'KB'
}
}
}
download.onclick = function () {
console.log(data, 'data');
const a = document.createElement('a')
a.href = data
a.download = imgName
a.type = imgType
a.click()
}
// 获取base64数据的大小,单位kb
function getBase64Size(base64, type) {
if (!base64) {
return 0
}
if (base64.indexOf(';base64,') === -1) {
return 0
}
base64 = base64.replace('data:' + type + ';base64,', '')
if (base64.length % 4 === 0) {
base64 = base64.replace(/=+$/, '')
}
return (base64.length - base64.length / 8 * 2) / 1024
}
</script>
</body>
</html>
示例图
结语
结束了。