评论

收藏

[Ruby] Vue实现压缩剪贴板图片功能

编程语言 编程语言 发布于:2025-08-02 22:30 | 阅读数:122 | 评论:0

QQ或微信发送截图时都会对截图进行压缩,目的是为了预防存在剪切板中图片过大,产生上传速度慢问题,这里我们使用vue来试试实现对剪贴板中的图片进行压缩的功能。

实现思路
  • 监听剪切板粘贴事件
  • 从事件回调中获取clipboardData中的image对象声明一个变量接收该对象
  • 使用reader.readAsDataURL方法加载clipboardData中的image对象
  • 在reader.onload回调中获取图片base64码
  • 创建Image对象,赋值图片base64码至当前对象的src属性
  • 调用Image对象的onload函数,获取图片宽高等信息
  • 声明canvas画布宽高分别为当前图片宽高除以缩放比例的值
  • 使用drawImage方法绘制当前图片

实现过程
监听剪切板粘贴事件: 实现图片粘贴
const that = this;
document.body.addEventListener('paste', function (event) {
  that.$fullScreenLoading.show("读取图片中");
  // 获取当前输入框内的文字
  const oldText = that.$refs.msgInputContainer.textContent;
  // 读取图片
  let items = event.clipboardData && event.clipboardData.items;
  let file = null;
  if (items && items.length) {
    // 检索剪切板items
    for (let i = 0; i < items.length; i++) {
      if (items[i].type.indexOf('image') !== -1) {
        file = items[i].getAsFile();
        break;
      }
    }
  }
  // 预览图片
  const reader = new FileReader();
  reader.onload = function(event) {
    // 图片内容
    const imgContent = event.target.result;
    // 创建img标签
    let img = document.createElement('img');
    // 获取当前base64图片信息,计算当前图片宽高以及压缩比例
    let imgObj = new Image();
    let imgWidth = "";
    let imgHeight = "";
    let scale = 1;
    imgObj.src = imgContent;
    imgObj.onload = function() {
      // 计算img宽高
      if(this.width<400){
        imgWidth = this.width;
        imgHeight = this.height;
      }else{
        // 输入框图片显示缩小10倍
        imgWidth = this.width/10;
        imgHeight = this.height/10;
        // 图片宽度大于1920,图片压缩5倍
        if(this.width>1920){
          // 真实比例缩小5倍
          scale = 5;
        }
      }
      // 设置可编辑div中图片宽高
      img.width = imgWidth;
      img.height = imgHeight;
      // 压缩图片,渲染页面
      that.compressPic(imgContent,scale,function (newBlob,newBase) {
        // 删除可编辑div中的图片名称
        that.$refs.msgInputContainer.textContent = oldText;
        img.src = newBase; //设置链接
        // 图片渲染
        that.$refs.msgInputContainer.append(img);
        that.$fullScreenLoading.hide();
      });
    };
  };
  reader.readAsDataURL(file);
});

使用base64压缩图片

// 参数: base64地址,压缩比例,回调函数(返回压缩后图片的blob和base64)
compressPic:function(base64, scale, callback){
  const that = this;
  let _img = new Image();
  _img.src = base64;
  _img.onload = function() {
    let _canvas = document.createElement("canvas");
    let w = this.width / scale;
    let h = this.height / scale;
    _canvas.setAttribute("width", w);
    _canvas.setAttribute("height", h);
    _canvas.getContext("2d").drawImage(this, 0, 0, w, h);
    let base64 = _canvas.toDataURL("image/jpeg");
    // 当canvas对象的原型中没有toBlob方法的时候,手动添加该方法
    if (!HTMLCanvasElement.prototype.toBlob) {
      Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
        value: function (callback, type, quality) {
          let binStr = atob(this.toDataURL(type, quality).split(',')[1]),
            len = binStr.length,
            arr = new Uint8Array(len);
          for (let i = 0; i < len; i++) {
            arr[i] = binStr.charCodeAt(i);
          }
          callback(new Blob([arr], {type: type || 'image/png'}));
        }
      });
    }else{
      _canvas.toBlob(function(blob) {
        if(blob.size > 1024*1024){
          that.compressPic(base64, scale, callback);
        }else{
          callback(blob, base64);
        }
      }, "image/jpeg");
    }
  }
}