2021/5/12 PC端图片裁剪及base64和blob相互切换

5 篇文章 0 订阅

需求: PC端裁剪屏幕

想法: 首先把屏幕当成一张图片,再去裁剪

 

1.首先需要下载两个插件

npm install html2canvas --save-dev   // 生成图片

npm install vue-cropper --save-dev    // 裁剪工具

 

2.开始操作

1.生成图片转换成blob-裁剪工具已准备

    // 使用html2canvas保存屏幕生成图片
    html2canvas(this.$refs.imageWrapper).then(canvas => {
          // 这里会返回一个base64但是我需要blob
          let dataURL = canvas.toDataURL("image/png");
          
          // 开始把base64转成blob
          let base64 = dataURL.split(',')[1];
          // 转码第一次html2canvas返回base64转成blob 
          base64ToBlob({b64data: base64, contentType: 'image/png'}).then(res => {
            // 转后后的blob对象-赋值给vue-cropper-裁剪工具
            this.option.img = res.preview;
            // 把裁剪图片覆盖屏幕-因为屏幕会闪一下所以采用了定时器(还是没用,笑死)
            setTimeout(() => {
              let element = document.querySelector('.vue-cropper');
              element.style.zIndex = 2;
            }, 100);
          })
      });


       // 把base64转换为blob
        function base64ToBlob ({b64data = '', contentType = '', sliceSize = 512} = {}) {
          return new Promise((resolve, reject) => {
            // 使用 atob() 方法将数据解码
            let byteCharacters = atob(b64data);
            let byteArrays = [];
            for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
              let slice = byteCharacters.slice(offset, offset + sliceSize);
              let byteNumbers = [];
              for (let i = 0; i < slice.length; i++) {
                  byteNumbers.push(slice.charCodeAt(i));
              }
              // 8 位无符号整数值的类型化数组。内容将初始化为 0。
              // 如果无法分配请求数目的字节,则将引发异常。
              byteArrays.push(new Uint8Array(byteNumbers));
            }
            let result = new Blob(byteArrays, {
              type: contentType
            })
            result = Object.assign(result,{
              // 这里一定要处理一下 URL.createObjectURL
              preview: URL.createObjectURL(result),
              name: `XXX.png`
            });

            imgInfo = result;
            resolve(result)
          })
        }

      // 这里下面是url转base64的方法------------------------------------------

      // 需要用到再使用-我没用到

      let imgUrL = `http://XXX.jpg`
      urlToBase64(imgUrL).then(res => {
          // 转化后的base64图片地址
          console.log('base64', res)
      })

     function urlToBase64(url) {
      return new Promise ((resolve,reject) => {
        let image = new Image();
        image.onload = function() {
          let canvas = document.createElement('canvas');
          canvas.width = this.naturalWidth;
          canvas.height = this.naturalHeight;
          // 将图片插入画布并开始绘制
          canvas.getContext('2d').drawImage(image, 0, 0);
          // result
          let result = canvas.toDataURL('image/png')
          resolve(result);
        };
        // CORS 策略,会存在跨域问题https://stackoverflow.com/questions/20424279/canvas-todataurl-securityerror
        image.setAttribute("crossOrigin",'Anonymous');
        image.src = url;
        // 图片加载失败的错误处理
        image.onerror = () => {
          reject(new Error('urlToBase64 error'));
      };
    }

    // 这里下面是base64转blob的方法------------------------------------------

    // 需要用到再使用-我没用到

    blobToBase64(blob).then(res => {
      // 转化后的base64
      console.log('base64', res)
    })

     blobToBase64(blob) {
          return new Promise((resolve, reject) => {
          const fileReader = new FileReader();
          fileReader.onload = (e) => {
              resolve(e.target.result);
          };
          // readAsDataURL
          fileReader.readAsDataURL(blob);
          fileReader.onerror = () => {
              reject(new Error('blobToBase64 error'));
          };
        });
      }

裁剪工具配置

<vueCropper
      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"
      :canScale="option.canScale"
      v-if="isVueCropper"
    ></vueCropper>


option: {
        img: '', // 裁剪图片的地址
        info: true, // 裁剪框的大小信息
        outputSize: 0.8, // 裁剪生成图片的质量
        outputType: 'jpeg', // 裁剪生成图片的格式
        canScale: false, // 图片是否允许滚轮缩放
        autoCrop: false, // 是否默认生成截图框
        // autoCropWidth: 300, // 默认生成截图框宽度
        // autoCropHeight: 200, // 默认生成截图框高度
        fixedBox: false, // 固定截图框大小 不允许改变
        fixed: false, // 是否开启截图框宽高固定比例
        fixedNumber: [7, 5], // 截图框的宽高比例
        full: true, // 是否输出原图比例的截图
        canMoveBox: true, // 截图框能否拖动
        original: false, // 上传图片按照原始比例渲染
        centerBox: false, // 截图框是否被限制在图片里面
        infoTrue: true // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
      },

2. 开始裁剪

// 开始裁剪
this.$refs.cropper.startCrop();  // https://github.com/xyxiao001/vue-cropper 具体方法请查看官网

3. 确认裁剪

// 动态生成html确定按钮-根据需求制作
document.querySelector('.cropper-view-box').innerHTML += `<div style="color:#fff;text-align:right;line-height:25px;cursor:pointer;position: absolute;
        bottom: -26px;
        right: 0px;" id="joblist">确定</div>`;


// 裁剪页面获取base64再次转为blob-根据需求
document.getElementById('joblist').addEventListener('click', function (ev) {
          // 获取截图的base64 数据
          that.$refs.cropper.getCropData((data) => {
            // do something
            console.log(data)
            let base64 = data.split(',')[1];
            // 转码第二次截图返回base64转成blob提供给后端
            base64ToBlob({b64data: base64, contentType: 'image/png'}).then(res => {
              // 裁剪完成之后隐藏图片-显示屏幕              
              let element = document.querySelector('.vue-cropper');
              element.style.zIndex = -1;
              
              let div = document.getElementById('joblist');
              document.querySelector('.cropper-view-box').removeChild(div);
            })
          })
  });

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值