vue3element plus实现头像裁剪

838 阅读1分钟

vue3配合element plus实现头像裁剪

实现上传功能

首先添加vue3中写组件,使用element plus的el-upload实现上传功能
  1.  <el-upload
          class="upload-demo"
          drag
          style="width: 400px"
          :auto-upload="false"//关闭默认上传功能
          :before-upload="beforeAvatarUpload"//检验图片大小和类型
          :on-change="changeSize"//检测图片上传
        >
          <el-icon class="el-icon--upload"><upload-filled /></el-icon>
          <div class="el-upload__text">请上传您的头像<em>上传</em></div>
        </el-upload>
    
  2. //导入el-upload-----------
    import { UploadFilled } from "@element-plus/icons-vue";
    
  3. //实现检验图片大小和类型
    import { reactive, ref } from "vue";
    import { ElMessage } from "element-plus";
    import axios from "axios";
    const beforeAvatarUpload = (rawFile) => {
      if (!rawFile.type.includes("image")) {
        ElMessage.error("很抱歉您上传的不是图片格式");
        return false;
      } else if (rawFile.size / 1024 / 1024 > 2) {
        ElMessage.error("您上传的图片大小超过了2MB");
        return false;
      }
      return true;
    };
    
    //检验图片上传
    const changeSize = (UploadFile) => {
     //这里的UploadFile就是上传上去的文件
    //图片上传以后出现dialog框,出现裁剪功能
    };
    
  4.  <el-dialog
          
          v-model="centerDialogVisible"
          title="裁剪头像"
          width="60%"
          align-center
        >
         //centerDialogVisible是diakog是否出现
          <!-- 这里可以来放图片 -->
    
        //这里就可以来放裁剪功能的代码
          <template #footer>
            <span class="dialog-footer">
              <el-button @click="centerDialogVisible = false">取消</el-button>
              <el-button type="primary" @click="uploadAvatar"> 确认 </el-button>
            </span>
          </template>
        </el-dialog>
    
    const centerDialogVisible = ref(false);
    const uploadFile = ref({});
    
  5. 引入vue-Cropper

    //安装
    npm install vue-cropper@next
    //引入
    import 'vue-cropper/dist/index.css'
    import { VueCropper }  from "vue-cropper";
    
    
    
  6. 使用vue-Cropper

     <el-dialog
          v-model="centerDialogVisible"
          title="裁剪头像"
          width="60%"
          align-center
        >
          <!-- 这里可以来放图片 -->
    
          <vueCropper
            class="crop-box"
            ref="cropper"
            :img="option.img"
            :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"
            :autoCropWidth="option.autoCropWidth"
            :autoCropHeight="option.autoCropHeight"
            @cropMoving="cropMoving"
          ></vueCropper>
    
          <template #footer>
            <span class="dialog-footer">
              <el-button @click="centerDialogVisible = false">取消</el-button>
              <el-button type="primary" @click="uploadAvatar"> 确认 </el-button>
            </span>
          </template>
        </el-dialog>
    
    <script setup>
    import { UploadFilled } from "@element-plus/icons-vue";
    import { ElMessage } from "element-plus";
    import { reactive, ref } from "vue";
    import "vue-cropper/dist/index.css";
    import { VueCropper } from "vue-cropper";
    import axios from "axios";
    const centerDialogVisible = ref(false);
    
        
    
    
    const croppedImageData = ref(null);
     //获取裁剪图片组件
    const cropper = ref();
    
    const imageSrc = ref("");
    
    const option = reactive({
      img: "", // 裁剪图片的地址
      info: true, // 裁剪框的大小信息
      outputSize: 1, // 裁剪生成图片的质量
      outputType: "jpg", // 裁剪生成图片的格式
      canScale: true, // 图片是否允许滚轮缩放
      autoCrop: true, // 是否默认生成截图框
      canMoveBox: true, // 截图框能否拖动
      autoCropWidth: 200, // 默认生成截图框宽度
      autoCropHeight: 200, // 默认生成截图框高度
      fixedBox: false, // 固定截图框大小 不允许改变
      fixed: true, // 是否开启截图框宽高固定比例
      fixedNumber: [1, 1], // 截图框的宽高比例
      full: false, // 是否输出原图比例的截图
      original: false, // 上传图片按照原始比例渲染
      centerBox: false, // 截图框是否被限制在图片里面
      infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
    });
    
    const beforeAvatarUpload = (rawFile) => {
      if (!rawFile.type.includes("image")) {
         //判断是否是图片格式
        ElMessage.error("很抱歉您上传的不是图片格式");
        return false;
          //验证图片大小
      } else if (rawFile.size / 1024 / 1024 > 2) {
        ElMessage.error("您上传的图片大小超过了2MB");
        return false;
      }
      return true;
    };
    
    const changeSize = (UploadFile) => {
      centerDialogVisible.value = true;
     
    	//这里将图片转化为base64位格式为图片进行裁剪
      const reader = new FileReader();
        
      reader.onload = (e) => {
        //将图片绑定到裁剪组件的img中
        option.img = e.target.result;
      };
      //拿到图片的base64
      reader.readAsDataURL(UploadFile.raw);
    };
    
        //上传头像点击了确认按钮
    const uploadAvatar = () => {
      //上传头像并且点击了确认按钮
      cropper.value.getCropBlob(async (data) => {
        // do something
        let formData = new FormData();
        //第三个参数是规定以什么为后缀,接口是根据后缀来返回地址格式的
        formData.append("file", data, "avatar.jpg");
        //上传文件接口
        let res = await axios({
          method: "post",
          //请求地址
          url: "http://localhost:3000/api/upload/image",
          data: formData,
          headers: {
            "Content-Type": "multipart/form-data", // Use 'multipart/form-data' for file uploads
          },
        });
        if (res.status == 200) {
          imageSrc.value = res.data.data.path;
          ElMessage({
            message: "恭喜您上传头像成功",
            type: "success",
          });
          centerDialogVisible.value = false;
        }
      });
    
    };
    </script>
    
    <style lang="scss" scoped>
    .dialog-footer button:first-child {
      margin-right: 10px;
    }
    :deep(.el-dialog__body) {
      width: 97%;
      height: 600px;
    }
    </style>
    
    
    
  7. 功能所有代码

    <template>
      <div
        style="
          width: 100vw;
          height: 100vh;
          display: flex;
          justify-content: center;
          align-items: center;
        "
      >
        <img :src="imageSrc" alt="" />
        <el-upload
          class="upload-demo"
          drag
          style="width: 400px"
          :auto-upload="false"
          :before-upload="beforeAvatarUpload"
          :on-change="changeSize"
        >
          <el-icon class="el-icon--upload"><upload-filled /></el-icon>
          <div class="el-upload__text">请上传您的头像<em>上传</em></div>
        </el-upload>
        <el-dialog
          v-model="centerDialogVisible"
          title="裁剪头像"
          width="60%"
          align-center
        >
          <!-- 这里可以来放图片 -->
    
          <vueCropper
            class="crop-box"
            ref="cropper"
            :img="option.img"
            :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"
            :autoCropWidth="option.autoCropWidth"
            :autoCropHeight="option.autoCropHeight"
            @cropMoving="cropMoving"
          ></vueCropper>
    
          <template #footer>
            <span class="dialog-footer">
              <el-button @click="centerDialogVisible = false">取消</el-button>
              <el-button type="primary" @click="uploadAvatar"> 确认 </el-button>
            </span>
          </template>
        </el-dialog>
      </div>
    </template>
    
    <script setup>
    import { UploadFilled } from "@element-plus/icons-vue";
    import { ElMessage } from "element-plus";
    import { reactive, ref } from "vue";
    import "vue-cropper/dist/index.css";
    import { VueCropper } from "vue-cropper";
    import axios from "axios";
    const centerDialogVisible = ref(false);
    
    const uploadFile = ref({});
    
    const croppedImageData = ref(null);
    const cropper = ref();
    
    const imageSrc = ref("");
    
    const option = reactive({
      img: "", // 裁剪图片的地址
      info: true, // 裁剪框的大小信息
      outputSize: 1, // 裁剪生成图片的质量
      outputType: "jpg", // 裁剪生成图片的格式
      canScale: true, // 图片是否允许滚轮缩放
      autoCrop: true, // 是否默认生成截图框
      canMoveBox: true, // 截图框能否拖动
      autoCropWidth: 200, // 默认生成截图框宽度
      autoCropHeight: 200, // 默认生成截图框高度
      fixedBox: false, // 固定截图框大小 不允许改变
      fixed: true, // 是否开启截图框宽高固定比例
      fixedNumber: [1, 1], // 截图框的宽高比例
      full: false, // 是否输出原图比例的截图
      original: false, // 上传图片按照原始比例渲染
      centerBox: false, // 截图框是否被限制在图片里面
      infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
    });
    
    const beforeAvatarUpload = (rawFile) => {
       
      if (!rawFile.type.includes("image")) {
        ElMessage.error("很抱歉您上传的不是图片格式");
        return false;
      } else if (rawFile.size / 1024 / 1024 > 2) {
        ElMessage.error("您上传的图片大小超过了2MB");
        return false;
      }
      return true;
    };
    
    const changeSize = (UploadFile) => {
      centerDialogVisible.value = true;
      uploadFile.value = UploadFile;
    
      const reader = new FileReader();
      reader.onload = (e) => {
        option.img = e.target.result;
      };
      reader.readAsDataURL(UploadFile.raw);
    };
    
    const uploadAvatar = () => {
      //上传头像并且点击了确认按钮
      cropper.value.getCropBlob(async (data) => {
        // do something
        let formData = new FormData();
        //第三个参数是规定以什么为后缀,接口是根据后缀来返回地址格式的
        formData.append("file", data, "avatar.jpg");
        //上传文件接口
        let res = await axios({
          method: "post",
          url: "http://localhost:3000/api/upload/image",
          data: formData,
          headers: {
            "Content-Type": "multipart/form-data", // Use 'multipart/form-data' for file uploads
          },
        });
        if (res.status == 200) {
          imageSrc.value = res.data.data.path;
          ElMessage({
            message: "恭喜您上传头像成功",
            type: "success",
          });
          centerDialogVisible.value = false;
        }
      });
    
      //let formData = new FormData();
      //formData.append("file", uploadFile.value.raw);
      //在这个里面就可以拿到图片的具体参数
      //centerDialogVisible.value = false;
    };
    </script>
    
    <style lang="scss" scoped>
    .dialog-footer button:first-child {
      margin-right: 10px;
    }
    :deep(.el-dialog__body) {
      width: 97%;
      height: 600px;
    }
    </style>