用 Vue 如何做图片裁剪功能

2026-09-23 技术分享

后台要头像、活动要封面,图比例不对整页会歪。用 vue create 建好之后,装 Element UI 和裁剪库,做一个弹窗组件:选图、拖框、右侧预览,确定后再把结果交给父页面。

入口是 public/index.html,应用从 src/main.js 挂到 #app。裁剪逻辑在 src/components/CropperImage.vue,App.vue 里引用。先装依赖再 npm run serve,不要指望双击 html 就能跑。

需要哪些依赖

本例按 package.json 装这些包(版本号跟表里走,升级前先看 changelog):

图片1.png

前三个是业务依赖:CropperImage.vue 里局部注册 VueCropper;Element UI 在 main.js 里 Vue.use 一次即可,业务页不用再引一遍。后三个是开发依赖,跟 Vue CLI 一起用,版本不要和 vue 对不上。

装的时候可以写:

图片2.png

如何用 vue create 创建并安装依赖

本机已装 Node 后,用 Vue CLI 建 Vue 2 应用(手里已有的可跳过创建,直接装包):

图片3.png

选 Vue 2、Babel。进目录装裁剪和 UI:

图片4.png

package.json 里脚本保留 vue create 生成时自带的即可:

图片5.png

src/main.js 里挂 Element UI,并引入样式。漏引 css,弹窗和按钮会裸奔。这坑我见过不止一次。

图片6.png

装完执行 npm run serve,浏览器打开本地地址。后面改组件保存会热更新。

如何把裁剪组件接到页面上

把裁剪做成独立组件 src/components/CropperImage.vue,在 App.vue(或业务页)里 import、局部注册,模板里写标签。父页用 @imgUpload 接裁完后的地址。

图片7.png

组件里点「上传图片」把 dialogVisible 设为 true,el-dialog 用 :visible.sync 绑上。:close-on-click-modal="false",裁的时候点到外面不会误关。

图片8.png

「选择图片」用 label 点到隐藏的 file,padding: 9px 15px 撑开,加上 cursor: pointer。裁剪核心是 vue-cropper,ref="cropper" 后面取 blob 要用。

图片9.png

说白了:vue create 把页面跑起来,业务页只负责把组件嵌进去、听一个事件。

如何完成选图裁切与预览

uploadImg 读文件。扩展名不是 gif/jpg/jpeg/png/bmp 就 $message 提示。过关后用 FileReader.readAsArrayBuffer,onload 里转成 blob 地址赋给 option.img,裁剪区才出图。

图片10.png

框大小写在 option:本例宽 657、高 440,fixedBox: true 锁框只拖图。要 1:1 头像改 fixed: true、fixedNumber: [1, 1]。@realTime 把预览数据塞进 previews,右边用 zoom: 400 / previews.w 缩着看。

点确定走 getCropBlob。本例先 createObjectURL 赋给 resultUrl,关弹窗,$emit('imgUpload', url) 通知父页。旧地址要 revokeObjectURL,多裁几次内存才不会涨。我第一次看也卡了一下:这是异步回调,不要在外面同步读 resultUrl。

图片11.png

模板里输出质量绑 outputSize,别写成不存在的 size,否则质量参数没传进去。

如何对接到真实项目中

本地跑通后,确定时不要只停在本地 blob。把数据塞进 FormData,调上传接口,成功用返回的 url 回填并 $emit。提示继续用 Element 的 $message,具体按实际项目来定。

pictureUpload 的路径和字段换成项目约定。下面这份覆盖 CropperImage.vue 里的 getpicture。

图片12.png

父页把 url 赋给头像或封面字段即可。裁剪框宽高、是否固定比例改 option。把这份源码拷进业务仓库后,先 npm i 再 npm run serve;node_modules 不要进压缩包,按 package.json 装。


案例下载
下载demo本地运行
技术分享