Vue3中vue-cropper详解与使用示例

文章目录

      • [一、安装(Vue 3 专用)](#一、安装(Vue 3 专用))
      • [二、核心 API 说明](#二、核心 API 说明)
        • [1. 常用 Props(配置项)](#1. 常用 Props(配置项))
        • [2. 常用事件](#2. 常用事件)
        • [3. 常用方法(通过 ref 调用)](#3. 常用方法(通过 ref 调用))
      • [三、Vue 3 完整示例(Composition API)](#三、Vue 3 完整示例(Composition API))
        • [1. 组件代码(直接复制可用)](#1. 组件代码(直接复制可用))
      • 四、全局引入(可选)
      • 五、常见场景与技巧
      • [六、TypeScript 支持](#六、TypeScript 支持)
      • 七、总结

vue-cropper 是一款专为 Vue 设计的轻量级图片裁剪组件,支持实时预览、旋转、缩放、固定比例、自动裁剪 等核心功能。在 Vue 3 中需安装 @next 版本,以下是完整详解与可直接运行的示例。


一、安装(Vue 3 专用)

bash 复制代码
# npm
npm install vue-cropper@next --save

# yarn
yarn add vue-cropper@next

# pnpm
pnpm add vue-cropper@next

二、核心 API 说明

1. 常用 Props(配置项)
属性 类型 默认 说明
img String - 图片地址(URL / Base64)
outputSize Number 1 输出质量(0-1)
outputType String 'jpeg' 格式:jpeg / png / webp
autoCrop Boolean false 是否自动生成裁剪框
autoCropWidth Number 200 自动裁剪宽度
autoCropHeight Number 200 自动裁剪高度
fixed Boolean false 是否固定裁剪比例
fixedNumber Array [] 固定宽高比,如 [1,1](正方形)
canScale Boolean true 能否鼠标滚轮缩放
canMove Boolean true 能否移动图片
canMoveBox Boolean true 能否拖动裁剪框
2. 常用事件
  • @realTime:实时裁剪触发(返回预览数据)
  • @imgLoad:图片加载完成
  • @cropMove:裁剪框移动时
3. 常用方法(通过 ref 调用)
javascript 复制代码
// 旋转
cropper.value.rotateRight() // 右旋转90°
cropper.value.rotateLeft()  // 左旋转90°

// 缩放
cropper.value.changeScale(1)  // 放大
cropper.value.changeScale(-1) // 缩小

// 获取结果
cropper.value.getCropData((data) => {
  // data = Base64
})

cropper.value.getCropBlob((blob) => {
  // blob = 二进制(上传用)
})

三、Vue 3 完整示例(Composition API)

1. 组件代码(直接复制可用)
vue 复制代码
<template>
  <div class="cropper-demo">
    <h3>Vue3 + vue-cropper 图片裁剪</h3>

    <!-- 上传选择图片 -->
    <input
      type="file"
      accept="image/*"
      @change="handleFileChange"
      class="file-input"
    />

    <!-- 裁剪组件 -->
    <div class="cropper-box" v-if="options.img">
      <vue-cropper
        ref="cropper"
        :img="options.img"
        :output-size="options.outputSize"
        :output-type="options.outputType"
        :auto-crop="options.autoCrop"
        :auto-crop-width="options.autoCropWidth"
        :auto-crop-height="options.autoCropHeight"
        :fixed="options.fixed"
        :fixed-number="options.fixedNumber"
        :can-scale="options.canScale"
        @real-time="realTimePreview"
        style="width: 100%; height: 400px; border: 1px solid #eee;"
      />
    </div>

    <!-- 工具栏 -->
    <div class="tool-bar" v-if="options.img">
      <button @click="rotateLeft">↺ 左旋转</button>
      <button @click="rotateRight">↻ 右旋转</button>
      <button @click="zoomIn">+ 放大</button>
      <button @click="zoomOut">- 缩小</button>
      <button @click="getCropBase64">✅ 获取Base64</button>
      <button @click="getCropBlob">✅ 获取Blob</button>
    </div>

    <!-- 预览区 -->
    <div class="preview-wrapper" v-if="previewUrl">
      <h4>裁剪预览</h4>
      <img :src="previewUrl" class="preview-img" />
    </div>
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue'
// 引入组件与样式
import 'vue-cropper/dist/index.css'
import { VueCropper } from 'vue-cropper'

const cropper = ref(null)

// 配置项
const options = reactive({
  img: '',                  // 图片
  outputSize: 1,            // 质量
  outputType: 'jpeg',       // 格式
  autoCrop: true,           // 自动裁剪
  autoCropWidth: 200,
  autoCropHeight: 200,
  fixed: true,              // 固定比例
  fixedNumber: [1, 1],      // 1:1 正方形(头像)
  canScale: true            // 允许缩放
})

const previewUrl = ref('')

// 选择本地图片
const handleFileChange = (e) => {
  const file = e.target.files[0]
  if (!file) return
  const reader = new FileReader()
  reader.onload = (ev) => {
    options.img = ev.target.result
  }
  reader.readAsDataURL(file)
}

// 实时预览
const realTimePreview = (data) => {
  previewUrl.value = data.url
}

// 旋转
const rotateLeft = () => cropper.value.rotateLeft()
const rotateRight = () => cropper.value.rotateRight()

// 缩放
const zoomIn = () => cropper.value.changeScale(1)
const zoomOut = () => cropper.value.changeScale(-1)

// 获取 Base64
const getCropBase64 = () => {
  cropper.value.getCropData((data) => {
    console.log('Base64:', data)
    alert('Base64 已输出到控制台')
  })
}

// 获取 Blob(用于上传)
const getCropBlob = () => {
  cropper.value.getCropBlob((blob) => {
    console.log('Blob:', blob)
    alert('Blob 已输出到控制台(可直接上传)')
  })
}
</script>

<style scoped>
.cropper-demo {
  max-width: 800px;
  margin: 20px auto;
  padding: 20px;
}
.file-input {
  margin: 10px 0;
}
.tool-bar {
  margin: 15px 0;
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.tool-bar button {
  padding: 6px 12px;
  cursor: pointer;
}
.preview-img {
  width: 200px;
  height: 200px;
  object-fit: cover;
  border: 1px solid #ddd;
}
</style>

四、全局引入(可选)

main.js 中全局注册,所有组件可直接使用:

javascript 复制代码
import { createApp } from 'vue'
import App from './App.vue'
import VueCropper from 'vue-cropper'
import 'vue-cropper/dist/index.css'

const app = createApp(App)
app.use(VueCropper)
app.mount('#app')

五、常见场景与技巧

  1. 头像裁剪(正方形固定比例)

    javascript 复制代码
    fixed: true,
    fixedNumber: [1, 1]
  2. 封面图(16:9)

    javascript 复制代码
    fixed: true,
    fixedNumber: [16, 9]
  3. 禁止移动/缩放

    javascript 复制代码
    canMove: false,
    canScale: false,
    canMoveBox: false
  4. 上传服务器(Blob 方式推荐)

    javascript 复制代码
    const formData = new FormData()
    cropper.value.getCropBlob((blob) => {
      formData.append('avatar', blob, 'avatar.jpg')
      // axios.post('/api/upload', formData)
    })

六、TypeScript 支持

如遇类型缺失,可在项目根目录创建 vue-cropper.d.ts

typescript 复制代码
declare module 'vue-cropper' {
  import type { DefineComponent } from 'vue'
  const VueCropper: DefineComponent<any, any, any>
  export { VueCropper }
}

七、总结

  • Vue 3 必须安装 vue-cropper@next
  • 核心流程:选择图片 → 裁剪配置 → 实时预览 → 获取 Base64 / Blob → 上传
  • 常用功能:固定比例、旋转、缩放、自动裁剪
  • 上传推荐使用 Blob 格式,体积更小、兼容性更好
相关推荐
还是大剑师兰特1 天前
Terser.js 详解与 Vue3 项目实战配置
大剑师·terser
还是大剑师兰特8 天前
接口参数:Query、Body、Path 区别 + 完整参数类型
大剑师·接口参数
还是大剑师兰特9 天前
RESTful 接口 + 实际开发通用规范
restful·大剑师
还是大剑师兰特10 天前
EventBus核心方法用法
javascript·vue.js·大剑师
还是大剑师兰特10 天前
vite-plugin-svg-icons作用详解
大剑师·svg-icons
还是大剑师兰特10 天前
vitejs/plugin-legacy 作用与使用方法
vite·大剑师
还是大剑师兰特13 天前
gzip,brotliCompress,deflate三种压缩算法对比,vue3最适合用哪种
大剑师·压缩算法
还是大剑师兰特23 天前
Stats.js 插件详解及示例(完全攻略)
前端·大剑师·stats
还是大剑师兰特1 个月前
Vue3 权限系统(Pinia + 登录接口 + 权限刷新 + 路由守卫 )
大剑师