UNPKG

imgfunc

Version:

图片上传JS

162 lines (155 loc) 5.2 kB
import { calcBASE64length } from "./lib"; import createImage from "./image"; import { COMPRESSERROR } from "./errorType"; import {STATIC_TIMEOUT, STATIC_RESPONSE_ERROR, STATIC_FILE_ERROR, STATIC_COMPRESS_ERROR, STATIC_EXCHANGE_ERROR} from './statusEnum' // 默认最大质量 const defaultMaxQuality = 100; // 默认最小的压缩质量 const defaultMinQuality = 0; // 大图质量压成小图 差率 1kb ;比如规定最大2*1024*1024图片,3M的图片在向下压缩时允许最小2*1024*1024-1024 const defaultCompressDiff = 1024; const CANVAS = document.createElement("canvas"); const CTX = CANVAS.getContext("2d"); /** * 压缩图片 * @param {*} param0 */ function imageTODataURL({ img, quality, fileType }) { const width = (CANVAS.width = img.width); const height = (CANVAS.height = img.height); CTX.clearRect(0, 0, width, height); CTX.drawImage(img, 0, 0, width, height); const base64 = CANVAS.toDataURL(fileType, quality / 100); CANVAS.width = 0; CANVAS.height = 0; return base64; } /** * 图片压缩算法 * @param {*} param0 */ const compressImage = ({ base64: base64Image, maxSize, fileType, quality: defaultQuality }) => { let compressBase64 = base64Image; // 最大的压缩率 let compressMaxQuality = defaultMaxQuality; // 最小压缩率 let compressMinQuality = defaultMinQuality; // 压缩得到最小的图片base64 let minCompressBase = null; return new Promise((resolve, reject) => { const compressRecursion = ({ base64, quality }) => { try { createImage(base64) .then(image => { // 将图片的类型统一转换 指定类型 默认 JPEG, compressBase64 = imageTODataURL({ img: image, quality, fileType }); const compressSize = calcBASE64length(compressBase64); if (compressSize > maxSize) { compressMaxQuality = quality; const diffQuality = compressMaxQuality - compressMinQuality; if (diffQuality <= 2) { if (!minCompressBase) { // TODO: 上传图片大小限制较小时,存在一轮压缩无法达到目的.这是考虑等比例压缩图片而非质量压缩 resolve({ result: true, base64: compressBase64 }); } else { resolve({ result: true, base64: minCompressBase || compressBase64 }); } } else { const compressQuality = Math.ceil( (compressMaxQuality + compressMinQuality) / 2 ); compressRecursion({ base64: compressBase64, quality: compressQuality }); } } else { minCompressBase = base64; if (compressSize < maxSize) { compressMaxQuality = 2 * quality > 100 ? 100 : 2 * quality; compressMinQuality = quality; const compressQuality = Math.ceil( (compressMaxQuality + compressMinQuality) / 2 ); compressRecursion({ base64: compressBase64, quality: compressQuality }); } else { resolve({ result: true, base64: compressBase64 }); } } }) .catch(error => { reject({ errorMsg: error, // 给开发者看的 message: "图片压缩出错了", errorType: COMPRESSERROR, status:STATIC_COMPRESS_ERROR }); }); } catch (err) { reject({ errorMsg: err, // 给开发者看的 message: "图片压缩出错了", errorType: COMPRESSERROR, status:STATIC_COMPRESS_ERROR }); } }; compressRecursion({ base64: base64Image, quality: defaultQuality }); }); }; export default async ({ base64, maxSize, fileType }) => { // 计算base64大小 const size = calcBASE64length(base64); if (size > maxSize) { // 执行压缩 const maxQuality = defaultMaxQuality; const minQuality = defaultMinQuality; const quality = Math.ceil((maxQuality + minQuality) / 2); try { const compressBase64 = await compressImage({ base64, maxSize, fileType, quality }); if (compressBase64.result) { const { base64: compressImage } = compressBase64; return { result: true, base64: compressImage }; } else { return { errorMsg: "代码错误", // 给开发者看的 message: "图片压缩出错了", errorType: COMPRESSERROR, status:STATIC_COMPRESS_ERROR }; } } catch (error) { return { errorMsg: error, // 给开发者看的 message: "图片压缩出错了", errorType: COMPRESSERROR, status:STATIC_COMPRESS_ERROR }; } } else { return { result: true, base64: base64 }; } };