Vue3(setup)中使用vue-cropper图片上传裁剪插件,复制代码直接使用

最近在项目中用到上传裁剪,看了一下代码,觉得这插件可可以。梳理了一下代码分享给大家

前端UI组件element-plus

如果你也用到了 ,快速帮你解决了问题,别忘记点赞收藏

1.首先看效果图
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  1. 因为版本vue-cropper 众多 ,虽然网上有各种写法 为了保证能运行 直接copy代码就能用
  2. 直接在package.json中添加依赖 "vue-cropper": "^1.0.9",
  3. 在这里插入图片描述
    然后安装依赖npm install

5 创建一个公用组件

imgcropper.vue

<template>

  <el-dialog
    v-model="isModel"
    title="裁剪图片"
    width="1000px"
    destroy-on-close
    center
    draggable
  >
    <div class="main">
      <div class="tip">
        <div class="tip-text">上传说明"vue-cropper": "^1.0.9"版本</div>
      </div>
      <el-row :gutter="20">
        <el-col span="14">
          <div class="mainbox">
            <vue-cropper
              ref="cropper"
              :img="option.img"
              :outputSize="option.outputSize"
              :outputType="option.outputType"
              :info="option.info"
              :canScale="option.canScale"
              :autoCrop="option.autoCrop"
              :autoCropWidth="option.autoCropWidth"
              :autoCropHeight="option.autoCropHeight"
              :fixed="option.fixed"
              :fixedNumber="option.fixedNumber"
              :full="option.full"
              :fixedBox="option.fixedBox"
              :canMove="option.canMove"
              :canMoveBox="option.canMoveBox"
              :original="option.original"
              :centerBox="option.centerBox"
              :height="option.height"
              :infoTrue="option.infoTrue"
              :maxImgSize="option.maxImgSize"
              :enlarge="option.enlarge"
              :mode="option.mode"
              @realTime="realTime"
             
            >
            </vue-cropper>
            <div class="main-btn">
              <el-button  size="sm" @click="rotateLeft"
                >↺ 向左旋转15°</el-button
              >
              <el-button  size="sm" @click="rotateRight"
                >↻ 向左旋转15°</el-button
              >
              <el-button  size="sm" @click="changeScale(1)"
                ><el-icon type="elui-icon-add-circle" color="#fff"></el-icon
                >+ 放大</el-button
              >
              <el-button  size="sm" @click="changeScale(-1)" >- 缩小</el-button >
              <el-button type="danger" size="sm" @click="changeReset"  >重置</el-button >
             
            </div>
          </div>
        </el-col>
        <el-col span="10">
          <div class="preview-model">
            <div class="preview" style="width: 200px; height: 200px" v-if="previews.url">
         
              <el-image
                lazy
                style="width: 100px; height: 100px"
                :src="previews.url"
                :zoom-rate="1.2"
                :max-scale="7"
                :min-scale="0.2"
                :preview-src-list="srcList"
                :initial-index="4"
                @load="lookImg"
            />
            </div>
            <div class="upload-btn">
              <el-upload v-model="file"  :on-change="selectImg">
                  <el-button type="primary" size="sm">选择图片</el-button>
              </el-upload>
              <el-button type="success" style="margin-left: 10px;" size="sm" @click="uploadFile">确认上传</el-button>
            </div>
          </div>
        </el-col>
      </el-row>
    </div>
  </el-dialog>

</template>
<script setup>
import { ref, reactive ,watch,defineExpose} from "vue";
import { VueCropper } from "vue-cropper";

import "vue-cropper/dist/index.css";
const isModel = ref(false);
const name = ref();
const file = ref();
const previews = ref({});
const previewImg = ref();
const cropper = ref(null);
const emit = defineEmits([""]);

const option = reactive({
  img: "",
  name: "",
  outputSize: 1, //裁剪生成图片的质量(可选0.1 - 1)
  outputType: "png", //裁剪生成图片的格式(jpeg || png || webp)
  info: true, //图片大小信息
  canScale: true, //图片是否允许滚轮缩放
  autoCrop: true, //是否默认生成截图框
  autoCropWidth: 200, //默认生成截图框宽度
  autoCropHeight: 200, //默认生成截图框高度
  fixed: false, //是否开启截图框宽高固定比例
  fixedNumber: [1.53, 1], //截图框的宽高比例
  full: false, //false按原比例裁切图片,不失真
  fixedBox: false, //固定截图框大小,不允许改变
  canMove: true, //上传图片是否可以移动
  canMoveBox: true, //截图框能否拖动
  original: false, //上传图片按照原始比例渲染
  centerBox: true, //截图框是否被限制在图片里面
  height: false, //是否按照设备的dpr 输出等比例图片
  infoTrue: false, //true为展示真实输出图片宽高,false展示看到的截图框宽高
  maxImgSize: 3000, //限制图片最大宽度和高度
  enlarge: 1, //图片根据截图框输出比例倍数
  mode: "100% 100%", //图片默认渲染方式
});

//预览
const srcList = ref([])


//当再次打开时 清空图片
watch(isModel, (val) => {
  if (!val) {
    previews.value = {};
    option.img = ''
    srcList.value = []
  }
});

//实时预览
const realTime = (data) => {
  previews.value = data;
  option.autoCropWidth = data.img.width;
  option.autoCropHeight = data.img.height;
};




//图片缩放
const changeScale = (num) => {
  num = num || 1;
  cropper.value.changeScale(num);
};

// 向左旋转
const rotateLeft = () => {
 cropper.value.rotate = cropper.value.rotate - 15 / 90;
 //直接旋转90度
  cropper.value.rotateLeft()
};

//向右旋转
const rotateRight = () => {
  cropper.value.rotate = cropper.value.rotate + 15 / 90;
  //直接旋转90度
  // cropper.value.rotateRight()
};

// 重置
const changeReset = () => {
  cropper.value.refresh();
};

//图片预览图片
const lookImg = () => {
  cropper.value.getCropBlob((data) => {
    file.value = data;
    let img = window.URL.createObjectURL(data);
    srcList.value.push(img)
  });
};


//选择图片
const selectImg = (e) => {
  //这里需要注意 每个UI组件 返回的数据格式不一样   需要什么取什么
  srcList.value = [];
  option.img = URL.createObjectURL(e.raw);
  option.name = e.raw.name;
 
};

/**
 * @function 确认上传
 *
 * */
const uploadFile = () => {
  cropper.value.getCropBlob((data) => {
    if (data) {
      data.fileName = option.name;
    }
    emit("uploadImgSuccess", data);
  });
};

/**
 * @function 开启弹窗
 * */
const open = () => {
  isModel.value = true;
};

/**
 * @function 关闭
 * */
const close = () => {
  isModel.value = false;
};

defineExpose({
  open,
  close,
});
</script>
<style lang="scss" scoped>
.main {
  box-sizing: border-box;
  min-height: 450px;
  padding: 20px;

  .tip {
    display: flex;
    align-items: center;
    margin-bottom: 20px;

    .tip-text {
      color: red;
    }
  }

  .mainbox {
    width: 100%;
    height: 300px;
  }

  .preview-model {
    display: flex;
    flex-direction: column;
    justify-content: flex-start;
    align-items: center;

    .preview {
      overflow: hidden;
    }

    .upload-btn {
      display: flex;
      width: 100%;
      justify-content: space-evenly;
      margin-top: 20px;
    }
  }

  .main-btn {
    display: flex;
    justify-content: center;
    margin-top: 20px;
  }
}

</style>

直接在页面中使用 例如index.vue

index.vue 


<template>
    <div class='content'>
          <el-button type="danger" @click="addimg">上传图片 </el-button>
          <img v-if="imgurl" :src="imgurl" alt="" width='200' height="100">
          <comCutimgcropper   ref="imgref"    @uploadImgSuccess="uploadImgSuccess"  ></comCutimgcropper>
    </div>
</template>
  
<script setup>
import comCutimgcropper from '../components/imgcropper.vue'
import { ref ,watch} from 'vue'
import {useRoute, useRouter} from 'vue-router'
const router = useRouter();
const imgref = ref(null);
const imgurl = ref("");

const addimg = () => {
  imgref.value.open();
}

const uploadImgSuccess = data => {
  //调用接口
  // uploadImage(data)
  
  //这里为了展示 直接 写死一张图片 关闭弹框
  imgurl.value = "https://img2.baidu.com/it/u=3354585195,1512541150&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1700845200&t=636a3f6d0f2d46b6753a203f48801a98"
  imgref.value.close()

}
const uploadImage = async data => {
  console.log(data)
  //这里就是跟后台约定好需要传递什么参数
  const params = {
    file: data,
    fileName: data.fileName, 
  }
  //上传接口
  const res = await uploads(params);
  if (res && res.code === 200) {
    //页面上显示图片 后端返回的图片地址
    imgurl.value = res.data.url;
    //关闭弹窗
    imgref.value.close()
  }
}


/**
 * axiso 封装一般这么写 都是采用 FormData的形式  注意请求头 headers    'Content-Type': 'multipart/form-data'
 * 
 * export const uploads = params => {
  const data = new FormData()
  data.append('file', params.file, params.fileName)
  return request({
    headers: {
      'Content-Type': 'multipart/form-data'
    },
    url: '/,
    method: 'post',
    data,
  })
}
 */

</script>


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

S71200通过PROFINET协议和岛电数字控制器通讯

项目要求 西门子S71200PLC需要通过PROFINET协议和岛电数字控制器&#xff08;型号&#xff1a;SRS13A&#xff09;通讯&#xff0c;读取温度的测量值PV和设定值SV。 项目实施 采用NET90-PN-MBT&#xff08;以下简称“网关”&#xff09;&#xff0c;它是一款将Modbus TCP/RT…

用户隐私与游戏体验如何平衡?第二周 Web3 开发者集结精华回顾

由 TinTinLand 联合 Dataverse 、Web3Go 、Subquery 、Cregis 、Litentry、Aspecta、SpaceID、ANOME、VARA&Gear、Moonbeam、Mantle、Obelisk 等 10 余家 Web3 项目共同举办的 Web3 开发者赢积分活动已举办至第三周。精彩线上主题活动分享、近距离交流体验互动&#xff0c;…

京东采销面对面,洞悉行业新趋势 京东3C数码生态大会在武汉圆满举行

为促进湖北省3C数码产业发展&#xff0c;本地企业降本增效、促进行业交流、充分发挥京东集团全链路生态服务能力&#xff0c;支持地方3C特色产业提质增量。2023年11月23日&#xff0c;由京东零售、京东物流主办&#xff0c;湖北省电子商务行业协会联合协办的“聚力共赢、携手共…

想问问各位大佬,网络安全这个专业普通人学习会有前景吗?

网络安全是一个非常广泛的领域&#xff0c;涉及到许多不同的岗位。这些岗位包括安全服务、安全运维、渗透测试、web安全、安全开发和安全售前等。每个岗位都有自己的要求和特点&#xff0c;您可以根据自己的兴趣和能力来选择最适合您的岗位。 渗透测试/Web安全工程师主要负责模…

山西电力市场日前价格预测【2023-11-25】

1.日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-11-25&#xff09;山西电力市场全天平均日前电价为312.19元/MWh。其中&#xff0c;最高日前电价为350.80元/MWh&#xff0c;预计出现在09:15。最低日前电价为273.49元/MWh&#xff0c;预…

NX二次开发UF_CSYS_map_point 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CSYS_map_point Defined in: uf_csys.h int UF_CSYS_map_point(int input_csys, double input_point [ 3 ] , int output_csys, double output_point [ 3 ] ) overview 概述 Ma…

2.19 keil里面工具EventCorder使用方法

设置方法如下&#xff1a; 添加初始化代码如下&#xff1a; eventRecord.c #include "eventRecord.h" #include "usart.h" extern UART_HandleTypeDef *pcControlUart;/* RecordEvent初始化 */ void InitEventRecorder(void) {#ifdef RTE_Compiler_Even…

Elasticsearch知识

目录 Elasticsearch逻辑设计和物理设计 逻辑设计物理设计Elasticsearch原理 倒排索引文档的分析过程保存文档搜索文档写数据的底层原理 数据刷新&#xff08;fresh&#xff09;事务日志的写入ES在大数据量下的性能优化 文件系统缓存优化数据预热文档&#xff08;Document&…

名酒新周期,西凤复兴的“四个自信”

执笔 | 文 清 编辑 | 萧 萧 11月18日&#xff0c;四大名酒之一、凤香品类龙头企业的西凤酒&#xff0c;携全系列产品亮相AIIC酒业创新展暨中国名酒成就展。 在当日下午举行的“筑梦新征程”2023中国名酒纪念大会暨《大师》影像志上线仪式上&#xff0c;陕西西凤酒股份有限…

linux网络之网络层与数据链路层

文章目录 一、网络层 1.IP协议 2.IP协议头格式 3.网段划分 4.特殊ip地址 5.IP地址的数量限制 6.私有ip和公网IP 7.路由 二、数据链路层 1.以太网 2.以太网帧格式 3.MAC地址 4.对比理解MAC地址和IP地址 5.MTU 6.ARP协议 ARP协议的工作流程 ARP数据报的格式 7.DNS 8.ICMP协议 9.N…

无需外接显示器,直接使用windows安装树莓派系统并可远程桌面登录

准备工作: 1.安装树莓派官方烧录工具 raspberry pi imager 2.下载树莓派系统镜像(也可选择在线下载安装) 打开imager工具&#xff0c;选择需要安装包树莓派版本 点击"NEXT"&#xff0c;在弹出的选项中选择编辑设置。 设置登录名和密码&#xff0c;已经所连接的wif…

针对CSP-J/S的每日一练:Day 11

一、审题 题目描述 给定两个大小分别为 m m m 和 n n n 的正序&#xff08;从小到大&#xff09;数组 n u m s 1 nums1 nums1 和 n u m s 2 nums2 nums2。请你找出并返回这两个正序数组的中位数。 算法的时间复杂度应该为 O ( l o g ( m n ) ) O(log (mn)) O(log(mn)) 。…

如何做接口测试呢?接口测试有哪些工具!

回想入职测试已经10年时间了&#xff0c;初入职场的我对于接口测试茫然不知。后来因为业务需要&#xff0c;开始慢慢接触接口测试。从最开始使用工具进行接口测试到编写代码实现接口自动化&#xff0c;到最后的测试平台开发。回想这一路走来感触颇深&#xff0c;因此为了避免打…

软件测试基础知识 —— 白盒测试

白盒测试 白盒测试&#xff08;White Box Testing&#xff09;又称结构测试、透明盒测试、逻辑驱动测试或基于代码的测试。白盒测试只测试软件产品的内部结构和处理过程&#xff0c;而不测试软件产品的功能&#xff0c;用于纠正软件系统在描述、表示和规格上的错误&#xff0c;…

ESP32 ESP-IDF5.1 在Visual Studio Code中自定义分区表与调整Flash大小

好记心不如烂笔头 使用ESP-IDF开发ESP32的时候,要是同时用到蓝牙和WIFI的话,很多时候会提示Flash不够, 我是照着这样解决的,存档记录 来源 : zaixingxing2539 大佬的 ESP32 ESP-IDF5.0 在VSCODE中自定义分区表 用Visual Studio Code自定义分区表 # ESP-IDF Partition Table…

MATLAB实战 | MEX文件

应用接口是MATLAB与其他语言相互调用各自函数的方法&#xff0c;MEX文件使MATLAB程序中可以调用或链接其他语言编写的函数&#xff0c;而MATLAB引擎使其他语言程序中可以调用MATLAB函数。 01、MEX文件 MEX是MATLAB Executable的缩写&#xff0c;是MATLAB中用于调用其他语言编写…

GEE:生成超链接方式下载影像

作者:CSDN @ _养乐多_ 本文将介绍如何使用Google Earth Engine(GEE)平台以生成下载超链接的形式下载遥感数据。 结果如下图所示,只需点击链接,即可下载数据到本地。 文章目录 一、函数详解二、代码示例一、函数详解 用法返回值Image.getDownloadURL(params, callback)Ob…

【Jmeter进阶】压力测试大杀器:Jmeter使用技巧与总结!

一、基本概念 1.线程组N&#xff1a;代表一定数量的并发用户&#xff0c;所谓并发就是指同一时刻访问发送请求的用户。线程组就是模拟并发用户访问。 2.Ramp-Up Period(in seconds)&#xff1a;建立所有线程的周期&#xff0c;就是告诉jmeter要在多久没启动所有线程&#xff…

CloudQuery x GBase,信创数据库管控革新之路

日前&#xff0c;杭州图尔兹信息技术有限公司自主研发的 CloudQuery 一体化数据库操作管控平台&#xff0c;已经和天津南大通用数据技术股份有限公司研发的南大通用安全数据库管理系统 [简称&#xff1a;GBase 8s] 完成兼容性测试&#xff0c;并获得兼容性认证证书。 现阶段&am…

红酒按照糖含量怎么分类?

我们常听人们形容葡萄酒为干型或甜型&#xff0c;这指的是葡萄酒的含糖量。不含糖就是干型&#xff0c;含糖少就是半干型&#xff0c;含糖多就是甜型&#xff0c;这是葡萄酒分类的一种——按糖量分。云仓酒庄的品牌雷盛红酒分享一般分为干型、半干型、半甜型、甜型四种。 云仓…