封装vue-cropper,图片裁剪组件

news2024/10/9 15:52:51

组件基本使用:

在这里插入图片描述

这里的action同时也可以传相对路径,比如封装了axios,那么组件源码里就不需要引入原生axios,可以替换为封装的axios。传 action="/upload/file"

源代码:

<script setup>
import WuyuCropper from '@/components/wuyu-cropper/index.vue'

function result(data) {
  console.log(data)
}

// 默认头像
const defaultAvatar = 'https://img.yzcdn.cn/vant/cat.jpeg'
</script>

<template>
  <wuyu-cropper @result="result"
                :src="defaultAvatar"
                action="http://localhost:9090/upload/file">
  </wuyu-cropper>
</template>

<style lang="scss" scoped>
</style>

组件属性

名称类型默认值是否必需说明
maxSizeNumber5单位:MB,图片大小限制
fixedNumberArray[1,1]裁剪比例
srcString“”初始化图片回显
actionString#上传接口
headersObject{}请求头

组件事件

名称参数列表说明
result(url)裁剪结束提交后触发该事件,并传递裁剪后的图片url

组件插槽

名称参数列表说明
default自定义按钮,打开裁剪框

组件源码

环境: vue3+element plus+axios+vue-cropper,
可选:vueuse的防抖动函数 useDebounceFn,如果不需要可以去掉

pnpm add vue-cropper@1.1.4 
pnpm add @vueuse/core@11.1.0
<!--可能需要修改 submit函数,根据后端返回值做处理 -->
<script setup>
import {ref} from "vue";
import 'vue-cropper/dist/index.css'
import {VueCropper} from "vue-cropper";
import {useDebounceFn} from "@vueuse/core";
import {ElMessage} from "element-plus";
import axios from "axios";

const emit = defineEmits(['result'])
const prop = defineProps({
  // 单位: MB
  maxSize: {
    type: Number,
    default: 5
  },
  fixedNumber: {
    type: Array,
    default: () => [1, 1]
  },
  src: {
    type: String,
    default: ''
  },
  action: {
    type: String,
    default: '#'
  },
  headers: {
    type: Object,
    default: () => {
    }
  }
})
const cropperRef = ref()
const uploadRef = ref()
const visible = ref(false)
const options = ref({
  img: prop.src, // 图片url
  fixed: true,    // 固定裁剪框大小
  fixedNumber: prop.fixedNumber, // 裁剪框比例
  autoCrop: true,
  filename: getFileName(prop.src)
})
const preview = ref({})
const realTime = useDebounceFn((e) => {
  preview.value = e
}, 500)

// 获取文件名
function getFileName(url) {
  return url.substring(url.lastIndexOf('/') + 1)
}

function open() {
  visible.value = true
  options.value.img = prop.src
  options.value.fixedNumber = prop.fixedNumber
  options.value.filename = getFileName(prop.src)
}

function close() {
  preview.value = {}
  uploadRef.value.clearFiles()
  visible.value = false
}

// 选择文件之前
function beforeUpload(file) {
  if (file.size / 1024 / 1024 > prop.maxSize) {
    ElMessage.error(`文件的大小不能超过:${prop.maxSize}MB`)
    return false
  }
}

// 选择文件之后
function httpRequest({file, filename}) {
  options.value.filename = file.name
  options.value.img = URL.createObjectURL(file)
}

// 提交裁剪文件
function submit() {
  cropperRef.value.getCropBlob(async (data) => {
    const formData = new FormData()
    formData.append('file', data, options.value.filename)
    // 上传文件
    const res = await axios.post(prop.action, formData, {headers: {...prop.headers}})
    // 提交成功,触发result事件,传递url
    emit('result', res.data.data)
    visible.value = false
  })
}

function rotateRight() {
  cropperRef.value.rotateRight()
}

function rotateLeft() {
  cropperRef.value.rotateLeft()
}

function zoomIn() {
  cropperRef.value.changeScale(1)
}

function zoomOut() {
  cropperRef.value.changeScale(-1)
}
</script>

<template>
  <div @click="open">
    <slot>
      <el-button>上传</el-button>
    </slot>
  </div>
  <el-drawer :model-value="visible"
             direction="ttb"
             append-to-body
             size="100%"
             @close="close">
    <template #default>
      <el-row style="height: 80%">
        <el-col :sm="12" class="cropper-box">
          <VueCropper
              ref="cropperRef"
              v-if="visible"
              :img="options.img"
              :fixed="options.fixed"
              :fixed-number="options.fixedNumber"
              :autoCrop="options.autoCrop"
              @realTime="realTime"
          ></VueCropper>
        </el-col>
        <el-col :sm="12" class="preview">
          <div :style="preview.div" class="preview-box">
            <img v-if="preview.url" class="img" :src="preview.url" :style="preview.img"/>
          </div>
        </el-col>
      </el-row>
      <el-row :gutter="10" style="margin-top: 1rem">
        <el-col :sm="1">
          <el-upload action="#"
                     :limit="1"
                     ref="uploadRef"
                     :http-request="httpRequest"
                     :before-upload="beforeUpload"
                     accept=".jpg,.jpeg,.png"
                     :show-file-list="false">
            <template #default>
              <el-button circle type="primary" icon="UploadFilled" title="上传"/>
            </template>
          </el-upload>
        </el-col>
        <el-col :sm="1">
          <el-button circle :disabled="!preview.url" @click="rotateRight" icon="RefreshRight" title="右转"/>
        </el-col>
        <el-col :sm="1">
          <el-button circle :disabled="!preview.url" @click="rotateLeft" icon="RefreshLeft" title="左转"/>
        </el-col>
        <el-col :sm="1">
          <el-button circle :disabled="!preview.url" @click="zoomIn" icon="ZoomIn" title="放大"/>
        </el-col>
        <el-col :sm="3">
          <el-button circle :disabled="!preview.url" @click="zoomOut" icon="ZoomOut" title="缩小"/>
        </el-col>
        <el-col :sm="2">
          <el-button type="success" @click="submit" :disabled="!preview.url">提交</el-button>
        </el-col>
      </el-row>
    </template>
  </el-drawer>
</template>

<style lang="scss" scoped>
.cropper-box {
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.preview {
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;

  .preview-box {
    height: 100%;
    overflow: hidden;

    .img {
      height: 100%;
      width: 100%;
    }
  }
}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2199423.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyTorch单机多卡训练(无废话)

目前大家基本都在使用DistributedDataParallel&#xff08;简称DDP&#xff09;用来训练&#xff0c;该方法主要用于分布式训练&#xff0c;但也可以用在单机多卡。 第一步&#xff1a;初始化分布式环境&#xff0c;主要用来帮助进程间通信 torch.distributed.init_process_g…

Notepad-- 程序员日常用法

一、快速查找标记&#xff0c;提取指定的字符串 1.使用正则表达式查找并标记&#xff0c;将标记的内容复制到新文本中 标记中输入&#xff1a;.*"staffNo": "([^"])".* 这个正则表达式可以匹配整个行&#xff0c;并将 staffNo 后面的内容标记出来。…

修复WordPress .htaccess文件中的常见问题

在搭建WordPress网站时&#xff0c;.htaccess文件非常重要。它可以帮助我们管理网站的重定向、优化URL结构、提高网站安全性等。然而&#xff0c;有时可能会出现由.htaccess文件引起的问题&#xff0c;比如500内部服务器错误、重定向次数过多和文章返回404错误等。本文将详细介…

Hadoop---概念篇

一、Hadoop的组成 二、HDFS架构概述 **1.NameNode(nn): **存储文件的元数据,例如:文件名、文件目录结构、文件属性(生成时间、副本数、文件权限)以及每个文件的块列表和块所在的DateNode等。 **2.DateNode(dn): **在本地文件系统中存储的文件块数据,以及块数据的校验和。 **3.…

后端必备技巧之SQL优化

日常开发中&#xff0c;几乎都免不了和数据库打交道&#xff0c;说到数据库&#xff0c;我们也需要联想这几个问题&#xff1a;我们写的SQL性能怎么样&#xff1f;有没有优化的空间&#xff1f;如何优化&#xff1f;下面我们来介绍关于SQL性能的命令EXPLAIN 什么是EXPLAIN命令&…

智融SW3536DC/DC+快充协议二合一IC

描述 SW3536 是一款高集成度的多快充协议双口充电芯片&#xff0c;支持 AC 口任意口快充输出&#xff0c;支持双口独立限流。其集成了 7A 高效率同步降压变换器&#xff0c;支持 PPS/ PD/ QC/ AFC/ FCP/ SCP/ PE/ SFCP/TFCP 等多种快充协议&#xff0c;支持 140W 输出功率&…

SGDC复位约束找不到信号问题

在使用spyglass编写sgdc时&#xff0c;对一个内部复位信号约束的时候&#xff0c;报信号找不到。 reset -name TOP.BLOCK3.U_TOP2.BLOCK1.U_TOP1.rst -value 0 但是明明get_pins 可以找到此信号。 由于存在generate命令&#xff0c;导致生成的路径比较奇怪&#xff0c;甚至存…

.NET 一款提权工具:Sharp4PetitPotato

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

深入浅出MongoDB(六)

深入浅出MongoDB&#xff08;六&#xff09; 文章目录 深入浅出MongoDB&#xff08;六&#xff09;分析查询性能原子性和事务字段名称带句点和美元符号查询计划 分析查询性能 mongodb compass提供解释计划标签页&#xff0c;其中显示有关查询性能的统计信息。这些统计信息可用…

简历修订与求职经历 - Chap02.

最新的简历&#xff1a; 1.基本信息 姓名 ---- 学历 学位 本科 理学学士 专业 应用物理 智能仪器仪表 性别 男 出生年月 1976/7 电话 ---- 年龄 48 毕业时间 1998/6 电邮 ---- 籍贯 河南洛阳宜阳 居住地 河南郑州高新区 1.1 期望从事职业信息 机械仪器…

泡沫背后:人工智能的虚幻与现实

人工智能的盛世与泡沫 现今&#xff0c;人工智能热潮席卷科技行业&#xff0c;投资者、创业者和用户都被其光环吸引。然而&#xff0c;深入探讨这种现象&#xff0c;人工智能的泡沫正在形成&#xff0c;乃至具备崩溃的潜质。我们看到的&#xff0c;无非是一场由资本推动的狂欢…

双11大促最值得入手的好物是哪些?双11好物种草清单大全分享!

在这个全民狂欢的购物盛宴中&#xff0c;每个人都希望能以最优惠的价格买到心仪已久的好物&#xff0c;随着科技的飞速发展和生活品质的提升&#xff0c;市场上的产品琳琅满目&#xff0c;让人目不暇接&#xff0c;为了帮助大家在这个双11找到真正值得入手的好物&#xff0c;我…

chatGPT模型接口分享

前言: 仅供学习和交流&#xff0c;请合理使用。 API&#xff1a;https://api.gptnet.org key&#xff1a;sk-x9Rmq3HeHh5z9EIi8wFaXCl02OfxRSk5UAFodYm1o4zo5X3i 支持模型&#xff1a;gpt-3.5-turbo、gpt-3.5-turbo-16k、gpt-4o-mini、llama-3.1-405b 暂时支持以上四个模型…

一键生成PPT在线使用的保姆级教程:告别加班就靠它

已经过完24年所有的法定节假日的你&#xff0c;上班状态还好吗&#xff1f; 小编人倒是挺飘忽的&#xff0c;就那种人在工位&#xff0c;魂仍在青青大草原的感觉&#xff0c;都是牛马却失去了自由奔跑的权利...... 尤其是还要面对节前一堆没完成的工作&#xff0c;手动完成不…

基于Jenkins+K8S构建DevOps自动化运维管理平台

目录 1.k8s助力DevOps在企业落地实践 1.1 传统方式部署项目为什么发布慢&#xff0c;效率低&#xff1f; 1.2 上线一个功能&#xff0c;有多少时间被浪费了&#xff1f; 1.3 如何解决发布慢&#xff0c;效率低的问题呢&#xff1f; 1.5 什么是DevOps&#xff1f; 1.5.1 敏…

买电容笔需要注意什么?2024平替电容笔推荐清单,小白必看!

在当今数字化快速发展的时代&#xff0c;电容笔作为一种重要的数字书写和创作工具&#xff0c;正日益受到人们的青睐。然而现在市场上的电容笔品牌繁多&#xff0c;我们还是需要提前了解产品的情况&#xff0c;避免进入到商家的陷阱中。下面我会介绍电容笔的一些避坑知识&#…

关于常见数据库中SQL分页语法整理

标题 MySQL分页查询常规版升级版 Oracle分页查询常规版升级版 PostgreSQL分页查询常规版升级版 SQL Server分页查询常规版升级版 MySQL分页查询 在MySQL中&#xff0c;分页查询通常使用 LIMIT 关键字来实现。 LIMIT [offset,] rows 其中&#xff0c;offset表示偏移量&#xff…

LLMUnity:在Unity 3D中使用大模型

在本文中&#xff0c;我们将展示如何在 Unity 引擎中使用 LLM&#xff08;大型语言模型&#xff09;&#x1f3ae;。我们将使用 LLMUnity 包&#xff0c;并查看一些示例&#xff0c;了解如何仅用几行代码设置对话交互&#xff01; 免责声明&#xff1a;我是 LLMUnity 的作者。…

STM32通用定时器TIM3的PWM输出实验配置步骤

通用定时器 PWM 输出实验 本小节我们来学习使用通用定时器的 PWM 输出模式。 脉冲宽度调制(PWM)&#xff0c;是英文“Pulse Width Modulation”的缩写&#xff0c;简称脉宽调制&#xff0c;是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。我们可以让定时…

Linux 命令 netstat 的 10 个基本用法

Netstat 简介 Netstat 是一款命令行工具&#xff0c;可用于列出系统上所有的网络套接字连接情况&#xff0c;包括 tcp, udp 以及 unix 套接字&#xff0c;另外它还能列出处于监听状态&#xff08;即等待接入请求&#xff09;的套接字。如果你想确认系统上的 Web 服务有没有起来…