资讯专栏INFORMATION COLUMN

Vue使用mixins手写压缩图片代码

CoXie / 2185人阅读

摘要:一介绍本文将介绍再项目中通过对图片进行压缩后使用。把图片能转换成出发事件对赋值完成,触发事件生成,调用回调函数。将图片将转成格式把转换成文件四压缩完成使用五参考链接压缩图片到以下

一、介绍

本文将介绍再Vue项目中通过js对图片进行压缩后使用。(纯前端实现,不依赖后台)

主要使用Canvas.toDataURL(type, encoderOptions)对图片大小进行调整

参数 描述
type 图片格式
encoderOptions 在指定图片格式为 image/jpeg 或 image/webp的情况下,可以从 0 到 1 的区间内选择图片的质量。
二、步骤 1.将图片转化为 base64
使用 FileReader.readAsDataURL(file):该方法会读取指定的 File 对象。读取操作完成的时候,readyState 会变成已完成(DONE),并触发 loadend 事件,同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。

reader.readAsDataURL 把图片能转换成 base64, 出发 reader.onload 事件对 image.src 赋值完成,触发 image.onload 事件生成canvas,调用回调函数。

/**
 * 将图片转化为base64
 */
imgBase64(file, callback) {
  // 看支持不支持FileReader
  if (!file || !window.FileReader) return;
  // 创建一个 Image 对象
  let image = new Image();
  // 绑定 load 事件处理器,加载完成后执行
  image.onload = function () {
    // 创建 canvas DOM 对象
    let canvas = document.createElement("canvas");
    // 返回一个用于在画布上绘图的环境, "2d" 指定了您想要在画布上绘制的类型
    let ctx = canvas.getContext("2d");
    // 如果高度超标 // 参数,最大高度
    let MAX_HEIGHT = 3000;
    if (image.height > MAX_HEIGHT) {
      // 宽度等比例缩放 *=
      image.width *= MAX_HEIGHT / image.height;
      image.height = MAX_HEIGHT;
    }
    // 获取 canvas的 2d 环境对象,
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    // 重置canvas宽高
    canvas.width = image.width;
    canvas.height = image.height;
    // 将图像绘制到canvas上
    ctx.drawImage(image, 0, 0, image.width, image.height);

    callback(image, canvas);

  };
  if (/^image/.test(file.type)) {
    // 创建一个reader
    let reader = new FileReader();
    // 读取成功后的回调
    reader.onload = function () {
      // 设置src属性,浏览器会自动加载。
      // 记住必须先绑定事件,才能设置src属性,否则会出同步问题。
      image.src = this.result;
    };
    // 将图片将转成 base64 格式
    reader.readAsDataURL(file);
  }
}
2.把base64转换成file文件
/**
 * 把base64转换成file文件
 */
convertBase64UrlToFile(dataurl, filename) {
  let arr = dataurl.split(","),
    mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]), n = bstr.length,
    u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], filename, {type: mime});
}
3.ES6 Promise的简单使用
function checkAndHandleCompression() {
  //当异步代码执行成功时,我们才会调用resolve(...), 当异步代码失败时就会调用reject(...)
  return new Promise((resolve, reject) => {
    resolve("成功!") // 代码正常执行!
  })
}

checkAndHandleCompression().then((data)=>{
  console.log(data) // print 成功!
});
4.对 Promise 填充代码,检查并压缩图片大小
如果图片过大就使用Canvas.toDataURL(type, encoderOptions)对图片进行压缩,并将结果异步返回
/**
 * 检查并压缩图片大小
 */
checkAndHandleCompression(file) {

  return new Promise((resolve, reject) => {

    this.imgBase64(file, (image, canvas) => {
      let maxSize = 2 * 1024; // 压缩到2M以下 (单位KB)
      let fileSize = file.size / 1024; // 图片大小 (单位KB)

      let uploadSrc, uploadFile;
      // 如果图片大小大于maxSize,进行压缩
      if (fileSize > maxSize) {
        uploadSrc = canvas.toDataURL(file.type, maxSize / fileSize);
        uploadFile = this.convertBase64UrlToFile(uploadSrc, file.name); // 转成file文件
      } else {
        uploadSrc = image.src;
        uploadFile = file;
      }

      let compressedSize = uploadFile.size / 1024;// 压缩后图片大小 (单位KB)
      // 判断图片大小是否小于maxSize,如果大于则继续压缩至小于为止
      if (compressedSize.toFixed(2) > maxSize) {
        this.checkAndHandleCompression(uploadFile);
      } else {
        let fileOptions = {uploadSrc, uploadFile};
        resolve(fileOptions);
      }
    });

  });

}
三、完整代码

创建mixins/image-compress.js

export default {

  methods: {
    /**
     * 检查并压缩图片大小
     */
    checkAndHandleCompression(file) {

      return new Promise((resolve, reject) => {

        this.imgBase64(file, (image, canvas) => {
          let maxSize = 2 * 1024; // 2M (单位KB)
          let fileSize = file.size / 1024; // 图片大小 (单位KB)

          let uploadSrc, uploadFile;
          // 如果图片大小大于maxSize,进行压缩
          if (fileSize > maxSize) { 
            uploadSrc = canvas.toDataURL(file.type, maxSize / fileSize); // 转换成DataURL
            uploadFile = this.convertBase64UrlToFile(uploadSrc, file.name); // 转成file文件
          } else {
            uploadSrc = image.src;
            uploadFile = file;
          }

          let compressedSize = uploadFile.size / 1024;// 压缩后图片大小 (单位KB)
          // 判断图片大小是否小于maxSize,如果大于则继续压缩至小于为止
          if (compressedSize.toFixed(2) > maxSize) {
            this.checkAndHandleUpload(uploadFile);
          } else {
            let fileOptions = {uploadSrc, uploadFile};
            resolve(fileOptions);
          }
        });

      });

    },

    /**
     * 将图片转化为base64
     */
    imgBase64(file, callback) {
      // 看支持不支持FileReader
      if (!file || !window.FileReader) return;
      // 创建一个 Image 对象
      let image = new Image();
      // 绑定 load 事件处理器,加载完成后执行
      image.onload = function () {
        // 创建 canvas DOM 对象
        let canvas = document.createElement("canvas");
        // 返回一个用于在画布上绘图的环境, "2d" 指定了您想要在画布上绘制的类型
        let ctx = canvas.getContext("2d");
        // 如果高度超标 // 参数,最大高度
        let MAX_HEIGHT = 3000;
        if (image.height > MAX_HEIGHT) {
          // 宽度等比例缩放 *=
          image.width *= MAX_HEIGHT / image.height;
          image.height = MAX_HEIGHT;
        }
        // 获取 canvas的 2d 环境对象,
        // 可以理解Context是管理员,canvas是房子
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        // 重置canvas宽高
        canvas.width = image.width;
        canvas.height = image.height;
        // 将图像绘制到canvas上
        ctx.drawImage(image, 0, 0, image.width, image.height);

        callback(image, canvas);

      };
      if (/^image/.test(file.type)) {
        // 创建一个reader
        let reader = new FileReader();
        // 读取成功后的回调
        reader.onload = function () {
          // 设置src属性,浏览器会自动加载。
          // 记住必须先绑定事件,才能设置src属性,否则会出同步问题。
          image.src = this.result;
        };
        // 将图片将转成 base64 格式
        reader.readAsDataURL(file);
      }
    },

    /**
     * 把Base64转换成file文件
     */
    convertBase64UrlToFile(dataurl, filename) {
      let arr = dataurl.split(","),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]), n = bstr.length,
        u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new File([u8arr], filename, {type: mime});
    }

  }
};
四、example


五、参考链接

js压缩图片到2m以下

MDN web docs FileReader.readAsDataURL()

MDN web docs Promise

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93426.html

相关文章

  • 小程序开发 第二篇:使用微信小程序开发者工具、wepy框架初始化项目

    摘要:上一篇小程序开发第一篇注册获取同步企业项目数据微信小程序开发者工具下载小程序开发者工具使用小程序原生开发直接使用小程序开发者工具打开项目即可小程序框架开发首选官方提供类开发框架,备选。 上一篇:小程序开发 第一篇:注册、获取unionid同步企业项目数据 1.微信小程序开发者工具 下载:小程序开发者工具 使用: 小程序原生开发:直接使用小程序开发者工具打开项目即可 小程序框架开发:...

    HitenDev 评论0 收藏0
  • 制作html5微信页面的经验总结。

    摘要:由于操作上比较多的设计都是隐性的例如滑动之类,需要手势动画作提示。如果页面是推广页面,绝大部分用户都是首次进入,而设计中的元素前端不能复现只能使用图片时,会产生加载时间较长的问题。各手机尺寸,和比例。 先罗列一下我遇到的问题: 用户可选择图片上传,但是图片比较大(基本都是2M以上),而且还得异步上传。 由于操作上比较多的设计都是隐性的例如滑动之类,需要手势动画作提示。 块内元素滚动...

    ermaoL 评论0 收藏0

发表评论

0条评论

CoXie

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<