vue3-cropperjs图片裁剪工具-用户上传图片截取-(含预览视频)

效果图

上传图片弹窗预览

对于这个上传图片样式可以参考

官方原代码

官网传送入口 Upload 上传 | Element Plus (element-plus.org)

html 复制代码
<template>
  <el-upload
    class="upload-demo"
    drag
    action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
    multiple
  >
    <el-icon class="el-icon--upload"><upload-filled /></el-icon>
    <div class="el-upload__text">
      Drop file here or <em>click to upload</em>
    </div>
    <template #tip>
      <div class="el-upload__tip">
        jpg/png files with a size less than 500kb
      </div>
    </template>
  </el-upload>
</template>

<script setup lang="ts">
import { UploadFilled } from '@element-plus/icons-vue'
</script>

上传图片之后

裁剪图片之后

预览视频

裁剪图片预览视频


操作步骤

安装依赖

npm install cropperjs
npm  i qs    
npm  i axios  
npm i element-plus     

template部分

html 复制代码
<template>
  <div>
    <el-dialog :title="dialogTitle.imgTitle" width="800px" v-model="dialogVisible.imgCropperVisible" :before-close="handleBeforeClose">
      <div v-if="imageSrc" style="display: flex; justify-content: space-between; align-items: center;">

        <!-- Display cropped image or original image if not cropped with background -->
        <div style="width: 50%; padding: 10px; background-color: #f5f5f5; display: flex; justify-content: center; align-items: center;">
          <img ref="previewImage" :src="croppedImageSrc || imageSrc" alt="Preview Image" style="max-width: 100%; height: auto;" />
        </div>

        <!-- Upload image section without background -->
        <div style="width: 50%; padding: 10px; display: flex; justify-content: center; align-items: center;">
          <img ref="uploadImage" :src="imageSrc" alt="Source Image" style="max-width: 100%; height: auto;" />
        </div>
      </div>

      <!-- Centered buttons -->
      <div v-if="imageSrc" style="margin-top: 20px; text-align: center;">
        <el-button type="primary" @click="cropImage">裁剪图片</el-button>
        <el-button @click="clearImage">重新选择</el-button>
        <el-button type="primary" @click="uploadCroppedImage">上传头像</el-button>
      </div>

      <!-- Conditional display for upload component -->
      <el-upload
          v-if="!imageSrc"
          class="upload-demo"
          drag
          action="http://localhost:8888/v1/file/singleUploadFile"
          multiple
          v-model:file-list="fileList"
          limit="1"
          :show-file-list="false"
          :before-upload="beforeUpload"
      >
        <el-icon class="el-icon--upload"><upload-filled /></el-icon>
        <div class="el-upload__text">
          Drop file here or <em>click to upload</em>
        </div>
        <template #tip>
          <div class="el-upload__tip">
            jpg/png files with a size less than 500kb
          </div>
        </template>
      </el-upload>
    </el-dialog>
  </div>
  <div>
    <img :src="BASE_URL+attraction_detail.imageUrl" alt="">
  </div>
</template>

js部分

javascript 复制代码
<script setup>
import { ref, nextTick, onBeforeUnmount } from 'vue';
import { ElMessage } from 'element-plus';
import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.css';
import axios from 'axios';

const imageSrc = ref(null);
const croppedImageSrc = ref(null);
const dialogTitle = ref({ imgTitle: '上传图片' });
const dialogVisible = ref({ imgCropperVisible: true });
const fileList = ref([]);

const uploadImage = ref(null);
const previewImage = ref(null);
let cropper = null;
const attraction_detail =ref({imageUrl:''})
const beforeUpload = (file) => {
  const isImage = file.type.startsWith('image/');
  if (!isImage) {
    ElMessage.error('只能上传图片文件');
    return false;
  }
  const reader = new FileReader();
  reader.onload = async (e) => {
    imageSrc.value = e.target.result;
    await nextTick();
    initCropper();
  };
  reader.readAsDataURL(file);
  return false;
};

const initCropper = () => {
  if (cropper) {
    cropper.destroy();
  }
  if (!uploadImage.value) return;

  cropper = new Cropper(uploadImage.value, {
    aspectRatio: 1,
    viewMode: 1,
  });
};

const cropImage = () => {
  if (cropper) {
    const canvas = cropper.getCroppedCanvas({
      width: 200,
      height: 200,
    });
    croppedImageSrc.value = canvas.toDataURL('image/png');
  }
};

const clearImage = () => {
  imageSrc.value = null;
  croppedImageSrc.value = null;
  fileList.value = [];
  if (cropper) {
    cropper.destroy();
    cropper = null;
  }
};

const uploadCroppedImage = async () => {
  if (!croppedImageSrc.value) {
    ElMessage.error('请先裁剪图片');
    return;
  }
  try {
    const blob = dataURLToBlob(croppedImageSrc.value);
    const formData = new FormData();
    formData.append('file', blob, 'avatar.png'); // 注意这里的表单字段名应为'file'

    const response = await axios.post('http://localhost:8888/v1/file/singleUploadFile', formData);

    if (response.data) {
      ElMessage.success('上传成功');
      dialogVisible.value.imgVisible = false;
      attraction_detail.value.imageUrl = response.data;
      console.log(response.data)

      console.log("")
    } else {
      ElMessage.error(response.data.msg || '上传失败');
    }
  } catch (error) {
    ElMessage.error('上传失败');
  }
};

const dataURLToBlob = (dataURL) => {
  const arr = dataURL.split(',');
  const mime = arr[0].match(/:(.*?);/)[1];
  const bstr = atob(arr[1]);
  let n = bstr.length;
  const u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], { type: mime });
};

onBeforeUnmount(() => {
  if (cropper) {
    cropper.destroy();
  }
});
</script>

css部分

css 复制代码
<style scoped>
.upload-demo .el-upload {
  display: block;
  width: 100%;
  margin-bottom: 20px;
}

.el-upload__text {
  color: #606266;
  font-size: 14px;
  line-height: 22px;
  margin-top: 5px;
}

.el-upload__tip {
  color: #909399;
  font-size: 12px;
  line-height: 1.5;
  margin-top: 7px;
}
</style>
相关推荐
白水先森12 小时前
ArcGIS Pro制作人口三维地图教程
arcgis·信息可视化·数据分析
摆烂老大20 小时前
SWAT| 水文 | SWAT模型(四):气象数据库制备(附Python代码)
python·arcgis·水文·swat模型
GIS遥感数据处理应用1 天前
MATLAB | 设置滑动窗口计算栅格数据的CV变异系数
matlab·arcgis·数据分析
白水先森1 天前
ArcGIS Pro进行坡度与坡向分析
经验分享·arcgis
GZ同学1 天前
Arcmap和ArcgisPro重装及配置迁移
arcgis
白水先森2 天前
ArcGIS Pro中等高线的生成与应用详解
经验分享·arcgis·信息可视化
白水先森2 天前
如何利用ArcGIS Pro打造萤火虫风格地图
经验分享·arcgis
角砾岩队长4 天前
ArcGIS笔记之度分秒与十进制度的转换
笔记·arcgis
yngsqq7 天前
关于arcgis中坐标系、投影的一些知识
arcgis
李建军7 天前
ArcGISPro 新建shp+数据结构
arcgis