UNPKG

kh-tool

Version:
784 lines (651 loc) 21 kB
import { enc } from 'crypto-js'; /** * 把文件读取成 base64 格式 * @param file 文件对象 */ function FileToBase64(file) { var reading = new FileReader(); return new Promise(function (resolve, reject) { reading.onload = function (event) { var _event$target; return resolve((event === null || event === void 0 ? void 0 : (_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.result) || null); }; reading.onerror = function () { return reject(new Error("文件读取失败")); }; reading.readAsDataURL(file); }); } function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function (obj) { return typeof obj; }; } else { _typeof = function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } /** * 将base64转换为文件对象 * @param base64 base64格式的编码 * @param getFile 获得 File 的结果吗 */ function Base64ToFile(base64) { var getFile = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; try { var _base64$split = base64.split(","), _base64$split2 = _slicedToArray(_base64$split, 2), typeStr = _base64$split2[0], atobStr = _base64$split2[1]; var matchRst = typeStr.match(/:(.*?);/); var mime = matchRst ? matchRst[1] : function () { throw new Error("未捕获到结果"); }(); var bstr = atob(atobStr); var n = bstr.length; var u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } var filename = "".concat(mime.replace("/", ".")); return getFile ? new File([u8arr], filename, { type: mime }) : new Blob([u8arr], { type: mime }); } catch (error) { return error; } } /** * 把文件读取成 ArrayBuffer格式 * @param file 文件对象 */ function FileToArrayBuffer(file) { var reading = new FileReader(); return new Promise(function (resolve, reject) { reading.onload = function (event) { var _event$target; return resolve((event === null || event === void 0 ? void 0 : (_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.result) || null); }; reading.onerror = function () { return reject(new Error("文件读取失败")); }; reading.readAsArrayBuffer(file); }); } function GetType(val) { return Object.prototype.toString.call(val).toLowerCase().replace(/\[object\s|]/g, ""); } function GetTypeOf(val, type) { return GetType(val) === type; } /** * 不是空数组 */ function NoEmptyArr(param) { return !!param && param instanceof Array && param.length !== 0; } /** * 不为空值 */ function NoEmpty(value) { if (value === null || value === "" || value === "undefined" || value === undefined || value === "null") { return false; } if (typeof value === "string") { value = value.replace(/\s/g, ""); if (value == "") { return false; } } return true; } /** * 是 JSON 字符串 * @param str */ function IsJsonString(str) { try { _typeof(JSON.parse(str)) == "object"; return true; } catch (_unused) { return false; } } /** * 是 URL 字符串 * @param str */ var IsUrlStr = function IsUrlStr(url) { try { return new URL(url); } catch (error) { return false; } }; // function var k = 0; /** * diff Object 的格式 */ function DiffType(one, other) { console.log(k++, one, other); if (GetTypeOf(one, "object") && GetTypeOf(other, "object")) { for (var i in one) { if (!one[i] || !other[i]) { return false; } if (GetTypeOf(one[i], "object") && GetTypeOf(other[i], "object")) { if (!DiffType(one[i], other[i])) { return false; } } } } return true; } function IdRandom() { var num = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 10; return Math.random().toString(36).substr(2, num); } /** * 主要用于格式化数字 * eg: 1234567 => 1,234,567 */ function FormatNumber(str) { return str.replace(/\B(?=(\d{3})+(?!\d))/g, ","); } /** * 将数字每3位之间用逗号分割,例如12345.22格式化为 12,345.22 * @param {String} s 要格式化的数值 * @param {Number} n 保留小数的位数 */ function FormatNumber2Decimal(s) { var n = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2; var decimal = n > 0 && n <= 20 ? n : 2; var _s$split = s.split("."), _s$split2 = _slicedToArray(_s$split, 2), front = _s$split2[0], _s$split2$ = _s$split2[1], back = _s$split2$ === void 0 ? "" : _s$split2$; return [FormatNumber(front), back.substr(0, decimal).padEnd(decimal, "0")].join("."); } var Base64 = enc.Base64, Utf8 = enc.Utf8; function StrToBase64(str) { return Base64.stringify(Utf8.parse(str)); } function StrFromBase64(str) { return Base64.parse(str).toString(Utf8); } /** 解析为url路径str专用 */ function StrToUrlStr(str) { return StrToBase64(str).replace(/\//g, "-").replace(/=/g, "_"); } /** 从url路径str解析原意专用 */ function StrFromUrlStr(str) { return StrFromBase64(str.replace(/-/g, "/").replace(/_/g, "=")); } /** * 命名法: * kebab 串式 asd-fgh * snake 蛇形 asd_fgh * Camel 驼峰命名法 AsdFgh * upperCamel 大驼峰命名法 同 Camel * lowerCamel 小驼峰命名法 asdFgh */ /** 短横线转换为驼峰(大驼峰) */ function Kebab2Camel(s) { return s.replace(/(^|-)(\w)/g, function (all, $1, $2) { return $2.toUpperCase(); }); } /** 短横线转换为小驼峰 */ function Kebab2lowerCamel(s) { return s.replace(/-(\w)/g, function (all, $1) { return $1.toUpperCase(); }); } /** 下划线转换为驼峰 */ function Snake2Camel(s) { return s.replace(/(^|_)(\w)/g, function (all, $1, $2) { return $2.toUpperCase(); }); } /** 下划线转换为小驼峰 */ function Snake2lowerCamel(s) { return s.replace(/_(\w)/g, function (all, $1) { return $1.toUpperCase(); }); } /** 驼峰转换为短横线 */ function Camel2Kebab(s) { return s.replace(/\w([A-Z])/g, "-$1").toLowerCase(); } /** 驼峰转换为下划线 */ function Camel2Snake(s) { return s.replace(/\w([A-Z])/g, "_$1").toLowerCase(); } /** * Mega pixel image rendering library for iOS6 Safari * * Fixes iOS6 Safari's image file rendering issue for large size image (over mega-pixel), * which causes unexpected subsampling when drawing it in canvas. * By using this library, you can safely render the image with proper stretching. * * Copyright (c) 2012 Shinichi Tomita <shinichi.tomita@gmail.com> * Released under the MIT license */ /** * Detect subsampling in loaded image. * In iOS, larger images than 2M pixels may be subsampled in rendering. */ function detectSubsampling(img) { var iw = img.naturalWidth; var ih = img.naturalHeight; if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image var canvas = document.createElement("canvas"); canvas.width = canvas.height = 1; var ctx = canvas.getContext("2d"); ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(img, -iw + 1, 0); // subsampled image becomes half smaller in rendering size. // check alpha channel value to confirm image is covering edge pixel or not. // if alpha value is 0 image is not covering, hence subsampled. return (ctx === null || ctx === void 0 ? void 0 : ctx.getImageData(0, 0, 1, 1).data[3]) === 0; } else { return false; } } /** * Detecting vertical squash in loaded image. * Fixes a bug which squash image vertically while drawing into canvas for some images. */ function detectVerticalSquash(img, iw, ih) { var canvas = document.createElement("canvas"); canvas.width = 1; canvas.height = ih; var ctx = canvas.getContext("2d"); ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(img, 0, 0); var data = ctx === null || ctx === void 0 ? void 0 : ctx.getImageData(0, 0, 1, ih).data; // search image edge pixel position in case it is squashed vertically. var sy = 0; var ey = ih; var py = ih; while (py > sy) { var alpha = data === null || data === void 0 ? void 0 : data[(py - 1) * 4 + 3]; if (alpha === 0) { ey = py; } else { sy = py; } py = ey + sy >> 1; } var ratio = py / ih; return ratio === 0 ? 1 : ratio; } /** * Rendering image element (with resizing) and get its data URL */ function renderImageToDataURL(img, options, doSquash) { var canvas = document.createElement("canvas"); renderImageToCanvas(img, canvas, options, doSquash); // return canvas.toDataURL("image/jpeg", options.quality || 0.8); return canvas.toDataURL(options, options.quality || 0.8); } /** * Rendering image element (with resizing) into the canvas element */ function renderImageToCanvas(img, canvas, options, doSquash) { var iw = img.naturalWidth; var ih = img.naturalHeight; if (!(iw + ih)) return; var width = options.width; var height = options.height; var ctx = canvas.getContext("2d"); ctx === null || ctx === void 0 ? void 0 : ctx.save(); transformCoordinate(canvas, ctx, width, height, options.orientation); var subsampled = detectSubsampling(img); if (subsampled) { iw /= 2; ih /= 2; } var d = 1024; // size of tiling canvas var tmpCanvas = document.createElement("canvas"); tmpCanvas.width = tmpCanvas.height = d; var tmpCtx = tmpCanvas.getContext("2d"); var vertSquashRatio = doSquash ? detectVerticalSquash(img, iw, ih) : 1; var dw = Math.ceil(d * width / iw); var dh = Math.ceil(d * height / ih / vertSquashRatio); var sy = 0; var dy = 0; while (sy < ih) { var sx = 0; var dx = 0; while (sx < iw) { var _tmpCtx, _tmpCtx2; (_tmpCtx = tmpCtx) === null || _tmpCtx === void 0 ? void 0 : _tmpCtx.clearRect(0, 0, d, d); (_tmpCtx2 = tmpCtx) === null || _tmpCtx2 === void 0 ? void 0 : _tmpCtx2.drawImage(img, -sx, -sy); ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(tmpCanvas, 0, 0, d, d, dx, dy, dw, dh); sx += d; dx += dw; } sy += d; dy += dh; } ctx === null || ctx === void 0 ? void 0 : ctx.restore(); tmpCanvas = tmpCtx = null; } /** * Transform canvas coordination according to specified frame size and orientation * Orientation value is from EXIF tag */ function transformCoordinate(canvas, ctx, width, height, orientation) { switch (orientation) { case 5: case 6: case 7: case 8: canvas.width = height; canvas.height = width; break; default: canvas.width = width; canvas.height = height; } switch (orientation) { case 2: // horizontal flip ctx === null || ctx === void 0 ? void 0 : ctx.translate(width, 0); ctx === null || ctx === void 0 ? void 0 : ctx.scale(-1, 1); break; case 3: // 180 rotate left ctx === null || ctx === void 0 ? void 0 : ctx.translate(width, height); ctx === null || ctx === void 0 ? void 0 : ctx.rotate(Math.PI); break; case 4: // vertical flip ctx === null || ctx === void 0 ? void 0 : ctx.translate(0, height); ctx === null || ctx === void 0 ? void 0 : ctx.scale(1, -1); break; case 5: // vertical flip + 90 rotate right ctx === null || ctx === void 0 ? void 0 : ctx.rotate(0.5 * Math.PI); ctx === null || ctx === void 0 ? void 0 : ctx.scale(1, -1); break; case 6: // 90 rotate right ctx === null || ctx === void 0 ? void 0 : ctx.rotate(0.5 * Math.PI); ctx === null || ctx === void 0 ? void 0 : ctx.translate(0, -height); break; case 7: // horizontal flip + 90 rotate right ctx === null || ctx === void 0 ? void 0 : ctx.rotate(0.5 * Math.PI); ctx === null || ctx === void 0 ? void 0 : ctx.translate(width, -height); ctx === null || ctx === void 0 ? void 0 : ctx.scale(-1, 1); break; case 8: // 90 rotate left ctx === null || ctx === void 0 ? void 0 : ctx.rotate(-0.5 * Math.PI); ctx === null || ctx === void 0 ? void 0 : ctx.translate(-width, 0); break; } } var URL$1 = globalThis.URL || globalThis.webkitURL || null; /** * MegaPixImage class */ var MegaPixImage = /*#__PURE__*/function () { function MegaPixImage(param) { var _this = this; _classCallCheck(this, MegaPixImage); var srcImage; if (globalThis.Blob && param instanceof Blob) { if (!URL$1) { throw Error("No createObjectURL function found to create blob url"); } var img = new Image(); img.src = URL$1.createObjectURL(param); this.blob = param; srcImage = img; } else { srcImage = param; } if (!srcImage.naturalWidth && !srcImage.naturalHeight) { srcImage.onload = srcImage.onerror = function () { var listeners = _this.imageLoadListeners; if (listeners) { _this.imageLoadListeners = null; for (var i = 0, len = listeners.length; i < len; i++) { listeners[i](); } } }; this.imageLoadListeners = []; } this.srcImage = srcImage; } /** * Rendering megapix image into specified target element */ _createClass(MegaPixImage, [{ key: "render", value: function render(target, options) { var _this2 = this; var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () { return ""; }; if (this.imageLoadListeners) { this.imageLoadListeners.push(function () { _this2.render(target, options, callback); }); return; } options = options || {}; var imgWidth = this.srcImage.naturalWidth; var imgHeight = this.srcImage.naturalHeight; var width = options.width; var height = options.height; var maxWidth = options.maxWidth; var maxHeight = options.maxHeight; var doSquash = !this.blob || this.blob.type === "image/jpeg"; if (width && !height) { height = imgHeight * width / imgWidth << 0; } else if (height && !width) { width = imgWidth * height / imgHeight << 0; } else { width = imgWidth; height = imgHeight; } if (maxWidth && width > maxWidth) { width = maxWidth; height = imgHeight * width / imgWidth << 0; } if (maxHeight && height > maxHeight) { height = maxHeight; width = imgWidth * height / imgHeight << 0; } var opt = { width: width, height: height }; for (var k in options) { opt[k] = options[k]; } var tagName = target.tagName.toLowerCase(); if (tagName === "img") { target.src = renderImageToDataURL(this.srcImage, opt, doSquash); } else if (tagName === "canvas") { renderImageToCanvas(this.srcImage, target, opt, doSquash); } // if (typeof this.onrender === "function") { // this.onrender(target); // } callback(); if (this.blob) { this.blob = null; URL$1 === null || URL$1 === void 0 ? void 0 : URL$1.revokeObjectURL(this.srcImage.src); } } }]); return MegaPixImage; }(); /** * @description 图片压缩的最核心的步骤——压缩 * @param image Image对象 dom * @param options.max_length 设置压缩的图片的最长边 * @param options.quality 压缩质量 */ function MinImg(image) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var max_length = options.max_length, quality = options.quality, _options$type = options.type, type = _options$type === void 0 ? "image/jpeg" : _options$type; var canvas = document.createElement("canvas"); var c_width = image.width; var c_height = image.height; if (max_length) { var bl; if (c_width > c_height) { bl = c_width / c_height; c_width = max_length; c_height = c_width / bl; } else { bl = c_height / c_width; c_height = max_length; c_width = c_height / bl; } } canvas.width = c_width; canvas.height = c_height; // const mpimg = canvas.getContext("2d"); // mpimg.drawImage(imageObj, 0, 0, c_width, c_height); var mpimg = new MegaPixImage(image); mpimg.render(canvas, { width: c_width, height: c_height, quality: quality, type: type }); var imgFile = canvas.toDataURL(type, quality); var getZipRstFile = Base64ToFile(imgFile); if (getZipRstFile instanceof File || getZipRstFile instanceof Blob) { return getZipRstFile; } else { throw getZipRstFile; } } /** * @description 压缩图片 * @param file 文件 * @param options 文件 * @use 读取文件方法示例 * js async写法 * ```js * async getFile(e) { * const file = e.target.files[0]; * let zipFile = await getZipImg(file); * console.log(zipFile); * } * ``` * ts Promise链写法 * ```ts * getFile(e: any) { * const file = e.target.files[0]; * console.log(file); // 压缩前 * ZipImg(file, { quality: 0.1, type: "image/webp" }) * .then((resp: File | Blob) => { * console.log(resp); // 压缩后 * }) * } * ``` */ function ZipImg(file) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { quality: 0.8 }; var reading = new FileReader(); var imageObj = new Image(); return new Promise(function (resolve, reject) { reading.onload = function (event) { var _event$target; var rst = (_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.result; imageObj.src = rst; imageObj.onload = function () { var ImgFile = MinImg(imageObj, options); return resolve(ImgFile); }; }; reading.onerror = function () { reject(new Error("图片加载失败")); }; reading.readAsDataURL(file); }); } export { Base64ToFile, Camel2Kebab, Camel2Snake, DiffType, FileToArrayBuffer, FileToBase64, FormatNumber, FormatNumber2Decimal, GetType, GetTypeOf, IdRandom, IsJsonString, IsUrlStr, Kebab2Camel, Kebab2lowerCamel, MinImg, NoEmpty, NoEmptyArr, Snake2Camel, Snake2lowerCamel, StrFromBase64, StrFromUrlStr, StrToBase64, StrToUrlStr, ZipImg };