图片进行压缩裁剪上传

场景:

 实现选择一张图片后,进行转换格式然后压缩裁剪上传

问题描述

网页中实现选择上传头像时,需将图片转换为jpg格式,并且符合图片大小为500k

代码如下:

    <template>
      <el-upload
        ref="avatarUpload"
        action
        :show-file-list="false"
        :on-change="fileChange"
        :auto-upload="false"
        :multiple="false"
        accept=""
      >
        <el-button type="primary">上传</el-button>
      </el-upload>
      <el-dialog
        title="图片裁剪"
        ref="dialog"
        width="35%"
        :visible.sync="dialogVisible"
        :close-on-click-modal="false"
      >
        <div class="cropper-w">
          <div class="cropper" :style="{ width: '100%', height: '280px' }">
            <vueCropper
              ref="cropper"
              :img="option.img"
              :outputSize="option.size"
              :outputType="option.outputType"
              :info="option.info"
              :full="option.full"
              :canMove="option.canMove"
              :canMoveBox="option.canMoveBox"
              :original="option.original"
              :autoCrop="option.autoCrop"
              :autoCropWidth="option.autoCropWidth"
              :autoCropHeight="option.autoCropHeight"
              :fixedBox="option.fixedBox"
              :centerBox="option.centerBox"
            >
            </vueCropper>
          </div>
        </div>
        <div slot="footer" class="dialog-footer">
          <el-button @click="dialogVisible = false"
            >{{ $t("common.cancel") }}</el-button
          >
          <el-button type="primary" @click="handleConfirm"
            >{{ $t("common.confirm") }}</el-button
          >
        </div>
      </el-dialog>
    </template>
    <script>
        data(){
          return{
            option: {
            img: "", // 裁剪图片的地址
            info: true, // 裁剪框的大小信息
            outputSize: 0.8, // 裁剪生成图片的质量
            outputType: "jpeg", // 裁剪生成图片的格式
            canScale: false, // 图片是否允许滚轮缩放
            autoCrop: true, // 是否默认生成截图框
            autoCropWidth: 400, // 默认生成截图框宽度
            autoCropHeight: 300, // 默认生成截图框高度
            fixedBox: false, // 固定截图框大小 不允许改变
            fixed: false, // 是否开启截图框宽高固定比例
            //   fixedNumber: [7, 5], // 截图框的宽高比例
            full: true, // 是否输出原图比例的截图
            canMoveBox: true, // 截图框能否拖动
            original: true, // 上传图片按照原始比例渲染
            centerBox: false, // 截图框是否被限制在图片里面
            infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
      },
          }
        },
        methods:{
          handleConfirm() {
              // vue-cropper获取截取后的图片信息,此处data为blob格式
              this.$refs.cropper.getCropBlob((data) => {
                // URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。
                // 这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。

                let blob = window.URL.createObjectURL(data);
                // // 处理缩放 转格式
                var img = new Image();
                img.src = blob;
                var _that = this;
                img.onload = function () {
                  var that = this;
                  //生成比例
                  let w = that.width;
                  let h = that.height;
                  let scale = w / h;
                  h = w / scale;
                  //生成canvas
                  var canvas = document.createElement("canvas");
                  var ctx = canvas.getContext("2d");
                  canvas.width = w;
                  canvas.height = h;
                  ctx.drawImage(that, 0, 0, w, h);
                  // 生成base64
                  // canvas的toDataURL()方法是返回一个包含图片展示的 数据URL。可以使用 type 参数其类型,默认为 PNG 格式。图片的分辨率为96dpi。  数字越小约不清晰
                  _that.cropperPic = canvas.toDataURL("image/jpeg", 0.8);
                  let files = _that.transformToFiles(_that.cropperPic, _that.filename);
                  _that.dialogVisible = false;
                  if (files.size / 1024 > 100 && files.size / 1024 < 500) {
                    _that.yaSuo(files);
                  } else {
                    _that.formData.picture = files;
                    _that.pictureUrl = window.URL.createObjectURL(files);
                  }
                };
              });
            },
          // base64转成files
          transformToFiles(dataurl, filename) {
            let arr = dataurl.split(",");
            let mime = arr[0].match(/:(.*?);/)[1];
            let suffix = mime.split("/")[1];
            let bstr = atob(arr[1]);
            let n = bstr.length;
            let u8arr = new Uint8Array(n);
            while (n--) {
              u8arr[n] = bstr.charCodeAt(n);
            }
            return new File([u8arr], `file.${suffix}`, { type: "image/jpeg" });
          },
          fileChange(file) {
            let min = 1024 * 1024 * 0.1;
            let max = 1024 * 1024 * 0.5;
            let fileSuffixList = ["jpg", "jpeg", "png", "webp", "bmp"];
            let fileName = file.name.substring(file.name.lastIndexOf(".") + 1);
            var self = this;
            if (
              fileSuffixList.indexOf(fileName) > -1 ||
              fileName.substring(0, 4) == "webp"
            ) {
              let isJpgOrPng = fileName === "jpeg";
              if (isJpgOrPng) {
                // 文件大于100小于500需要压缩
                if (file.size < min && file.size > max) {
                  this.yaSuo(file);
                } else if (file.size > max) {
                  // 文件大于500   先裁剪在压缩
                  this.openCropper(file, fileName);
                } else {
                }
              } else {
                var imgFile = new FileReader();
                try {
                  imgFile.onload = function (e) {
                    var image = new Image();
                    image.src = e.target.result; //base64数据
                    image.onload = function () {
                      self.imgToCanvas(image);
                    };
                  };
                  imgFile.readAsDataURL(file.raw);
                } catch (e) {
                  console.log("请上传图片!" + e);
                }
              }
              var reader = new FileReader();
              reader.onload = function (e) {
                self.formData.picture = e.target.result;

                self.pictureUrl = e.target.result;
              };
              //选择图片文件后即时预览图片
              reader.readAsDataURL(file.raw);
            } else {
              this.$message.warning(
                this.$t("common.selectImg") +
                  "('*.jpg', '*.jpeg', '*.png', '*.webp', '*.bmp')"
              );
            }
          },
          async yaSuo(file) {
            // 压缩到100KB,这里的100就是要压缩的大小,可自定义
            await imageConversion.compressAccurately(file, 100).then((res) => {
              // 把blob转换为文件
              let a = new File([res], `${file.name}`, { type: res.type });
              let blob = new Blob([res], { type: "image/jpeg" });
              // this.ada = window.URL.createObjectURL(blob);
              this.formData.picture = blob;
              this.pictureUrl = window.URL.createObjectURL(blob); // this.pictureUrl =
            });
          },
          // 把image 转换为 canvas对象
          imgToCanvas(image) {
            var canvas = document.createElement("canvas");
            canvas.width = image.width;
            canvas.height = image.height;
            canvas.getContext("2d").drawImage(image, 0, 0);
            this.canvasToImg(canvas);
            // return canvas;
          },
        //canvas转换为image
        canvasToImg(canvas) {
          //这个src是图片的base64流数据 一定要经过转换以后再转为文件 否则的话传给后端会出错
          var src = canvas.toDataURL("image/jpeg");
          this.ada = src;
          let arr = src.split(",");
          let mime = arr[0].match(/:(.*?);/)[1]; //设置file文件流的type名称
          let suffix = mime.split("/")[1]; //设置file文件流的name名称
          let filename;
          // atob 对经过 base-64 编码的字符串进行解码
          let bstr = window.atob(arr[1]);
          // n 是解码后的长度
          let n = bstr.length;
          // Uint8Array 数组类型表示一个 8 位无符号整型数组 初始值都是 数子0
          let u8arr = new Uint8Array(n);
          // charCodeAt() 方法可返回指定位置的字符的 Unicode 编码。这个返回值是 0 - 65535 之间的整数
          while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
          }
          // new File返回File对象 第一个参数是 ArraryBuffer 或 Bolb 或Arrary 第二个参数是文件名
          // 第三个参数是 要放到文件中的内容的 MIME 类型
          let file = new File([u8arr], `${filename}.${suffix}`, {
            type: "image/jpeg",
          });
          let min = 1024 * 1024 * 0.1;
          let max = 1024 * 1024 * 0.5;
          if (file.size > min && file.size < max) {
            this.yaSuo(file);
          } else if (file.size > max) {
            this.openCropper(file, "jpeg");
          } else {
            this.formData.picture = file;
            this.pictureUrl = window.URL.createObjectURL(file); // this.pictureUrl = file;
          }
          // this.yaSuo(file);
          // return src;
        },
        }
    </script>
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在UniApp中实现图片裁剪可以使用uni-cropper插件来完成。下面是一个简单的示例代码: 1. 首先,安装uni-cropper插件。在HBuilderX中,打开插件市场(快捷键Ctrl+Shift+P),搜索并安装uni-cropper插件。 2. 在需要使用图片裁剪功能的页面中,引入uni-cropper组件: ```vue <template> <view> <uni-cropper v-model="cropperData" @confirm="confirmCrop"></uni-cropper> <image :src="cropperData.src" mode="aspectFill" @tap="showCropper"></image> </view> </template> <script> export default { data() { return { cropperData: { src: '', // 裁剪图片的地址 mode: 'rectangle', // 裁剪框的形状,可选值有:rectangle(矩形)和 circle(圆形) sizeType: ['original', 'compressed'], // 图片选择的类型,可选值有:original(原图)和 compressed(压缩图) cropSize: { width: 200, height: 200 } // 裁剪框的大小 } } }, methods: { showCropper() { uni.chooseImage({ count: 1, success: (res) => { this.cropperData.src = res.tempFilePaths[0] } }) }, confirmCrop(res) { console.log(res) // 在这里可以处理裁剪后的结果,例如上传到服务器等操作 } } } </script> ``` 在上面的代码中,我们使用了uni-cropper组件来实现图片裁剪功能。通过选择图片按钮选择一张图片后,点击图片会打开裁剪框,裁剪完成后会触发confirm事件,我们可以在confirmCrop方法中处理裁剪后的结果。 注意:在使用uni-cropper插件之前,请确保已经安装了uni-cropper插件并引入了所需要的依赖库。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值