实现图片上传
<input type="file" id="upload">
<script>
const upload = document.getElementById('upload');
upload.addEventListener('change', function (e) {
console.log(e.target.files);
})
</script>
对图片格式与大小进行限制
<input type="file" id="upload">
<script>
//定义图片类型与最大尺寸
const Accept = ['image/jpg', 'image/png', 'image/jpeg'];
const MaxSize = 1024 * 1024
const upload = document.getElementById('upload');
upload.addEventListener('change', function (e) {
const [file] = e.target.files
if (!file) return
//获取图片信息
const { type: fileType, size: fileSize } = file
//图片格式验证
if (!Accept.includes(fileType)) {
alert(`不支持${fileType}类型`)
upload.value = ''
return
}
//图片大小验证
if (fileSize > MaxSize) {
alert(`文件大小不能超过${MaxSize}`)
upload.value = ''
return
}
})
这样,图片大小与图片类型就已经有了限制.
核心图片压缩算法
图片转base64
function ToBase64(file, callback) {
let reader = new FileReader()
reader.readAsDataURL(file)
reader.addEventListener('load', function (e) {
console.log(e.target.result);
})
}
ToBase64(file)
readAsDataURL 方法会读取指定的 Blob 或 File 对象。读取操作完成的时候,readyState 会变成已完成DONE,并触发 loadend (en-US) 事件,同时 result 属性将包含一个data:URL 格式的字符串(base64 编码)以表示所读取文件的内容。
图片压缩
//压缩图片
function compress(base64Image) {
let maxW = 500
let maxH = 500
// console.log(base64Image)
const image = new Image()
image.addEventListener('load', function (e) {
let ratio
let needCompress = false
console.log(image.naturalWidth, image.naturalHeight);
//naturalWidth和naturalHeight是图片原始尺寸永远不会改变
//当限定宽 > 图片宽
if (maxW < image.naturalWidth) {
needCompress = true
ratio = image.naturalWidth / maxW
console.log(ratio, 'ratio');
maxH = image.naturalHeight / ratio
console.log(maxH, 'maxH');
}
//当限定高 > 图片高
if (maxH < image.naturalHeight) {
needCompress = true
ratio = image.naturalHeight / maxH
console.log(ratio, 'ratio');
maxW = image.naturalWidth / ratio
console.log(maxW, 'maxW');
}
//当图片 < 最大值
if (!needCompress) {
maxW = image.naturalWidth
maxH = image.naturalHeight
}
const canvas = document.createElement('canvas')
canvas.width = maxW
canvas.height = maxH
canvas.style.visibility = 'hidden'
document.body.appendChild(canvas)
const ctx = canvas.getContext('2d')
ctx.clearRect(0, 0, maxW, maxH) //清空画布
ctx.drawImage(image, 0, 0, maxW, maxH) //将图片绘制到canvas上
const compressImage = canvas.toDataURL('image/jpeg', 0.9)//转换为base64编码
canvas.remove()
})
image.src = base64Image
// document.body.appendChild(image)
}
改造图片转base64方法,在其中进行图片压缩
//转换为base64
function ToBase64(file, callback) {
let reader = new FileReader()
reader.readAsDataURL(file)
reader.addEventListener('load', function (e) {
const base64 = e.target.result
callback && callback(base64)
reader = null
})
}
ToBase64(file,compress)
整体代码
<!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>
</head>
<body>
<input type="file" id="upload">
<script>
//上传图片到服务器
function uploadToServer(compressImage) {
console.log('上传图片到服务器');
}
//基本数据
const Accept = ['image/jpg', 'image/png', 'image/jpeg'];
const MaxSize = 1024 * 1024
const upload = document.getElementById('upload');
upload.addEventListener('change', function (e) {
const [file] = e.target.files
if (!file) {
return
}
const { type: fileType, size: fileSize } = file
//图片格式验证
if (!Accept.includes(fileType)) {
alert(`不支持${fileType}类型`)
upload.value = ''
return
}
//图片大小验证
if (fileSize > MaxSize) {
alert(`文件大小不能超过${MaxSize}`)
upload.value = ''
return
}
//压缩图片
//转换为base64
function ToBase64(file, callback) {
let reader = new FileReader()
reader.addEventListener('load', function (e) {
const base64 = e.target.result
callback && callback(base64)
reader = null
})
reader.readAsDataURL(file)
}
//压缩图片
function compress(base64Image, callback) {
let maxW = 500
let maxH = 500
// console.log(base64Image)
const image = new Image()
image.addEventListener('load', function (e) {
let ratio
let needCompress = false
// console.log(image.width, image.height);
console.log(image.naturalWidth, image.naturalHeight);
//naturalWidth和naturalHeight是图片原始尺寸永远不会改变,width和height是图片在浏览器中的尺寸
if (maxW < image.naturalWidth) {
needCompress = true
ratio = image.naturalWidth / maxW
console.log(ratio, 'ratio');
maxH = image.naturalHeight / ratio
console.log(maxH, 'maxH');
}
if (maxH < image.naturalHeight) {
needCompress = true
ratio = image.naturalHeight / maxH
console.log(ratio, 'ratio');
maxW = image.naturalWidth / ratio
console.log(maxW, 'maxW');
}
if (!needCompress) {
maxW = image.naturalWidth
maxH = image.naturalHeight
}
const canvas = document.createElement('canvas')
canvas.width = maxW
canvas.height = maxH
canvas.style.visibility = 'hidden'
document.body.appendChild(canvas)
const ctx = canvas.getContext('2d')
ctx.clearRect(0, 0, maxW, maxH) //清空画布
ctx.drawImage(image, 0, 0, maxW, maxH) //将图片绘制到canvas上
const compressImage = canvas.toDataURL('image/jpeg', 0.9)
callback && callback(compressImage) //模拟发请求
console.log(compressImage);
canvas.remove()
})
image.src = base64Image
// document.body.appendChild(image)
}
ToBase64(file, (base64Image) => compress(base64Image, uploadToServer))
})
</script>
</body>
</html>
核心流程
- 监听 input type = file 的 change 方法 , 获取到 e.target.files
- 使用 fileREader 读取文件 , 监听 该对象的 load 方法 , 拿到 e.target.result , 这是 base64 数据
- 压缩图片 新建 image 对象 , 监听 load 方法 根据自定义的宽高拿到纵横比对图片进行限制
- 使用 canvas 画布 进行图片的绘制 , 使用 drawImage 方法 , 把图片绘制到画布上 , 再调用 toDataURL 方法(方法返回一个包含图片展示的 data URI )