vue-cropper GitHub项目

    vue-cropper是基于VUE实现的一个开源的图片裁剪组件。裁剪功能还不错,就是压缩功能其实没有实现效果的感觉(至少我使用时没有压缩图片效果)。所以另外找了个压缩图片的方法。组件的话就不添加了,点击链接看官网更清楚,这里重点是压缩图片的方法。

    1. // 将File(Blob)对象转变为一个dataURL字符串, 即base64格式
    2. const fileToDataURL = file => new Promise((resolve) => {
    3. const reader = new FileReader();
    4. reader.onloadend = e => resolve(e.target.result);
    5. reader.readAsDataURL(file);
    6. });
    7. // 将dataURL字符串转变为image对象,即base64转img对象
    8. const dataURLToImage = dataURL => new Promise((resolve) => {
    9. const img = new Image();
    10. img.onload = () => resolve(img);
    11. img.src = dataURL;
    12. });
    13. // 将一个canvas对象转变为一个File(Blob)对象
    14. const canvastoFile = (canvas, type, quality) => new Promise(resolve => canvas.toBlob(blob => resolve(blob), type, quality));
    15. const compress = (originfile, maxSize) => new Promise(async(resolve, reject) => {
    16. const originSize = originfile.size / 1024; // 单位为kb
    17. console.log('图片指定最大尺寸为', maxSize, '原始尺寸为:', originSize);
    18. // 将原图片转换成base64
    19. const base64 = await fileToDataURL(originfile);
    20. // 缩放图片需要的canvas
    21. const canvas = document.createElement('canvas');
    22. const context = canvas.getContext('2d');
    23. // 小于maxSize,则不需要压缩,直接返回
    24. if (originSize < maxSize) {
    25. resolve({ compressBase64: base64, compressFile: originfile });
    26. console.log(`图片小于指定大小:${maxSize}KB,不用压缩`);
    27. return;
    28. }
    29. const img = await dataURLToImage(base64);
    30. const scale = 1;
    31. const originWidth = img.width;
    32. const originHeight = img.height;
    33. const targetWidth = originWidth * scale;
    34. const targetHeight = originHeight * scale;
    35. canvas.width = targetWidth;
    36. canvas.height = targetHeight;
    37. context.clearRect(0, 0, targetWidth, targetHeight);
    38. context.drawImage(img, 0, 0, targetWidth, targetHeight);
    39. // 将Canvas对象转变为dataURL字符串,即压缩后图片的base64格式
    40. // const compressedBase64 = canvas.toDataURL('image/jpeg', 0.1);
    41. // 经过我的对比,通过scale控制图片的拉伸来压缩图片,能够压缩jpg,png等格式的图片
    42. // 通过canvastoFile方法传递quality来压缩图片,只能压缩jpeg类型的图片,png等格式不支持
    43. // scale的压缩效果没有canvastoFile好
    44. // 在压缩到指定大小时,通过scale压缩的图片比通过quality压缩的图片模糊的多
    45. // 压缩的思路,用二分法找最佳的压缩点
    46. // 这里为了规避浮点数计算的弊端,将quality转为整数再计算;
    47. // const preQuality = 100;
    48. const maxQualitySize = { quality: 100, size: Number.MAX_SAFE_INTEGER };
    49. const minQualitySize = { quality: 0, size: 0 };
    50. let quality = 100;
    51. let count = 0; // 压缩次数
    52. let compressFinish = false; // 压缩完成
    53. let invalidDesc = '';
    54. let compressBlob = null;
    55. // 二分法最多尝试8次即可覆盖全部可能
    56. while (!compressFinish && count < 12) {
    57. compressBlob = await canvastoFile(canvas, 'image/jpeg', quality / 100);
    58. const compressSize = compressBlob.size / 1024;
    59. count++;
    60. if (compressSize === maxSize) {
    61. console.log(`压缩完成,总共压缩了${count}次`);
    62. compressFinish = true;
    63. return;
    64. }
    65. if (compressSize > maxSize) {
    66. maxQualitySize.quality = quality;
    67. maxQualitySize.size = compressSize;
    68. }
    69. if (compressSize < maxSize) {
    70. minQualitySize.quality = quality;
    71. minQualitySize.size = compressSize;
    72. }
    73. console.log(`第${count}次压缩,压缩后大小${compressSize},quality参数:${quality}`);
    74. quality = Math.ceil((maxQualitySize.quality + minQualitySize.quality) / 2);
    75. if (maxQualitySize.quality - minQualitySize.quality < 2) {
    76. if (!minQualitySize.size && quality) {
    77. quality = minQualitySize.quality;
    78. } else if (!minQualitySize.size && !quality) {
    79. compressFinish = true;
    80. invalidDesc = '压缩失败,无法压缩到指定大小';
    81. console.log(`压缩完成,总共压缩了${count}次`);
    82. } else if (minQualitySize.size > maxSize) {
    83. compressFinish = true;
    84. invalidDesc = '压缩失败,无法压缩到指定大小';
    85. console.log(`压缩完成,总共压缩了${count}次`);
    86. } else {
    87. console.log(`压缩完成,总共压缩了${count}次`);
    88. compressFinish = true;
    89. quality = minQualitySize.quality;
    90. }
    91. }
    92. }
    93. if (invalidDesc) {
    94. // 压缩失败,则返回原始图片的信息
    95. console.log(`压缩失败,无法压缩到指定大小:${maxSize}KB`);
    96. reject({ msg: invalidDesc, compressBase64: base64, compressFile: originfile });
    97. return;
    98. }
    99. compressBlob = await canvastoFile(canvas, 'image/jpeg', quality / 100);
    100. const compressSize = compressBlob.size / 1024;
    101. console.log(`最后一次压缩(即第${count + 1}次),quality为:${quality},大小:${compressSize}`);
    102. const compressedBase64 = await fileToDataURL(compressBlob);
    103. const compressedFile = new File([compressBlob], originfile.name, { type: 'image/jpeg' });
    104. resolve({ compressFile: compressedFile, compressBase64: compressedBase64 });
    105. });
    106. // export default compress;

    js压缩图片到指定大小(_葱)此处详尽