vue3中使用el-upload + tui-image-editor进行图片处理

效果如下

看之前请先看上一篇《vue3中使用组件tui-image-editor进行图片处理 》中的
1、第一步安装
2、第二部封装组件

本篇只是在这基础上结合el-upload使用组件
3、第三步结合el-upload使用组件

javascript 复制代码
<template>
  <el-dialog
    :title="dialogTitle"
    :modelValue="dialogVisible"
    width="55%"
    top="4vh"
    :before-close="closeDialog"
    :close-on-click-modal="false"
    destroy-on-close
  >
    <div class="newBox">
      
      <el-upload
        class="img-edit"
        :show-file-list="false"
        :accept="cropperObj.accpetType"
        :limit="cropperObj.limit"
        :on-change="cropperObj.handleAvatarSuccess"
        :before-upload="cropperObj.beforeAvatarUpload"
        :disabled="cropperObj.dealPicShow"
      >
        <div class="imgCorpper" v-if="cropperObj.dealPicShow"  @mouseenter="cropperObj.buttonopen" @mouseleave="cropperObj.buttonexit">
          <div class="imgCorpperY">
            <el-image  
            :src="cropperObj.previewViewer"
            :zoom-rate="1.2"
            :preview-src-list="cropperObj.srcList"
            :initial-index="4"
            fit="cover"/> 
            <el-image-viewer
              v-if="cropperObj.showImageViewer"
              @close="cropperObj.closeImgView"
              :url-list="cropperObj.srcList"
            />
            <div :class="cropperObj.showBack?'imgcurrent show':'imgcurrent'"  >
              <div class="imgBack"></div>
              <div class="imgicon">
                <el-icon @click="cropperObj.showPic"><ZoomIn /></el-icon>
                <el-icon @click="cropperObj.delePic"><Delete /></el-icon>
              </div>
            </div>
          </div>
        </div>
        <el-icon v-else class="img-edit-icon"><Plus /></el-icon>
      </el-upload>
      <!-- 上传提示 -->
      <div class="el-upload__tip" v-if="!cropperObj.dealPicShow">
        请上传大小不超过 <b style="color: #f56c6c">{{ cropperObj.fileSize }}MB</b>格式为 <b style="color: #f56c6c">{{ cropperObj.fileType.join("/") }}</b>的文件
      </div>
      <!-- 图片处理框 -->
      <SignImage 
        v-if="cropperObj.cVisible" 
        :dialogVisible.sync="cropperObj.cVisible" 
        :title="cropperObj.ctitle"
        :imgUrl="cropperObj.previewsImgUrl"
        @getNewImg="cropperObj.getNewImg"
        @closeCropperDialog="cropperObj.closeCropperView"
      ></SignImage>

    </div>
    
    <template #footer>
      <div class="dialog-footer">
        <!-- <el-button class="btn-sure" type="primary" @click="closeDialog">确 定</el-button> -->
        <el-button @click="closeDialog">取 消</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup>
import SignImage from '@/components/SignImage/index.vue'
import { importNewImg, editNewImg } from "@/api/back/home.js";
import { ref, reactive, watch } from "vue";

  const props = defineProps({
    dialogVisible: {
      type: Boolean,
      default: false,
    },
    dialogTitle: {
      type: String,
      default: "",
    },
    
  });

  // 关闭弹窗
  const emits = defineEmits(["closeDialog"]);
  const closeDialog = () => {
    emits("closeDialog");
  };


// new 背景图片
const cropperObj = reactive({
  fileType: ["png", "jpg", "jpeg"],
  accpetType:".png,.jpg,.jpeg",
  limit:1,
  fileSize:10,
  cVisible:false, // 显示切图弹框
  ctitle:"", // 弹框标题
  imgShow:false, //是否有图片
  previewsImgUrl:"", //图片地址
  srcList:[], //图片预览地址数组
  showBack:false, // 预览删除图层是否展示
  showImageViewer:false, // 是否预览
  previewViewer:"", // 处理后的图片地址
  dealPicShow:false, // 是否删除了处理后的图片
  // 开启编辑弹框
  openCropperView: () => {
    cropperObj.ctitle="图片"
    cropperObj.cVisible = true 
  },
  // 关闭编辑弹框所触发的事件
  closeCropperView: (data)=> {
    cropperObj.cVisible = false
  },
  // 预览删除图层显示
  buttonopen: ()=>{
    cropperObj.showBack = true
  },
  // 预览删除图层隐藏
  buttonexit: ()=>{
    cropperObj.showBack = false
  },
  // 预览开启
  showPic: ()=>{
    cropperObj.showImageViewer = true
  },
  // 预览隐藏
  closeImgView: ()=>{
    cropperObj.showImageViewer = false
  },
  // 删除图片
  delePic:()=>{
    cropperObj.previewsImgUrl ="";
    cropperObj.previewViewer = ""
    cropperObj.srcList=[]
    setTimeout(function(){
      cropperObj.dealPicShow = false
    },1000)
    cropperObj.imgShow = false
    // formData.backgroundUrl = "";
  },
  // 获取处理完的图片
  getNewImg:(val) =>{
    cropperObj.previewViewer = window.serverUrl.IMG_SERVER + val
    cropperObj.dealPicShow = true
    cropperObj.srcList=[cropperObj.previewViewer]
    // formData.backgroundUrl = val;
  },
  beforeAvatarUpload:(file)=> {
    let isImg = false;
    let fileExtension = "";
    if (cropperObj.fileType.length) {
      if (file.name.lastIndexOf(".") > -1) {
        fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
      }
      isImg = cropperObj.fileType.some((type) => {
        if (file.raw.type.indexOf(type) > -1) return true;
        if (fileExtension && fileExtension.indexOf(type) > -1) return true;
        return false;
      });
    } else {
      isImg = file.type.indexOf("image") > -1;
    }
    if (!isImg) {
      ElMessage.error(`格式不正确, 请上传${cropperObj.fileType.join("/")}图片格式文件!`);
      return false;
    } else {
      isImg = true;
    }
    if (cropperObj.fileSize) {
      const isLt = file.size / 1024 / 1024 < cropperObj.fileSize;
      if (!isLt) {
        proxy.$modal.msgError(`上传大小不能超过 ${cropperObj.fileSize} MB!`);
        // fileList.value = [];
        return false;
      }
    }
  },
  handleAvatarSuccess:(file, fileList)=> {
    const bgFormData = new FormData()
    bgFormData.append("file", file.raw);
    importNewImg(bgFormData).then(res => {
      cropperObj.previewsImgUrl = window.serverUrl.IMG_SERVER + res.fileName
      cropperObj.ctitle="图片处理"
      cropperObj.cVisible = true 
    })
  },
})


</script>

<style lang="scss"  scoped>
  .img-edit{
    display: flex;
    justify-content: center;
    align-items: center;
    font-size:1rem;
    width:148px;
    height: 148px;
    border:1px dashed #cdd0d6;
    position: relative;
    border-radius: 6px;
    .el-icon{
      width:0.35rem;
      height: 0.35rem;
      color:#909399;
    }
    .imgCorpper{
    display: flex;
    justify-content: center;
    align-items: center;
    font-size:1rem;
    width:148px;
    height: 148px;
    border:1px dashed #cdd0d6;
    position: relative;
    border-radius: 6px;
    cursor:pointer;
    .el-icon{
      width:0.35rem;
      height: 0.35rem;
      color:#909399;
    }
    .imgCorpperY{
      position: relative;
      width: 100%;
      height: 100%;
      border-radius: 6px;
      overflow: hidden;
      height: 100%;;
      >img{
        width: 100%;
        height: 100%;;
      }
      .el-image{
        width: 100%;
        height: 148px;
        max-height: 100%;;
      }
      .imgcurrent{
          display: none;
          position: absolute;
          width: 100%;
          height: 100%;
          top: 0;
          .imgBack{
            background: #00000082;
            width: 100%;
            height: 100%;
            position: absolute;
            z-index: 1;
          }
          .imgicon{
            position: absolute;
            width: 60%;
            margin: 0 20%;
            height: 100%;
            display: flex;
            justify-content: space-between;
            align-items: center;
            color: #fff;
            z-index: 2;
            .el-icon{
              color: #fff;
              // font-size: 1rem;
            }
          }
        }
        >.show{
          display:block;
        }
      }
    }
  }
  .img-edit:hover {
    border-color: #409EFF;
  }
</style>
相关推荐
Sunlightʊə1 小时前
2.登录页测试用例
运维·服务器·前端·功能测试·单元测试
Code Crafter2 小时前
ES6-ES14 新特性速查
前端·ecmascript·es6
Lhuu(重开版2 小时前
CSS从0到1
前端·css·tensorflow
CDwenhuohuo2 小时前
微信小程序里用 setData() 修改数据并打印输出 的几种写法
javascript·微信小程序·小程序
不说别的就是很菜3 小时前
【前端面试】HTML篇
前端·html
前端一小卒3 小时前
生产环境Sourcemap策略:从苹果事故看前端构建安全架构设计
前端·javascript
im_AMBER3 小时前
React 18
前端·javascript·笔记·学习·react.js·前端框架
老前端的功夫3 小时前
Vue2中key的深度解析:Diff算法的性能优化之道
前端·javascript·vue.js·算法·性能优化
集成显卡4 小时前
AI取名大师 | PM2 部署 Bun.js 应用及配置 Let‘s Encrypt 免费 HTTPS 证书
开发语言·javascript·人工智能
han_4 小时前
前端高频面试题之Vue(高级篇)
前端·vue.js·面试