场景:上传图片时,有些图片会很大,如果一次性传很多张,会给服务器造成压力,页面效果也不好
使用到的方法介绍:
drawImage()
方法在画布上绘制图像、画布或视频;也能够绘制图像的某些部分,以及/或者增加或减少图像的尺寸
context.drawImage(img, x, y)
:在画布上定位图像context.drawImage(img, x, y, width, height)
:在画布上定位图像,并规定图像的宽高context.drawImage(img, sx, sy, swidth, sheight, x, y, width, height)
:剪切图像,并在画布上定位被剪切的部分参数说明:
img
:规定要使用的图像、画布或视频x
:在画布上放置图像的x坐标位置y
:在画布上放置图像的y坐标位置width
:要使用的图像的宽 — 伸展或缩小(可选)height
:要使用的图像的高 — 伸展或缩小(可选)sx
:开始剪切的x坐标(可选)sy
:开始剪贴的y坐标(可选)swidth
:被剪切图像的宽(可选)sheight
:被剪切图像的高(可选)
toDataURL(type, encoderOptions)
将canvas对象转换为base64编码
type
指定转换为base64编码后图片的格式,如:image/png、image/jpeg、image/webp等,默认是image/png格式;encoderOptions
用于设置转换为base64编码后图片的质量,取值范围为0-1,超出取值范围用默认值0.92代替;
canvas.toBlob(callback, type, encoderOptions)
创造Blob对象,用以展示canvas上的图片;如不特别指明,图片的类型默认为 image/png,分辨率为96dpi
callback
:回调函数,可获取一个单独的Blob对象type
:指定图片的格式,默认是image/pngencoderOptions
:Number类型,取值在0-1之间,当请求图片格式为image/jpeg或者image/webp时,用来指定图片质量;如果不在这个范围之间取值,则使用默认值,其余参数忽略
具体实现如下:
// 通过创建canvas重新设置图像宽高实现压缩
export const getCompressFile = function (file) {
return new Promise((resolve, reject) => {
// 创建一个读取文件的对象
let reader = new FileReader()
// 读取图像文件
reader.readAsDataURL(file)
reader.onload = function (e) {
// 新建一个img标签(不嵌入DOM节点,仅做canvas操作)
let image = new Image()
// 把原图赋给img标签
image.src = e.target.result
image.onload = function () {
// 创建一个canvas元素
let canvas = document.createElement('canvas'),
context = canvas.getContext('2d'),
// 差不多是压缩了四分之一
imageWidth = image.width / 2, // 压缩后图片的宽度
imageHeight = image.height / 2, // 压缩后图片的高度
comFile = '' // 存储压缩后的图片
canvas.width = imageWidth // 设置画布的宽
canvas.height = imageHeight // 设置画布的高
// 重新设置img标签中的图片大小,实现压缩
context.drawImage(image, 0, 0, imageWidth, imageHeight)
// 将canvas上图片转换为base64格式 --- 1.0是图片的质量,一般在0-1之前取值,值越小图片质量越差
comFile = canvas.toDataURL('image/jpeg', 1.0)
canvas.toBlob(function (blob) {
const fd = new File([blob], file.name, { type: 'image/jpeg' })
console.log('图片压缩后文件信息', fd)
resolve(fd)
}, 'image/jpeg')
}
}
})
}
挂载到全局:
import getCompressFile from '@/utils/public/common'
Vue.prototype.compressFile = getCompressFile
页面调用:
<van-uploader
v-model="updateFile"
multiple
:max-count="10"
:before-read="beforeRead"
>
<van-button icon="plus" type="default"></van-button>
</van-uploader>
beforeRead(file){
return this.compressFile(file, false)
},