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 格式,体积更小、兼容性更好
相关推荐
还是大剑师兰特2 天前
解决nginx错误:http://localhost:7000正常,http://localhost:7000/map 报错404
nginx·大剑师
还是大剑师兰特5 天前
地图的分类
大剑师·地图分类
还是大剑师兰特16 天前
ruoyi‑vue3 添加【车辆管理】菜单组完整方案
大剑师·若依系统
还是大剑师兰特20 天前
若依(ruoyi)前后台系统从零到一部署配置(坑点带解析)
大剑师
还是大剑师兰特20 天前
ideaIC‑2024.1.7(社区版zip绿色解压版)完整使用教程
大剑师·idealc
还是大剑师兰特22 天前
MySQL8.0 Windows完整安装教程
windows·mysql·大剑师
还是大剑师兰特2 个月前
VSCode 插件冲突导致崩溃、卡死、假死 全套根治方案
vscode·大剑师
还是大剑师兰特2 个月前
ThinkPad T490 Windows 自动修复失败完整解决步骤
windows·大剑师·t490
还是大剑师兰特2 个月前
二年级奥数(12) : 巧填符号+竖式数字谜
大剑师·二年级奥数
还是大剑师兰特2 个月前
二年级奥数(9):鸡兔同笼+ 归一问题
大剑师·二年级奥数