canvas需通过filereader读取本地图片为data url或imagebitmap后绘制编辑,流程为选文件→读取→解码→绘制→编辑→导出;缩放旋转用ctx变换,涂鸦用路径绘制,滤镜改像素;导出推荐toblob异步处理,大图应缩略交互、原图导出。

Canvas 本身不直接读取本地文件,需借助 FileReader 将用户选择的图片文件转为可绘制的数据(如 data URL 或 ImageBitmap),再加载到 Canvas 上进行编辑。核心流程是:选文件 → 读取 → 解码 → 绘制 → 编辑(缩放、旋转、涂鸦、滤镜等)→ 导出。
1. 获取并加载本地图片到 Canvas
通过 <input type="file"> 获取文件,用 FileReader 读取为 data URL,再创建 Image 对象,在其 onload 中绘制到 Canvas:
注意:必须等图片加载完成(img.onload)再调用 drawImage,否则 Canvas 为空。
- 使用
FileReader.readAsDataURL(file)最简单,兼容性好 - 也可用
readAsArrayBuffer+createImageBitmap(更高效,支持 WebP/AVIF,但需检查浏览器支持) - Canvas 宽高建议按图片原始尺寸设置(
canvas.width = img.naturalWidth),避免拉伸失真
2. 基础编辑操作实现方式
所有编辑都基于对 Canvas 2D 上下文的操作,不修改原始图片数据,而是实时重绘:
-
缩放/平移:用
ctx.save()+ctx.translate()+ctx.scale()+ctx.drawImage()组合,保存变换状态便于复位 -
旋转:以图片中心为原点,先
translate(centerX, centerY),再rotate(radians),再反向 translate 回去,最后绘制 -
涂鸦(自由绘图):监听
mousedown/mousemove/mouseup,用lineTo()+stroke()在临时图层(或同一 Canvas)上绘制路径 -
简单滤镜(如灰度):用
ctx.getImageData()获取像素,遍历修改 RGBA 值(例如avg = (r+g+b)/3; r=g=b=avg),再用ctx.putImageData()写回
3. 保存编辑结果
编辑完成后,调用 canvas.toDataURL('image/png') 或 canvas.toBlob() 获取结果:
-
toDataURL()返回 base64 字符串,适合小图或快速预览;大图可能触发内存警告 -
toBlob(callback, type, quality)更推荐(尤其导出 JPEG),异步执行,不阻塞主线程,且质量可控(quality0.1–1.0) - 导出为文件:用
URL.createObjectURL(blob)创建临时链接,模拟点击下载
4. 注意事项与优化建议
本地图片编辑易忽略性能和体验细节:
- 大图(如手机拍摄)直接全尺寸绘制会卡顿,建议加载时生成缩略图用于交互,导出时再用原始分辨率重绘
- 频繁调用
getImageData/putImageData性能较差,滤镜类操作可用OffscreenCanvas(需支持)或 WebGL 加速 - 撤销/重做可用“快照栈”:每次关键编辑后调用
canvas.toDataURL()存入数组(慎用,占内存),或记录操作指令(更省内存) - 移动端需处理
touchstart/touchmove替代 mouse 事件,并防止页面滚动(e.preventDefault())
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











