【vue+el-upload+vue-cropper】vue图片上传,vue-cropper图片裁剪后上传

news2024/11/17 7:56:30

在这里插入图片描述

一. 先看效果演示

在这里插入图片描述

二. 图片上传

用的el-upload加el-image组件
html部分

<el-dialog>
...//无关代码已省略
	<div v-for="item in imgArr" :key="item.index">
      <span>{{ item.name }}</span>
      <el-upload action="#" list-type="picture-card" :on-change="onChange.bind(null, item.index)" :auto-upload="false" :file-list="item.fileList" :class="{ hide: item.hideUpload }">
          <i slot="default" class="el-icon-plus"></i>
          <div slot="file" slot-scope="{ file }">
            <el-image class="el-upload-list__item-thumbnail" :src="item.aimgSrc" alt="" :onerror="defaultImg" :preview-src-list="item.fileList"></el-image>
            <span class="el-upload-list__item-actions">
            	// 预览按钮
              <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
                <i class="el-icon-zoom-in"></i>
              </span>
              	// 删除按钮
              <span class="el-upload-list__item-delete" @click="handleRemove(file, item.index)">
                <i class="el-icon-delete"></i>
              </span>
              	// 裁剪按钮
              <span v-if="item.index == 6" class="el-upload-list__item-delete" @click="beforeCrop(file)">
                <i class="el-icon-scissors"></i>
              </span>
            </span>
          </div>
        </el-upload>
	</div>
</el-dialog>
....

注释:
el-upload
:on-change=“onChange.bind(null, item.index)” 不加.bind会报错,
:auto-upload=“false” 表示不自动上传,也就是手动上传
:file-list=“item.fileList” 上传的图片列表,数组对象格式[{url:xxxx}]
:class=“{ hide: item.hideUpload }” 到el-image使用,上传完后影藏那个加号和虚线框

el-image
:οnerrοr=“defaultImg” 图片加载失败,报错时候的默认图片.
:preview-src-list=“item.fileList” 预览的图片列表,同:file-list=“item.fileList”

预览,删除,裁剪,三个按钮,目前功能与预览无关,预览功能有空再另写吧

js部分


      imgArr: [
        // aimgFile调接口, aimgSrc回显, hideUpload影藏加号, fileList预览大图
        { index: 0, name: '图片A:', aimgFile: '', aimgSrc: '', hideUpload: false, fileList: [] },
        { index: 1, name: '图片A:', aimgFile: '', aimgSrc: '', hideUpload: false, fileList: [] },
        { index: 2, name: '图片A:', aimgFile: '', aimgSrc: '', hideUpload: false, fileList: [] },
        { index: 3, name: '图片A:', aimgFile: '', aimgSrc: '', hideUpload: false, fileList: [] },
        { index: 4, name: '图片A:', aimgFile: '', aimgSrc: '', hideUpload: false, fileList: [] },
        { index: 5, name: '图片A:', aimgFile: '', aimgSrc: '', hideUpload: false, fileList: [] },
        { index: 6, name: '图片A:', aimgFile: '', aimgSrc: '', hideUpload: false, fileList: [] },
      ],
      files :'', //裁剪图片的标记
      
    // 上传图片 index 图片下标 file图片内容 flag裁剪图片的标记
    onChange(index, file, flag) {
      this.files = file.raw
      const isJPG = file.raw.type === 'image/jpeg' || file.raw.type == 'image/png'
      const isLt2M = file.raw.size / 1024 / 1024 < 2
      if (!isJPG) {
        this.$message.error('上传图片只能是 JPG 或 PNG 格式!')
        this.handleRemove(file.raw, index)
        return
      }
      if (!isLt2M) {
        this.$message.error('上传图片大小不能超过 2MB!')
        this.handleRemove(file.raw, index)
        return
      }
      // 上传图片
      const fileData = new FormData()
      fileData.append('imgFile', file.raw)
      fileData.append('imgType', 1)
      // 调接口
      doctorAccessoryUpload(fileData).then((res) => {
        if (res) {
          this.imgArr[index].hideUpload = true
          this.imgArr[index].aimgSrc = file.url
          this.imgArr[index].aimgFile = res.result
          // 裁剪后上传
          if (flag === 1) this.imgArr[index].fileList = [{ url: file.url }]
        } else {
          this.handleRemove(file.raw, index)
        }
      })
    },
    // 删除上传图片
    handleRemove(file, index) {
      this.imgArr[index].aimgSrc = ''
      this.imgArr[index].aimgFile = ''
      this.imgArr[index].fileList = []
      this.imgArr[index].hideUpload = false
    },
三. 裁剪图片

下载vueCropper插件

	npm i vue-cropper --save  // 我的版本是^0.6.4

另起一个dialog

      <!-- 图片裁剪 -->
      <el-dialog title="图片裁剪" :visible.sync="cropDialog" width="40%" :modal="true" :close-on-click-modal="false" center @close="cropCancles" v-dialogDrag>
        <div class="cropBox">
          <template>
            <div>
              <vueCropper
                @mouseenter.native="enter"
                @mouseleave.native="leave"
                ref="cropper"
                :img="option.uploadImg"
                :outputSize="option.size"
                :outputType="option.outputType"
                :info="true"
                :full="option.full"
                :canMove="option.canMove"
                :canMoveBox="option.canMoveBox"
                :original="option.original"
                :autoCrop="option.autoCrop"
                :fixed="option.fixed"
                :fixedNumber="option.fixedNumber"
                :centerBox="option.centerBox"
                :infoTrue="option.infoTrue"
                :fixedBox="option.fixedBox"
              ></vueCropper>
            </div>
          </template>
          <div>
            <img :src="cropImg" alt="" />
          </div>
        </div>
        <div slot="footer">
          <el-button @click="cropCancles">取 消</el-button>
          <el-button type="primary" @click="cropConfirm">裁剪图片</el-button>
        </div>
      </el-dialog>
      <script>
      import { VueCropper } from 'vue-cropper'
      export default {
  		components: { VueCropper },
  		data() {
		    return {
	          cropDialog: false,
		      option: {
		        uploadImg: '', // 原图地址
		        info: true, // 裁剪框的大小信息
		        outputSize: 1, // 裁剪生成图片的质量
		        outputType: 'jpeg', // 裁剪生成图片的格式
		        canScale: true, // 图片是否允许滚轮缩放
		        autoCrop: true, // 是否默认生成截图框
		        fixedBox: true, // 固定截图框大小 不允许改变
		        fixed: true, // 是否开启截图框宽高固定比例
		        fixedNumber: [3, 4], // 截图框的宽高比例
		        full: false, // 是否输出原图比例的截图
		        canMove: true, //是否可以移动原图
		        canMoveBox: true, // 截图框能否拖动
		        original: false, // 上传图片按照原始比例渲染
		        centerBox: true, // 截图框是否被限制在图片里面
		        infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
		      },
		      cropImg: require('../../public/img/default.png'),
			}
		}
		  //开始裁剪
	    enter() {
	      if (this.option.uploadImg == '') {
	        return
	      }
	      this.$refs.cropper.startCrop()
	    },
	    //停止裁剪
	    leave() {
	      this.$refs.cropper.stopCrop()
	      this.$refs.cropper.getCropData((data) => {
	        this.cropImg = data
	      })
	    },
	    // 裁剪前
	    beforeCrop(file) {
	      this.option.uploadImg = file.url
	      this.cropDialog = true
	      setTimeout(() => {
	        this.$refs.cropper.getCropData((data) => {
	          this.cropImg = data
	        })
	      }, 500)
	    },
	    // 确认裁剪
	    cropConfirm() {
	      //获取截图的base64格式数据
	      this.$refs.cropper.getCropData((data) => {
	        this.cropImg = data
	        this.handleRemove(this.files, this.imgArr.length - 1)
	        this.cropCancles()
	        setTimeout(() => {
	          this.onChange(this.imgArr.length - 1, { raw: this.dataURLtoFile(data, 'Default.jpg'), url: data }, 1)
	        }, 1000)
	      })
	    },
	    // 取消裁剪
	    cropCancles() {
	      this.cropDialog = false
	      this.option.uploadImg = ''
	      this.cropImg = require('../../public/img/default.png')
	    },
	    // base64转file
	    dataURLtoFile(dataurl, filename) {
	      let arr = dataurl.split(',')
	      let mime = arr[0].match(/:(.*?);/)[1]
	      let bstr = atob(arr[1])
	      let n = bstr.length
	      let u8arr = new Uint8Array(n)
	      while (n--) {
	        u8arr[n] = bstr.charCodeAt(n)
	      }
	      return new File([u8arr], filename, { type: mime })
	    },
	  }
      </script>

ok 结束了,记录一下

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

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

相关文章

【408】计算机学科专业基础 - 数据结构

数据结构知识 绪论 数据结构在学什么 如何用程序代码把现实世界的问题信息化 如何用计算机高效地处理这些信息从而创造价值 数据结构的基本概念 什么是数据&#xff1a; 数据是信息的载体&#xff0c;是描述客观事物属性的数、字符及所有能输入到计算机中并被计算机程序…

K8S知识点(十)

&#xff08;1&#xff09;Pod详解-启动命令 创建Pod&#xff0c;里面的两个容器都正常运行 &#xff08;2&#xff09;Pod详解-环境变量 &#xff08;3&#xff09;Pod详解-端口设置 &#xff08;4&#xff09;Pod详解-资源配额 修改&#xff1a;memory 不满足条件是不能正常…

揭秘:车企如何利用5R模式在数位行销领域取得突破

01 车企进入“大逃杀”时间 汽车行业一边是出口“捷报频传”&#xff0c;一边是内销“压力山大”。 内销的难&#xff0c;在之前中部某省的政府“骨折价”补贴掀起的“价格战”中已经可见一斑。这一颇具标志性的事件反映了汽车行业&#xff0c;尤其是燃油车行业正处在巨大的转…

曾被揭露造假的越南,再次宣称研发成功5G芯片,这是真的么?

日前在2023 年越南国际创新展 (VIIE 2023) 上&#xff0c;越南的Viettel宣布成功研发5G芯片&#xff0c;可以应用于5G基站&#xff0c;并表示该公司已成为全球第六大芯片设备供应商。 越南是近10年来制造业发展强劲的国家之一&#xff0c;甚至还在2022年成为全球经济增长最快的…

C#多线程入门概念及技巧

C#多线程入门概念及技巧 一、什么是线程1.1线程的概念1.2为什么要多线程1.3线程池1.4线程安全1.4.1同步机制1.4.2原子操作 1.5线程安全示例1.5.1示例一1.5.2示例二 1.6C#一些自带的方法实现并行1.6.1 Parallel——For、ForEach、Invoke1.6.1 PLINQ——AsParallel、AsSequential…

TSINGSEE视频智能分析人员入侵AI检测算法如何让城市管理更加高效、智慧?

在城市管理场景中&#xff0c;经常面临着禁区垂钓、非法捕捞、行人闯红灯、小区盗窃、车辆乱停乱放等一系列管理难题&#xff0c;这给城市发展带来了不小的阻力&#xff0c;同时也极易增加管理的人力、物力和财力。传统的人员巡逻监管效率低并且存在时间差&#xff0c;很难及时…

2.4.0 Milky Way 强势登场!新功能大爆炸,让你High翻全场!

Yo开发达人们&#xff0c;我们有重磅新功能要给你们放送啦&#xff01; Check it out 数据汇总不再单调&#xff0c;新的聚合函数登场&#xff01; compact_state_agg #1359gauge_agg #1370first #1395last #1413mode #1440increase #1476delta #1395time_delta #1405rate #14…

内存映射:PS和PL DDR3的一些区别

之前写的一些资料&#xff1a; PS与PL互联与SCU以及PG082-CSDN博客 参考别人的资料&#xff1a; PL读写PS端DDR的设计_pl读写ps端ddr数据-CSDN博客 xilinx sdk、vitis查看地址_vitis如何查看microblazed地址_yang_wei_bk的博客-CSDN博客 可见&#xff0c;PS端的DDR3需要从…

从0到1实现一个前端监控系统(附源码)

目录 一、从0开始 二、上报数据方法 三、上报时机 四、性能数据收集上报 收集上报FP 收集上报FCP 收集上报LCP 收集上报DOMContentLoaded 收集上报onload数据 收集上报资源加载时间 收集上报接口请求时间 五、错误数据收集上报 收集上报资源加载错误 收集上报js错…

msvcp120.dll丢失的6种解决方法,教你如何修复dll文件丢失

“找不到msvcp120dll,无法继续执行代码的6个修复方案”。我相信很多朋友在运行某些程序时&#xff0c;可能会遇到这样的错误提示&#xff1a;“找不到msvcp120dll&#xff0c;无法继续执行代码”。那么&#xff0c;msvcp120dll究竟是什么&#xff1f;为什么会丢失呢&#xff1f…

Java基础知识第四讲:Java 基础 - 深入理解泛型机制

Java 基础 - 深入理解泛型机制 背景&#xff1a;Java泛型这个特性是从JDK 1.5才开始加入的&#xff0c;为了兼容之前的版本&#xff0c;Java泛型的实现采取了“伪泛型”的策略&#xff0c;即Java在语法上支持泛型&#xff0c;但是在编译阶段会进行所谓的“类型擦除”&#xff0…

NestJS——基于Node.js 服务器端应用程序的开发框架

文章目录 前言什么是 NestJS&#xff1f; 一、NestJS特性&#xff1f;二、使用步骤Typescript 知识后端开发基本知识新建项目目录结构 前言 Nestjs中文文档 什么是 NestJS&#xff1f; Nest (NestJS) 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的开发框架。它利用…

【JVM系列】- 寻觅·方法区的内容

寻觅方法区的内容 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f31d;分享学习心得&#xff0c;欢迎指正&#xff0c;大家一起学习成长&#xff01; 文章目录 寻觅…

杂记 | 使用FRP搭建内网穿透服务(新版toml配置文件,搭配反向代理食用)

文章目录 01 需求与回顾02 下载程序包03 编辑.toml文件3.1 编辑frps.toml3.2 编辑frpc.toml 04 启动服务4.1 启动服务端4.2 启动客户端 05 配置反向代理&#xff08;可选&#xff09;06 windows设置为默认启动&#xff08;可选&#xff09;6.1 创建启动脚本6.2 设置为开机自启 …

【Spring Cloud】声明性REST客户端:Feign

Spring Cloud Feign ——fallback 服务降级 1. Feign 简介2. Feign 的基础使用2.1 普通 HTTP 请求2.2 Feign 远程调用上传文件接口 1. Feign 简介 Feign 是一个声明式的 HTTP 客户端&#xff0c;它简化了编写基于 REST 的服务间通信代码的过程。在 Spring Cloud 中&#xff0c…

你一定要学会的Java语法 -- 【继承】

书接上回&#xff0c;我们已经学完了类和对象&#xff0c;今天内容可能有一点难&#xff0c;相信自己能跨过这道坎。 目录 一. 继承 1.什么是继承 2. 继承的概念 3. 继承的语法 4.父类成员访问 子类和父类成员变量同名 子类和父类成员方法同名 5.super关键字 6.子类构…

POJ 3254 Corn Fields 状态压缩DP(铺砖问题)

一、题目大意 我们要在N * M的田地里种植玉米&#xff0c;有如下限制条件&#xff1a; 1、对已经种植了玉米的位置&#xff0c;它的四个相邻位置都无法继续种植玉米。 2、题目中有说一些块无论如何&#xff0c;都无法种植玉米。 求所有种植玉米的方案数&#xff08;不种植也…

Vector - CANoe - Vector Hardware Manager基础介绍

经常使用CANoe的人都知道&#xff0c;我们之前使用配置VN系列硬件通道的时候使用的是Vector Hardware Config&#xff0c;非常的方便&#xff0c;不过在Vector Driver Setup驱动版本大于22.14后&#xff0c;为了更好的适用车载以太网相关的配置&#xff0c;以及各个配置之间继承…

kubenetes-kubelet组件

一、kubelet架构 每个节点都运行一个kubelet进程&#xff0c;默认监听10250端口&#xff0c;kubelet作用非常重要&#xff0c;是节点的守护神。 接收并执行 master发来的指令。管理Pod及Pod中的容器。每个kubelet进程会在API Server 上注册节点自身信息&#xff0c;定期向mast…

Java学习_对象

对象在计算机中的执行原理 类和对象的一些注意事项 this关键字 构造器 构造器是一种特殊的方法 : 特殊之处在于&#xff0c;名字必须与所在类的名字一样&#xff0c;而且不能写返回值类型 封装 封装的设计规范&#xff1a;合理隐藏、合理暴露 实体类 成员变量和局部变量的区别 …