vue使用vant+VueCropper实现按照比例裁剪并回显

需要实现的效果如下: 

 控制裁剪框的比例使用:

 beforeRead(file, detail) {
      if (detail.name == "changeSize1") {
        this.option.fixedNumber = [522, 928];
      } else if (detail.name == "changeSize2" || detail.name == "changeSize3") {
        this.option.fixedNumber = [523, 453];
      }
      if (file.type !== "image/jpeg" && file.type !== "image/png") {
        this.$toast("请上传 jpg/png 格式图片");
        return false;
      }
      this.showCropper = true;
      this.imageToBase64(file);
      this.imageFileName = detail.name;
    },

裁剪结束之后点击选择,上传服务器并回显:

getCropBlob() {
      this.loadingShow = true;
      this.$refs.cropper.getCropBlob((blob) => {
        const url = URL.createObjectURL(blob);
        const fileObject = {
          url,
          isImage: true,
          file: blob,
        };

        if (this.imageFileName === "changeSize1") {
          this.file1 = [fileObject];
        } else if (this.imageFileName === "changeSize2") {
          this.file2 = [fileObject];
        } else if (this.imageFileName === "changeSize3") {
          this.file3 = [fileObject];
        }

        this.showCropper = false;
        this.loadingShow = false;
        this.$emit("update:showAta", false);
      });
    },

完整代码如下:

<template>
  <div class="photoAlbum">
    <NavBar :title="title" />
    <div class="content-box">
      <van-uploader
        v-model="file1"
        class="uploader-left"
        multiple
        :max-count="1"
        :before-read="beforeRead"
        name="changeSize1"
      />
      <div class="up-right">
        <van-uploader
          v-model="file2"
          class="uploader-Tright"
          multiple
          :max-count="1"
          :before-read="beforeRead"
          name="changeSize2"
        />
        <van-uploader
          v-model="file3"
          class="uploader-Bleft"
          multiple
          :max-count="1"
          :before-read="beforeRead"
          name="changeSize3"
        />
      </div>
    </div>
    <div class="uploadava">
      <van-popup
        duration="0"
        v-model="showCropper"
        position="top"
        :style="{ height: '100%' }"
      >
        <div class="cropper-container">
          <van-loading
            v-show="loadingShow"
            size="50"
            color="#fff"
            vertical
            text-color="#fff"
            >上传中...</van-loading
          >
          <vueCropper
            ref="cropper"
            :img="option.img"
            :outputSize="option.outputSize"
            :outputType="option.outputType"
            :info="option.info"
            :full="option.full"
            :autoCropWidth="option.autoCropWidth"
            :autoCropHeight="option.autoCropHeight"
            :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"
            :high="option.high"
            :mode="option.mode"
          />
          <van-nav-bar
            left-text="取消"
            right-text="选择"
            @click-left="onClickLeft"
            @click-right="getCropBlob"
          />
        </div>
      </van-popup>
    </div>
    <!-- <div class="btn">
      <button>确认</button>
    </div> -->
  </div>
</template>

<script>
import NavBar from "@/components/NavBar/NavBar";
import { Uploader } from "vant";
import { VueCropper } from "vue-cropper";

export default {
  components: {
    NavBar,
    VueCropper,
  },
  props: {
    showAta: {
      default: false,
      type: Boolean,
    },
    avaUrl: {
      default: "",
      type: String,
    },
  },
  data() {
    return {
      title: "vcard.routes.photoAlbum",
      file1: [],
      file2: [],
      file3: [],
      show: true, // 上传类型的弹窗
      imageFileName: "",
      showCropper: false, // 裁剪的弹窗
      option: {
        img: "",
        outputSize: 0.8,
        info: false, // 裁剪框的大小信息
        outputType: "jpeg", // 裁剪生成图片的格式
        canScale: true, // 图片是否允许滚轮缩放
        autoCrop: true, // 是否默认生成截图框
        autoCropWidth: window.innerWidth - 100 + "px", // 默认生成截图框宽度
        autoCropHeight: window.innerWidth - 100 + "px", // 默认生成截图框高度
        high: true, // 是否按照设备的dpr 输出等比例图片
        fixedBox: false, // 固定截图框大小 不允许改变
        fixed: true, // 是否开启截图框宽高固定比例
        fixedNumber: [], // 截图框的宽高比例
        full: true, // 是否输出原图比例的截图
        canMoveBox: true, // 截图框能否拖动
        original: false, // 上传图片按照原始比例渲染
        centerBox: true, // 截图框是否被限制在图片里面
        infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
        mode: "100% auto", // 图片默认渲染方式
      },
      loadingShow: false, // 是否展示loading
    };
  },
  methods: {
    beforeRead(file, detail) {
      if (detail.name == "changeSize1") {
        this.option.fixedNumber = [522, 928];
      } else if (detail.name == "changeSize2" || detail.name == "changeSize3") {
        this.option.fixedNumber = [523, 453];
      }
      if (file.type !== "image/jpeg" && file.type !== "image/png") {
        this.$toast("请上传 jpg/png 格式图片");
        return false;
      }
      this.showCropper = true;
      this.imageToBase64(file);
      this.imageFileName = detail.name;
    },
    imageToBase64(file) {
      let reader = new FileReader();

      reader.readAsDataURL(file);
      reader.onload = () => {
        this.option.img = reader.result;
      };
    },
    getCropBlob() {
      this.loadingShow = true;
      this.$refs.cropper.getCropBlob((blob) => {
        const url = URL.createObjectURL(blob);
        const fileObject = {
          url,
          isImage: true,
          file: blob,
        };

        if (this.imageFileName === "changeSize1") {
          this.file1 = [fileObject];
        } else if (this.imageFileName === "changeSize2") {
          this.file2 = [fileObject];
        } else if (this.imageFileName === "changeSize3") {
          this.file3 = [fileObject];
        }

        this.showCropper = false;
        this.loadingShow = false;
        this.$emit("update:showAta", false);
      });
    },
    onClickLeft() {
      this.loadingShow = false;
      this.showCropper = false;
      this.$parent.showPhotoUploader = false;
    },
  },
};
</script>

<style scoped lang="scss">
@import "./photoAlbum.scss";
</style>
<style lang="scss">
.uploader-left {
  width: 49%;
  .van-uploader__wrapper {
    width: 100%;
    .van-uploader__upload {
      width: 100%;
      height: 5.96rem;
      margin: 0;
    }
  }
  .van-uploader__preview {
    width: 100%;
    margin: 0;
    .van-image {
      width: 100%;
      height: 5.96rem;
    }
  }
}

.van-loading {
  position: absolute;
  z-index: 9999;
  left: 50%;
  top: 50%;
  margin-left: -55px;
  margin-top: -30px;
  background: rgba(0, 0, 0, 0.3);
  padding: 10px 30px;
  border-radius: 25px;
}

.up-right {
  width: 49%;
  position: relative;
  height: 5.96rem;
  .van-uploader {
    width: 100%;
    .van-uploader__wrapper {
      width: 100%;
      .van-uploader__upload {
        width: 100%;
        height: 2.9rem;
        margin: 0;
      }
    }
  }
  .uploader-Bleft {
    position: absolute;
    bottom: 0;
    right: 0;
  }

  .van-uploader__preview {
    width: 100%;
    margin: 0;
    .van-image {
      width: 100%;
      height: 2.9rem;
    }
  }
}

.uploadava {
  .update-avatar {
    height: 100%;
    text-align: center;
    .update-avatar-line {
      width: 100%;
      height: 1px;
      background-color: #979797;
    }
    .avatar-select-type {
      background-color: #fff;
      width: 346px;
      border-radius: 12px;
      padding-bottom: 4px;
      .upload-avator {
        padding: 14px;
      }
    }
    p {
      margin: 15px 0 30px;
      background-color: #fff;
      width: 346px;
      border-radius: 12px;
      padding: 15px 0 18px;
    }
  }
  .cropper-container {
    height: 90.7vh;
    .van-nav-bar {
      background-color: rgba(0, 0, 0, 0.87);
      :global(.van-nav-bar__text) {
        color: #fff;
      }
      :global(.van-nav-bar__text:nth-child(2)) {
        color: #000;
        font-weight: 500;
      }
    }
  }
  .vue-cropper {
    background: #000;
    height: 100%;
    padding-top: 46px;
    box-sizing: border-box;
  }
}
</style>

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

async.1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值