sculp-js 1.13.3-beta.0 → 1.13.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/_virtual/_commonjsHelpers.js +3 -3
- package/dist/cjs/array.js +36 -46
- package/dist/cjs/async.js +41 -43
- package/dist/cjs/base64.js +77 -66
- package/dist/cjs/clipboard.js +54 -53
- package/dist/cjs/cloneDeep.js +90 -91
- package/dist/cjs/cookie.js +27 -30
- package/dist/cjs/date.js +101 -98
- package/dist/cjs/dom.js +114 -121
- package/dist/cjs/download.js +77 -78
- package/dist/cjs/easing.js +29 -32
- package/dist/cjs/file.js +147 -152
- package/dist/cjs/func.js +64 -78
- package/dist/cjs/index.js +1 -3
- package/dist/cjs/math.js +32 -38
- package/dist/cjs/node_modules/bezier-easing/src/index.js +35 -23
- package/dist/cjs/number.js +58 -61
- package/dist/cjs/object.js +112 -126
- package/dist/cjs/path.js +39 -43
- package/dist/cjs/qs.js +34 -41
- package/dist/cjs/random.js +31 -34
- package/dist/cjs/string.js +62 -63
- package/dist/cjs/tooltip.js +66 -69
- package/dist/cjs/tree.js +265 -263
- package/dist/cjs/type.js +42 -46
- package/dist/cjs/unique.js +39 -42
- package/dist/cjs/url.js +47 -48
- package/dist/cjs/validator.js +38 -38
- package/dist/cjs/variable.js +27 -21
- package/dist/cjs/watermark.js +78 -67
- package/dist/esm/array.js +36 -46
- package/dist/esm/async.js +41 -43
- package/dist/esm/base64.js +77 -66
- package/dist/esm/clipboard.js +55 -54
- package/dist/esm/cloneDeep.js +90 -91
- package/dist/esm/cookie.js +27 -30
- package/dist/esm/date.js +101 -98
- package/dist/esm/dom.js +114 -121
- package/dist/esm/download.js +78 -79
- package/dist/esm/easing.js +29 -32
- package/dist/esm/file.js +147 -152
- package/dist/esm/func.js +64 -78
- package/dist/esm/index.js +96 -8
- package/dist/esm/math.js +32 -38
- package/dist/esm/number.js +58 -61
- package/dist/esm/object.js +124 -127
- package/dist/esm/path.js +39 -43
- package/dist/esm/qs.js +34 -41
- package/dist/esm/random.js +31 -34
- package/dist/esm/string.js +74 -64
- package/dist/esm/tooltip.js +66 -69
- package/dist/esm/tree.js +265 -263
- package/dist/esm/type.js +68 -47
- package/dist/esm/unique.js +39 -42
- package/dist/esm/url.js +47 -48
- package/dist/esm/validator.js +56 -39
- package/dist/esm/variable.js +27 -21
- package/dist/esm/watermark.js +79 -68
- package/dist/types/array.d.ts +0 -1
- package/dist/types/async.d.ts +0 -1
- package/dist/types/base64.d.ts +0 -1
- package/dist/types/clipboard.d.ts +0 -1
- package/dist/types/cloneDeep.d.ts +0 -1
- package/dist/types/cookie.d.ts +0 -1
- package/dist/types/date.d.ts +0 -1
- package/dist/types/dom.d.ts +0 -1
- package/dist/types/download.d.ts +0 -1
- package/dist/types/easing.d.ts +0 -1
- package/dist/types/file.d.ts +0 -1
- package/dist/types/func.d.ts +0 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/math.d.ts +0 -1
- package/dist/types/number.d.ts +0 -1
- package/dist/types/object.d.ts +0 -1
- package/dist/types/path.d.ts +0 -1
- package/dist/types/qs.d.ts +0 -1
- package/dist/types/random.d.ts +0 -1
- package/dist/types/string.d.ts +0 -1
- package/dist/types/tooltip.d.ts +0 -1
- package/dist/types/tree.d.ts +2 -2
- package/dist/types/type.d.ts +0 -1
- package/dist/types/unique.d.ts +0 -1
- package/dist/types/url.d.ts +0 -1
- package/dist/types/validator.d.ts +0 -1
- package/dist/types/variable.d.ts +0 -1
- package/dist/types/watermark.d.ts +0 -1
- package/dist/umd/index.min.js +2 -2
- package/package.json +12 -6
- package/dist/types/array.d.ts.map +0 -1
- package/dist/types/async.d.ts.map +0 -1
- package/dist/types/base64.d.ts.map +0 -1
- package/dist/types/clipboard.d.ts.map +0 -1
- package/dist/types/cloneDeep.d.ts.map +0 -1
- package/dist/types/cookie.d.ts.map +0 -1
- package/dist/types/core-index.d.ts +0 -17
- package/dist/types/core-index.d.ts.map +0 -1
- package/dist/types/date.d.ts.map +0 -1
- package/dist/types/dom.d.ts.map +0 -1
- package/dist/types/download.d.ts.map +0 -1
- package/dist/types/easing.d.ts.map +0 -1
- package/dist/types/file.d.ts.map +0 -1
- package/dist/types/func.d.ts.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -3278
- package/dist/types/math.d.ts.map +0 -1
- package/dist/types/number.d.ts.map +0 -1
- package/dist/types/object.d.ts.map +0 -1
- package/dist/types/path.d.ts.map +0 -1
- package/dist/types/qs.d.ts.map +0 -1
- package/dist/types/random.d.ts.map +0 -1
- package/dist/types/string.d.ts.map +0 -1
- package/dist/types/tooltip.d.ts.map +0 -1
- package/dist/types/tree.d.ts.map +0 -1
- package/dist/types/type.d.ts.map +0 -1
- package/dist/types/unique.d.ts.map +0 -1
- package/dist/types/url.d.ts.map +0 -1
- package/dist/types/validator.d.ts.map +0 -1
- package/dist/types/variable.d.ts.map +0 -1
- package/dist/types/watermark.d.ts.map +0 -1
package/dist/esm/download.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.13.
|
|
2
|
+
* sculp-js v1.13.6
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { isFunction,
|
|
7
|
+
import { isFunction, isNullOrUnDef, isString } from './type.js';
|
|
8
8
|
import { urlSetParams } from './url.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -13,7 +13,7 @@ import { urlSetParams } from './url.js';
|
|
|
13
13
|
* @param {LooseParams} params
|
|
14
14
|
*/
|
|
15
15
|
function downloadURL(url, params) {
|
|
16
|
-
|
|
16
|
+
window.open(params ? urlSetParams(url, params) : url);
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* 通过 A 链接的方式下载
|
|
@@ -22,20 +22,20 @@ function downloadURL(url, params) {
|
|
|
22
22
|
* @param {Function} callback
|
|
23
23
|
*/
|
|
24
24
|
function downloadHref(href, filename, callback) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
25
|
+
let eleLink = document.createElement('a');
|
|
26
|
+
eleLink.download = filename;
|
|
27
|
+
eleLink.style.display = 'none';
|
|
28
|
+
eleLink.href = href;
|
|
29
|
+
document.body.appendChild(eleLink);
|
|
30
|
+
eleLink.click();
|
|
31
|
+
setTimeout(() => {
|
|
32
|
+
document.body.removeChild(eleLink);
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
eleLink = null;
|
|
35
|
+
if (isFunction(callback)) {
|
|
36
|
+
callback();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
41
|
* 将大文件对象通过 A 链接的方式下载
|
|
@@ -44,14 +44,14 @@ function downloadHref(href, filename, callback) {
|
|
|
44
44
|
* @param {Function} callback
|
|
45
45
|
*/
|
|
46
46
|
function downloadBlob(blob, filename, callback) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
const objURL = URL.createObjectURL(blob);
|
|
48
|
+
downloadHref(objURL, filename);
|
|
49
|
+
setTimeout(() => {
|
|
50
|
+
URL.revokeObjectURL(objURL);
|
|
51
|
+
if (isFunction(callback)) {
|
|
52
|
+
callback();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
55
|
}
|
|
56
56
|
/**
|
|
57
57
|
* 根据URL下载文件(解决跨域a.download不生效问题)
|
|
@@ -64,34 +64,36 @@ function downloadBlob(blob, filename, callback) {
|
|
|
64
64
|
* @param {CrossOriginDownloadParams} options
|
|
65
65
|
*/
|
|
66
66
|
function crossOriginDownload(url, filename, options) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
67
|
+
const {
|
|
68
|
+
successCode = 200,
|
|
69
|
+
successCallback,
|
|
70
|
+
failCallback
|
|
71
|
+
} = isNullOrUnDef(options) ? { successCode: 200, successCallback: void 0, failCallback: void 0 } : options;
|
|
72
|
+
const xhr = new XMLHttpRequest();
|
|
73
|
+
xhr.open('GET', url, true);
|
|
74
|
+
xhr.responseType = 'blob';
|
|
75
|
+
xhr.onload = function () {
|
|
76
|
+
if (xhr.status === successCode) downloadBlob(xhr.response, filename, successCallback);
|
|
77
|
+
else if (isFunction(failCallback)) {
|
|
78
|
+
const status = xhr.status;
|
|
79
|
+
const responseType = xhr.getResponseHeader('Content-Type');
|
|
80
|
+
if (isString(responseType) && responseType.includes('application/json')) {
|
|
81
|
+
const reader = new FileReader();
|
|
82
|
+
reader.onload = () => {
|
|
83
|
+
failCallback({ status, response: reader.result });
|
|
84
|
+
};
|
|
85
|
+
reader.readAsText(xhr.response);
|
|
86
|
+
} else {
|
|
87
|
+
failCallback(xhr);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
xhr.onerror = e => {
|
|
92
|
+
if (isFunction(failCallback)) {
|
|
93
|
+
failCallback({ status: 0, code: 'ERROR_CONNECTION_REFUSED' });
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
xhr.send();
|
|
95
97
|
}
|
|
96
98
|
/**
|
|
97
99
|
* 将指定数据格式通过 A 链接的方式下载
|
|
@@ -101,32 +103,29 @@ function crossOriginDownload(url, filename, options) {
|
|
|
101
103
|
* @param {string[]} [headers]
|
|
102
104
|
*/
|
|
103
105
|
function downloadData(data, fileType, filename, headers) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const href = 'data:' + MIMETypes[fileType] + ';charset=utf-8,\ufeff' + encodeURIComponent(headerStr + bodyStr);
|
|
128
|
-
downloadHref(href, filename);
|
|
129
|
-
}
|
|
106
|
+
filename = filename.replace(`.${fileType}`, '') + `.${fileType}`;
|
|
107
|
+
if (fileType === 'json') {
|
|
108
|
+
const blob = new Blob([JSON.stringify(data, null, 4)]);
|
|
109
|
+
downloadBlob(blob, filename);
|
|
110
|
+
} else {
|
|
111
|
+
// xlsx实际生成的也为csv,仅后缀名名不同
|
|
112
|
+
if (!headers || !headers.length) throw new Error('未传入表头数据');
|
|
113
|
+
if (!Array.isArray(data)) throw new Error('data error! expected array!');
|
|
114
|
+
const headerStr = headers.join(',') + '\n';
|
|
115
|
+
let bodyStr = '';
|
|
116
|
+
data.forEach(row => {
|
|
117
|
+
// \t防止数字被科学计数法显示
|
|
118
|
+
bodyStr += Object.values(row).join(',\t') + ',\n';
|
|
119
|
+
});
|
|
120
|
+
const MIMETypes = {
|
|
121
|
+
csv: 'text/csv',
|
|
122
|
+
xls: 'application/vnd.ms-excel',
|
|
123
|
+
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
|
124
|
+
};
|
|
125
|
+
// encodeURIComponent解决中文乱码
|
|
126
|
+
const href = 'data:' + MIMETypes[fileType] + ';charset=utf-8,\ufeff' + encodeURIComponent(headerStr + bodyStr);
|
|
127
|
+
downloadHref(href, filename);
|
|
128
|
+
}
|
|
130
129
|
}
|
|
131
130
|
|
|
132
131
|
export { crossOriginDownload, downloadBlob, downloadData, downloadHref, downloadURL };
|
package/dist/esm/easing.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.13.
|
|
2
|
+
* sculp-js v1.13.6
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -9,11 +9,11 @@ import { isArray } from './type.js';
|
|
|
9
9
|
|
|
10
10
|
// @ref https://cubic-bezier.com/
|
|
11
11
|
const easingDefines = {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
linear: [0, 0, 1, 1],
|
|
13
|
+
ease: [0.25, 0.1, 0.25, 1],
|
|
14
|
+
'ease-in': [0.42, 0, 1, 1],
|
|
15
|
+
'ease-out': [0, 0, 0.58, 1],
|
|
16
|
+
'ease-in-out': [0.42, 0, 0.58, 1]
|
|
17
17
|
};
|
|
18
18
|
/**
|
|
19
19
|
* 设置缓存定义
|
|
@@ -21,12 +21,11 @@ const easingDefines = {
|
|
|
21
21
|
* @param {EasingDefine} define
|
|
22
22
|
*/
|
|
23
23
|
function setEasing(name, define) {
|
|
24
|
-
|
|
24
|
+
easingDefines[name] = define;
|
|
25
25
|
}
|
|
26
26
|
function getEasing(name) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return easingDefines;
|
|
27
|
+
if (name) return easingDefines[name];
|
|
28
|
+
return easingDefines;
|
|
30
29
|
}
|
|
31
30
|
/**
|
|
32
31
|
* 缓冲函数化,用于 js 计算缓冲进度
|
|
@@ -34,18 +33,17 @@ function getEasing(name) {
|
|
|
34
33
|
* @returns {EasingFunction}
|
|
35
34
|
*/
|
|
36
35
|
function easingFunctional(name) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
let fn;
|
|
37
|
+
if (isArray(name)) {
|
|
38
|
+
fn = bezier(...name);
|
|
39
|
+
} else {
|
|
40
|
+
const define = easingDefines[name];
|
|
41
|
+
if (!define) {
|
|
42
|
+
throw new Error(`${name} 缓冲函数未定义`);
|
|
40
43
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
throw new Error(`${name} 缓冲函数未定义`);
|
|
45
|
-
}
|
|
46
|
-
fn = bezier(...define);
|
|
47
|
-
}
|
|
48
|
-
return (input) => fn(Math.max(0, Math.min(input, 1)));
|
|
44
|
+
fn = bezier(...define);
|
|
45
|
+
}
|
|
46
|
+
return input => fn(Math.max(0, Math.min(input, 1)));
|
|
49
47
|
}
|
|
50
48
|
/**
|
|
51
49
|
* 缓冲字符化,用于 css 设置缓冲属性
|
|
@@ -53,18 +51,17 @@ function easingFunctional(name) {
|
|
|
53
51
|
* @returns {string}
|
|
54
52
|
*/
|
|
55
53
|
function easingStringify(name) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
throw new Error(`${name} 缓冲函数未定义`);
|
|
64
|
-
}
|
|
65
|
-
bezierDefine = define;
|
|
54
|
+
let bezierDefine;
|
|
55
|
+
if (isArray(name)) {
|
|
56
|
+
bezierDefine = name;
|
|
57
|
+
} else {
|
|
58
|
+
const define = easingDefines[name];
|
|
59
|
+
if (!define) {
|
|
60
|
+
throw new Error(`${name} 缓冲函数未定义`);
|
|
66
61
|
}
|
|
67
|
-
|
|
62
|
+
bezierDefine = define;
|
|
63
|
+
}
|
|
64
|
+
return `cubic-bezier(${bezierDefine.join(',')})`;
|
|
68
65
|
}
|
|
69
66
|
|
|
70
67
|
export { easingFunctional, easingStringify, getEasing, setEasing };
|
package/dist/esm/file.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.13.
|
|
2
|
+
* sculp-js v1.13.6
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -11,7 +11,7 @@ import { isObject, isNumber } from './type.js';
|
|
|
11
11
|
* @returns {boolean}
|
|
12
12
|
*/
|
|
13
13
|
function supportCanvas() {
|
|
14
|
-
|
|
14
|
+
return !!document.createElement('canvas').getContext;
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* 选择本地文件
|
|
@@ -20,22 +20,22 @@ function supportCanvas() {
|
|
|
20
20
|
* @returns {HTMLInputElement}
|
|
21
21
|
*/
|
|
22
22
|
function chooseLocalFile(accept, changeCb) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
23
|
+
let inputObj = document.createElement('input');
|
|
24
|
+
inputObj.setAttribute('id', String(Date.now()));
|
|
25
|
+
inputObj.setAttribute('type', 'file');
|
|
26
|
+
inputObj.setAttribute('style', 'visibility:hidden');
|
|
27
|
+
inputObj.setAttribute('accept', accept);
|
|
28
|
+
document.body.appendChild(inputObj);
|
|
29
|
+
inputObj.click();
|
|
30
|
+
// @ts-ignore
|
|
31
|
+
inputObj.onchange = e => {
|
|
32
|
+
changeCb(e.target.files);
|
|
33
|
+
setTimeout(() => {
|
|
34
|
+
document.body.removeChild(inputObj);
|
|
35
|
+
// @ts-ignore
|
|
36
|
+
inputObj = null;
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
41
|
* 计算图片压缩后的尺寸
|
|
@@ -47,20 +47,20 @@ function chooseLocalFile(accept, changeCb) {
|
|
|
47
47
|
* @returns {*}
|
|
48
48
|
*/
|
|
49
49
|
function calculateSize({ maxWidth, maxHeight, originWidth, originHeight }) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
50
|
+
let width = originWidth,
|
|
51
|
+
height = originHeight;
|
|
52
|
+
// 图片尺寸超过限制
|
|
53
|
+
if (originWidth > maxWidth || originHeight > maxHeight) {
|
|
54
|
+
if (originWidth / originHeight > maxWidth / maxHeight) {
|
|
55
|
+
// 更宽,按照宽度限定尺寸
|
|
56
|
+
width = maxWidth;
|
|
57
|
+
height = Math.round(maxWidth * (originHeight / originWidth));
|
|
58
|
+
} else {
|
|
59
|
+
height = maxHeight;
|
|
60
|
+
width = Math.round(maxHeight * (originWidth / originHeight));
|
|
62
61
|
}
|
|
63
|
-
|
|
62
|
+
}
|
|
63
|
+
return { width, height };
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
66
66
|
* 根据原始图片的不同尺寸计算等比例缩放后的宽高尺寸
|
|
@@ -72,41 +72,42 @@ function calculateSize({ maxWidth, maxHeight, originWidth, originHeight }) {
|
|
|
72
72
|
* @returns {*} {width, height}
|
|
73
73
|
*/
|
|
74
74
|
function scalingByAspectRatio({ sizeKB, maxSize, originWidth, originHeight }) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
75
|
+
let targetWidth = originWidth,
|
|
76
|
+
targetHeight = originHeight;
|
|
77
|
+
if (isNumber(maxSize)) {
|
|
78
|
+
const { width, height } = calculateSize({ maxWidth: maxSize, maxHeight: maxSize, originWidth, originHeight });
|
|
79
|
+
targetWidth = width;
|
|
80
|
+
targetHeight = height;
|
|
81
|
+
} else if (sizeKB < 500) {
|
|
82
|
+
// [50KB, 500KB)
|
|
83
|
+
const maxWidth = 1200,
|
|
84
|
+
maxHeight = 1200;
|
|
85
|
+
const { width, height } = calculateSize({ maxWidth, maxHeight, originWidth, originHeight });
|
|
86
|
+
targetWidth = width;
|
|
87
|
+
targetHeight = height;
|
|
88
|
+
} else if (sizeKB < 5 * 1024) {
|
|
89
|
+
// [500KB, 5MB)
|
|
90
|
+
const maxWidth = 1400,
|
|
91
|
+
maxHeight = 1400;
|
|
92
|
+
const { width, height } = calculateSize({ maxWidth, maxHeight, originWidth, originHeight });
|
|
93
|
+
targetWidth = width;
|
|
94
|
+
targetHeight = height;
|
|
95
|
+
} else if (sizeKB < 10 * 1024) {
|
|
96
|
+
// [5MB, 10MB)
|
|
97
|
+
const maxWidth = 1600,
|
|
98
|
+
maxHeight = 1600;
|
|
99
|
+
const { width, height } = calculateSize({ maxWidth, maxHeight, originWidth, originHeight });
|
|
100
|
+
targetWidth = width;
|
|
101
|
+
targetHeight = height;
|
|
102
|
+
} else if (10 * 1024 <= sizeKB) {
|
|
103
|
+
// [10MB, Infinity)
|
|
104
|
+
const maxWidth = originWidth > 15000 ? 8192 : originWidth > 10000 ? 4096 : 2048,
|
|
105
|
+
maxHeight = originHeight > 15000 ? 8192 : originHeight > 10000 ? 4096 : 2048;
|
|
106
|
+
const { width, height } = calculateSize({ maxWidth, maxHeight, originWidth, originHeight });
|
|
107
|
+
targetWidth = width;
|
|
108
|
+
targetHeight = height;
|
|
109
|
+
}
|
|
110
|
+
return { width: targetWidth, height: targetHeight };
|
|
110
111
|
}
|
|
111
112
|
/**
|
|
112
113
|
* Web端:等比例压缩图片批量处理 (小于minFileSizeKB:50,不压缩), 支持压缩全景图或长截图
|
|
@@ -120,94 +121,88 @@ function scalingByAspectRatio({ sizeKB, maxSize, originWidth, originHeight }) {
|
|
|
120
121
|
* @returns {Promise<ICompressImgResult | ICompressImgResult[] | null>}
|
|
121
122
|
*/
|
|
122
123
|
function compressImg(file, options = { mime: 'image/jpeg', minFileSizeKB: 50 }) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
124
|
+
if (!(file instanceof File || file instanceof FileList)) {
|
|
125
|
+
throw new Error(`${file} require be File or FileList`);
|
|
126
|
+
} else if (!supportCanvas()) {
|
|
127
|
+
throw new Error(`Current runtime environment not support Canvas`);
|
|
128
|
+
}
|
|
129
|
+
const { quality, mime = 'image/jpeg', maxSize: size, minFileSizeKB = 50 } = isObject(options) ? options : {};
|
|
130
|
+
let targetQuality = quality,
|
|
131
|
+
maxSize;
|
|
132
|
+
if (quality) {
|
|
133
|
+
targetQuality = quality;
|
|
134
|
+
} else if (file instanceof File) {
|
|
135
|
+
const sizeKB = +parseInt((file.size / 1024).toFixed(2));
|
|
136
|
+
if (sizeKB < minFileSizeKB) {
|
|
137
|
+
targetQuality = 1;
|
|
138
|
+
} else if (sizeKB < 1 * 1024) {
|
|
139
|
+
targetQuality = 0.85;
|
|
140
|
+
} else if (sizeKB < 5 * 1024) {
|
|
141
|
+
targetQuality = 0.8;
|
|
142
|
+
} else {
|
|
143
|
+
targetQuality = 0.75;
|
|
133
144
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (file instanceof FileList) {
|
|
153
|
-
return Promise.all(Array.from(file).map(el => compressImg(el, { maxSize, mime: mime, quality: targetQuality }))); // 如果是 file 数组返回 Promise 数组
|
|
154
|
-
}
|
|
155
|
-
else if (file instanceof File) {
|
|
156
|
-
return new Promise(resolve => {
|
|
157
|
-
const ext = {
|
|
158
|
-
'image/webp': 'webp',
|
|
159
|
-
'image/jpeg': 'jpg',
|
|
160
|
-
'image/png': 'png'
|
|
161
|
-
};
|
|
162
|
-
const fileName = [...file.name.split('.').slice(0, -1), ext[mime]].join('.');
|
|
163
|
-
const sizeKB = +parseInt((file.size / 1024).toFixed(2));
|
|
164
|
-
if (sizeKB < minFileSizeKB) {
|
|
165
|
-
resolve({
|
|
166
|
-
file: file
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
const reader = new FileReader(); // 创建 FileReader
|
|
171
|
-
// @ts-ignore
|
|
172
|
-
reader.onload = ({ target: { result: src } }) => {
|
|
173
|
-
const image = new Image(); // 创建 img 元素
|
|
174
|
-
image.onload = () => {
|
|
175
|
-
const canvas = document.createElement('canvas'); // 创建 canvas 元素
|
|
176
|
-
const context = canvas.getContext('2d');
|
|
177
|
-
const originWidth = image.width;
|
|
178
|
-
const originHeight = image.height;
|
|
179
|
-
const { width, height } = scalingByAspectRatio({ sizeKB, maxSize, originWidth, originHeight });
|
|
180
|
-
canvas.width = width;
|
|
181
|
-
canvas.height = height;
|
|
182
|
-
context.clearRect(0, 0, width, height);
|
|
183
|
-
context.drawImage(image, 0, 0, width, height); // 绘制 canvas
|
|
184
|
-
const canvasURL = canvas.toDataURL(mime, targetQuality);
|
|
185
|
-
const buffer = atob(canvasURL.split(',')[1]);
|
|
186
|
-
let length = buffer.length;
|
|
187
|
-
const bufferArray = new Uint8Array(new ArrayBuffer(length));
|
|
188
|
-
while (length--) {
|
|
189
|
-
bufferArray[length] = buffer.charCodeAt(length);
|
|
190
|
-
}
|
|
191
|
-
const miniFile = new File([bufferArray], fileName, {
|
|
192
|
-
type: mime
|
|
193
|
-
});
|
|
194
|
-
resolve({
|
|
195
|
-
file: miniFile,
|
|
196
|
-
bufferArray,
|
|
197
|
-
origin: file,
|
|
198
|
-
beforeSrc: src,
|
|
199
|
-
afterSrc: canvasURL,
|
|
200
|
-
beforeKB: sizeKB,
|
|
201
|
-
afterKB: Number((miniFile.size / 1024).toFixed(2))
|
|
202
|
-
});
|
|
203
|
-
};
|
|
204
|
-
image.src = src;
|
|
205
|
-
};
|
|
206
|
-
reader.readAsDataURL(file);
|
|
207
|
-
}
|
|
145
|
+
}
|
|
146
|
+
if (isNumber(size)) {
|
|
147
|
+
maxSize = size >= 1200 ? size : 1200;
|
|
148
|
+
}
|
|
149
|
+
if (file instanceof FileList) {
|
|
150
|
+
return Promise.all(Array.from(file).map(el => compressImg(el, { maxSize, mime: mime, quality: targetQuality }))); // 如果是 file 数组返回 Promise 数组
|
|
151
|
+
} else if (file instanceof File) {
|
|
152
|
+
return new Promise(resolve => {
|
|
153
|
+
const ext = {
|
|
154
|
+
'image/webp': 'webp',
|
|
155
|
+
'image/jpeg': 'jpg',
|
|
156
|
+
'image/png': 'png'
|
|
157
|
+
};
|
|
158
|
+
const fileName = [...file.name.split('.').slice(0, -1), ext[mime]].join('.');
|
|
159
|
+
const sizeKB = +parseInt((file.size / 1024).toFixed(2));
|
|
160
|
+
if (sizeKB < minFileSizeKB) {
|
|
161
|
+
resolve({
|
|
162
|
+
file: file
|
|
208
163
|
});
|
|
209
|
-
|
|
210
|
-
|
|
164
|
+
} else {
|
|
165
|
+
const reader = new FileReader(); // 创建 FileReader
|
|
166
|
+
// @ts-ignore
|
|
167
|
+
reader.onload = ({ target: { result: src } }) => {
|
|
168
|
+
const image = new Image(); // 创建 img 元素
|
|
169
|
+
image.onload = () => {
|
|
170
|
+
const canvas = document.createElement('canvas'); // 创建 canvas 元素
|
|
171
|
+
const context = canvas.getContext('2d');
|
|
172
|
+
const originWidth = image.width;
|
|
173
|
+
const originHeight = image.height;
|
|
174
|
+
const { width, height } = scalingByAspectRatio({ sizeKB, maxSize, originWidth, originHeight });
|
|
175
|
+
canvas.width = width;
|
|
176
|
+
canvas.height = height;
|
|
177
|
+
context.clearRect(0, 0, width, height);
|
|
178
|
+
context.drawImage(image, 0, 0, width, height); // 绘制 canvas
|
|
179
|
+
const canvasURL = canvas.toDataURL(mime, targetQuality);
|
|
180
|
+
const buffer = atob(canvasURL.split(',')[1]);
|
|
181
|
+
let length = buffer.length;
|
|
182
|
+
const bufferArray = new Uint8Array(new ArrayBuffer(length));
|
|
183
|
+
while (length--) {
|
|
184
|
+
bufferArray[length] = buffer.charCodeAt(length);
|
|
185
|
+
}
|
|
186
|
+
const miniFile = new File([bufferArray], fileName, {
|
|
187
|
+
type: mime
|
|
188
|
+
});
|
|
189
|
+
resolve({
|
|
190
|
+
file: miniFile,
|
|
191
|
+
bufferArray,
|
|
192
|
+
origin: file,
|
|
193
|
+
beforeSrc: src,
|
|
194
|
+
afterSrc: canvasURL,
|
|
195
|
+
beforeKB: sizeKB,
|
|
196
|
+
afterKB: Number((miniFile.size / 1024).toFixed(2))
|
|
197
|
+
});
|
|
198
|
+
};
|
|
199
|
+
image.src = src;
|
|
200
|
+
};
|
|
201
|
+
reader.readAsDataURL(file);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
return Promise.resolve(null);
|
|
211
206
|
}
|
|
212
207
|
|
|
213
208
|
export { chooseLocalFile, compressImg, supportCanvas };
|