前端图片压缩常见的一些解决办法

 更新时间:2023年11月17日 09:56:12   作者:前端小二哥  
这篇文章主要给大家介绍了关于前端图片压缩常见的一些解决办法,图片上传是前端中常见的的业务场景,无论是前台还是后台,适当的对图片进行压缩处理,可以显著的提升用户体验,需要的朋友可以参考下

问题产生背景

在某一h5的项目,要求上传的图片格式为 base64 , 问题是用户上传的图片基本都在MB 级别,转base64 以后,图片的体积会增大30%以上,随着图片的体积增加,转换的base64 格式文件体积越大,如果此时前端不对用户上传的图片体积进行压缩,可能会导致服务器压力过大,从而崩溃;

解决办法

1、使用纯 js 解决

解决思路:

1、通过 input 文件选择框拿到要上传的图片文件file

2、FileReader.readAsDataURL() 读取 file 内容。完成后 result 属性中将包含一个 data: URL格式的 Base64字符串以表示所读取文件的内容。

3、创建一个 img 标签,将 FileReader 对象返回的 base64 格式 url 给到一个 img 标签

4、img.onload() 函数中获取图片的尺寸,再通过 canvas.drawImage() 绘制图像,设置尺寸或者图像的质量等

canvas.toDataURL(file.type, quality) 设置图像的质量,将 canvas 转换为图片 base64 格式

代码如下所示:

compressImg(file) {
    const reader = new FileReader();
        // readAsDataURL 方法会读取指定的 Blob 或 File 对象。读取操作完成的时候,readyState 会变成已完成DONE,并触发 loadend (en-US) 事件,
        // 同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。
        reader.readAsDataURL(file);
        reader.onload = () => {
          const img = new Image();
          img.src = reader.result;
          img.onload = () => {
            // 图片的宽高
            const w = img.width;
            const h = img.height;
            const canvas = document.createElement("canvas");
            // canvas对图片进行裁剪,这里设置为图片的原始尺寸
            canvas.width = w;
            canvas.height = h;
            const ctx = canvas.getContext("2d");
            // canvas中,png转jpg会变黑底,所以先给canvas铺一张白底
            ctx.fillStyle = "#fff";
            // fillRect()方法绘制一个填充了内容的矩形,这个矩形的开始点(左上点)在
            // (x, y) ,它的宽度和高度分别由width 和 height 确定,填充样式由当前的fillStyle 决定。
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            // 绘制图像
            ctx.drawImage(img, 0, 0, w, h);
            // canvas转图片达到图片压缩效果
            // 返回一个包含图片展示的 data URI base64 在指定图片格式为 image/jpeg 或 image/webp的情况下,
            // 可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,将会使用默认值 0.92。其他参数会被忽略。
            const dataUrl = canvas.toDataURL("image/jpeg", 0.8);
            // base64格式文件转成Blob文件格式
            return blobFile = dataURLtoBlob(dataUrl);
            // 拿到这个blobFile文件就可以上传给服务端
            console.log("压缩后的file----------", blobFile);
          };
        };
}
    // canvas生成的格式为base64,如果需要Blob格式可按如下进行转化
    dataURLtoBlob(dataurl) {
      const arr = dataurl.split(","),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]);
      let n = bstr.length;
      const u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new Blob([u8arr], { type: mime });
    },

使用以上方法存在缺点:

  • 压缩后的格式只能是 jpeg 格式,如果需要其他格式的可能需要优化或者用别的方法

2、插件 js-image-compressor

在使用中,我们可以根据自身需求自定义配置压缩比(quality)、输出图片类型(mimeType)、宽(width)、高(height)、最大宽(maxWidth)、最大高(maxHeight)、最小宽(minWidth)、最大高(minHeight)、png转jpeg阈值(convertSize)、是否矫正jpeg方向(redressOrientation)和是否宽松模式(loose)。

● 是否矫正jpeg方向(redressOrientation),jpeg 格式图片在某些iOS浏览器会按其方向呈现图像,这个选项可以控制恢复初始方向,默认为 true;

● 是否宽松模式(loose)、的意思是控制当压缩的图片 size 大于源图片,输出源图片,否则输出压缩后图片,默认是 true。
以下是标准配置:

var options = {
  file: file,
  quality: 0.6,
  mimeType: 'image/jpeg',
  maxWidth: 2000,
  maxHeight: 2000,
  width: 1000,
  height: 1000,
  minWidth: 500,
  minHeight: 500,
  convertSize: Infinity,
  loose: true,
  redressOrientation: true,
  // 压缩前回调
  beforeCompress: function (result) {
    console.log('压缩之前图片尺寸大小: ', result.size);
    console.log('mime 类型: ', result.type);
  },
  // 压缩成功回调
  success: function (result) {
    console.log('压缩之后图片尺寸大小: ', result.size);
    console.log('mime 类型: ', result.type);
    console.log('实际压缩率: ', ((file.size - result.size) / file.size * 100).toFixed(2) + '%');
  },
  // 发生错误
  error: function (msg) {
    console.error(msg);
  }
};
new ImageCompressor(options);

以上就是插件式的解决办法,更详细的文档,可以在 gitbhub 的官方文档上查看;插件式解决办法已经在项目中实践,推荐大家使用~~

写在最后

以上提供的插件式解决办法已经在项目中实践,但是存在的问题是,插件控制的压缩率和实际的压缩率有一定的出入(不同格式的图片出入有一定差异),因此压缩率不好严格控制

到此这篇关于前端图片压缩常见的一些解决办法的文章就介绍到这了,更多相关前端图片压缩解决内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript实现LRU算法的示例详解

    JavaScript实现LRU算法的示例详解

    不知道屏幕前的朋友们,有没有和我一样,觉得LRU算法原理很容易理解,实现起来却很复杂。所以本文就为大家整理了一下实现的示例代码,需要的可以参考一下
    2023-04-04
  • Js和VUE实现跑马灯效果

    Js和VUE实现跑马灯效果

    这篇文章主要为大家详细介绍了Js和VUE实现跑马灯效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • JS冒泡事件的快速解决方法

    JS冒泡事件的快速解决方法

    这篇文章主要是对JS冒泡事件的快速解决方法进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2013-12-12
  • JavaScript库 开发规则

    JavaScript库 开发规则

    1. 保持无侵入性,标记不想知道你的JavaScript代码;2. 严禁修改和扩展Object.prototype!;3. 对JavaScript内建对象的扩展越少越好;4. 跟随标准;5. 或着跟随主导 ;6. 保持灵活;7. 管理内存;8. 淘汰浏览器嗅探;9. 小巧更佳……
    2009-01-01
  • JavaScript实现为指定对象添加多个事件处理程序的方法

    JavaScript实现为指定对象添加多个事件处理程序的方法

    这篇文章主要介绍了JavaScript实现为指定对象添加多个事件处理程序的方法,可实现让指定对象处理多个事件的功能,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-04-04
  • 一文读懂TS 中联合类型和交叉类型各自的含义

    一文读懂TS 中联合类型和交叉类型各自的含义

    联合类型在 TypeScript 中相当流行,你可能已经用过很多次了。交叉类型稍微不那么常见,它们似乎引起更多的困惑,这篇文章主要介绍了一文读懂TS 中联合类型和交叉类型的含义,需要的朋友可以参考下
    2022-12-12
  • 原生JS实现轮播图效果

    原生JS实现轮播图效果

    这篇文章主要为大家详细介绍了原生JS实现轮播图效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • TypeScript命名空间讲解

    TypeScript命名空间讲解

    这篇文章主要介绍了TypeScript命名空间,TypeScript 是 JavaScript 的一个超集,支持 ECMAScript 6 标准。由微软开发的自由和开源的编程语言。设计目标是开发大型应用,它可以编译成纯 JavaScript,编译出来的 JavaScript 可以运行在任何浏览器上,下面来看详细内容吧

    2021-12-12
  • 基于JavaScript实现每日签到打卡轨迹功能

    基于JavaScript实现每日签到打卡轨迹功能

    这篇文章主要为大家详细介绍了基于JavaScript实现每日签到打卡轨迹功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • es6中some和every方法使用简单示例

    es6中some和every方法使用简单示例

    JavaScript在ES6版本后提供了一些更加便捷的方法供开发者使用,实现原理其实是在对应的构造函数原型提供方法,下面这篇文章主要给大家介绍了关于es6中some和every方法使用的相关资料,需要的朋友可以参考下
    2023-04-04

最新评论