图片压缩
作者:Yuan Tang
更新于:5 个月前
字数统计:1.1k 字
阅读时长:4 分钟
前置知识
第三方库
file-saver
,其 saveAs
方法用于获取并保存 blob
等格式的图片。
Canvas
使用 drawImage
绘制图片,语法如下:
js
context.drawImage(image, dx, dy)
context.drawImage(image, dx, dy, dWidth, dHeight)
context.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
参数解释:
参数 | 含义 |
---|---|
image | 要绘制的图像,可以是 <img> 元素、<canvas> 元素或 Image 对象。 |
sx(可选) | 图像剪裁的起始点 x 坐标。 |
sy(可选) | 图像剪裁的起始点 y 坐标。 |
sWidth(可选) | 图像剪裁的宽度。 |
sHeight(可选) | 图像剪裁的高度。 |
dx | 绘制图像的起始点 x 坐标。 |
dy | 绘制图像的起始点 y 坐标。 |
dWidth(可选) | 绘制图像的宽度。 |
dHeight(可选) | 绘制图像的高度。 |
下面是几个示例,展示了如何使用 drawImage
方法:
js
const canvas = document.getElementById('myCanvas')
const ctx = canvas.getContext('2d')
// 例子1: 在画布上绘制一个图像
const image = new Image()
image.src = 'image.png'
image.onload = function () {
ctx.drawImage(image, 0, 0)
}
// 例子2: 绘制图像的一部分,并指定目标宽度和高度
ctx.drawImage(image, 10, 10, 50, 50, 100, 100, 50, 50)
// 例子3: 使用剪裁区域绘制图像
ctx.drawImage(image, 20, 20, 100, 100, 0, 0, 50, 50)
注意
如果图像还没有加载完成,绘制操作可能不会生效,因此你需要使用
onload
事件或其他方式确保图像加载完成后再进行绘制。
toBlob()
是 <canvas>
元素上的一个方法,用于将当前画布内容转换为一个 Blob 对象, Blob 对象可以用于各种用途,例如上传到服务器或保存为本地文件。
通过 canvas
中的 toBlob()
转换为一个 Blob 对象,基本语法如下所示:
js
canvas.toBlob(callback, type, quality)
参数解释:
参数 | 含义 |
---|---|
callback | 转换完成后的回调函数,用来接收生成的 Blob 对象作为参数。 |
type(可选) | 指定生成的 Blob 对象的 MIME 类型,默认为 image/png 。 |
quality(可选) | 指定生成的 Blob 对象的质量参数,仅针对 image/jpeg 和 image/webp 类型的图片有效,范围为 0 到 1,默认为 0.92。 |
以下是一个示例,展示了如何使用 toBlob()
方法将 <canvas>
元素的内容转换为 Blob 对象:
js
const canvas = document.getElementById('myCanvas')
const ctx = canvas.getContext('2d')
// 绘制画布内容
ctx.fillStyle = 'red'
ctx.fillRect(0, 0, 100, 100)
// 将画布内容转换为 Blob 对象
canvas.toBlob((blob) => {
// 在回调函数中处理生成的 Blob 对象
// 可以将它上传到服务器或进行其他操作
}, 'image/png')
在示例中,首先获取到 <canvas>
元素的上下文对象 ctx
,接着使用绘图方法绘制画布内容(这里绘制一个红色的矩形)。然后,使用 toBlob()
方法将画布内容转换为 Blob 对象,并在回调函数中进行处理。
注意
toBlob()
方法是HTML5新增的方法,不是所有的浏览器都支持它。在使用之前,最好检查一下浏览器的兼容性。
获取图片
首先先获取用户选择上传的图片,前端文件上传与相关操作方法复习可点击 前端文件上传与相关操作 。代码如下所示:
vue
<script setup>
import { ref } from 'vue'
const imgUrl = ref('')
function onChangeFn(e) {
// 获取用户上传的文件
const file = e.target.files[0]
// 预览文件
const fr = new FileReader()
fr.readAsDataURL(file)
// 获取图片读完的图片结果(非同步,需要在onload获取)
fr.onload = () => {
imgUrl.value = fr.result
}
}
</script>
<template>
<input type="file" @change="onChangeFn">
<img :src="imgUrl">
</template>
压缩实现
保存运行后,选择图片可以成功渲染到页面上。现在利用 canvas
转 blob
或 DataURL
格式时实现图片压缩。步骤如下:
- 创建一个
canvas
真实 DOM,并获取到图片 DOM 的宽高 - 通过
canvas
的getContext('2d')
方法法创建获取 2D 渲染上下文 - 通过
drawImage()
在<canvas>
元素上绘制图像 - 使用
toBlob()
方法把canvas
DOM 节点转换为一个 Blob 对象 - 把转换好的 blob 对象通过第三方库
file-saver
的saveAs
方法转为图片格式 - 做其他业务处理(如发请求)
js
import { saveAs } from 'file-saver'
function onChangeFn(e) {
const imgRef = ref(null) // img DOM 节点
// ...
fr.onload = () => {
imgUrl.value = fr.result
// 创建canvas真实dom元素
const canvas = document.createElement('canvas')
canvas.height = imgRef.value.height
canvas.width = imgRef.value.width
// 创建2d上下文
const ctx = canvas.getContext('2d')
setTimeout(() => {
ctx.drawImage(imgRef.value, 0, 0, imgRef.value.width, imgRef.value.height)
// 把canvas转为blob格式
canvas.toBlob((blob) => {
// saveAs(blob, 'img.jpeg')
const form = new FormData()
form.append('file', blob)
axios.post('xxx', form)
}, 'image/jpeg', 0.4)
}, 1000)
}
}