sculp-js 1.10.1 → 1.10.2
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/lib/cjs/array.js +1 -1
- package/lib/cjs/async.js +1 -1
- package/lib/cjs/base64.js +1 -1
- package/lib/cjs/clipboard.js +1 -1
- package/lib/cjs/cloneDeep.js +1 -1
- package/lib/cjs/cookie.js +1 -1
- package/lib/cjs/date.js +1 -1
- package/lib/cjs/dom.js +1 -1
- package/lib/cjs/download.js +1 -1
- package/lib/cjs/easing.js +1 -1
- package/lib/cjs/file.js +36 -24
- package/lib/cjs/func.js +1 -1
- package/lib/cjs/index.js +1 -1
- package/lib/cjs/isEqual.js +1 -1
- package/lib/cjs/math.js +1 -1
- package/lib/cjs/number.js +1 -1
- package/lib/cjs/object.js +1 -1
- package/lib/cjs/path.js +1 -1
- package/lib/cjs/qs.js +1 -1
- package/lib/cjs/random.js +1 -1
- package/lib/cjs/string.js +1 -1
- package/lib/cjs/tooltip.js +1 -1
- package/lib/cjs/tree.js +1 -1
- package/lib/cjs/type.js +1 -1
- package/lib/cjs/unique.js +1 -1
- package/lib/cjs/url.js +1 -1
- package/lib/cjs/validator.js +1 -1
- package/lib/cjs/variable.js +1 -1
- package/lib/cjs/watermark.js +1 -1
- package/lib/cjs/we-decode.js +1 -1
- package/lib/es/array.js +1 -1
- package/lib/es/async.js +1 -1
- package/lib/es/base64.js +1 -1
- package/lib/es/clipboard.js +1 -1
- package/lib/es/cloneDeep.js +1 -1
- package/lib/es/cookie.js +1 -1
- package/lib/es/date.js +1 -1
- package/lib/es/dom.js +1 -1
- package/lib/es/download.js +1 -1
- package/lib/es/easing.js +1 -1
- package/lib/es/file.js +36 -24
- package/lib/es/func.js +1 -1
- package/lib/es/index.js +1 -1
- package/lib/es/isEqual.js +1 -1
- package/lib/es/math.js +1 -1
- package/lib/es/number.js +1 -1
- package/lib/es/object.js +1 -1
- package/lib/es/path.js +1 -1
- package/lib/es/qs.js +1 -1
- package/lib/es/random.js +1 -1
- package/lib/es/string.js +1 -1
- package/lib/es/tooltip.js +1 -1
- package/lib/es/tree.js +1 -1
- package/lib/es/type.js +1 -1
- package/lib/es/unique.js +1 -1
- package/lib/es/url.js +1 -1
- package/lib/es/validator.js +1 -1
- package/lib/es/variable.js +1 -1
- package/lib/es/watermark.js +1 -1
- package/lib/es/we-decode.js +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/umd/index.js +133 -120
- package/package.json +1 -1
package/lib/cjs/array.js
CHANGED
package/lib/cjs/async.js
CHANGED
package/lib/cjs/base64.js
CHANGED
package/lib/cjs/clipboard.js
CHANGED
package/lib/cjs/cloneDeep.js
CHANGED
package/lib/cjs/cookie.js
CHANGED
package/lib/cjs/date.js
CHANGED
package/lib/cjs/dom.js
CHANGED
package/lib/cjs/download.js
CHANGED
package/lib/cjs/easing.js
CHANGED
package/lib/cjs/file.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.10.
|
|
2
|
+
* sculp-js v1.10.2
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
9
|
var type = require('./type.js');
|
|
10
|
-
var weDecode = require('./we-decode.js');
|
|
11
10
|
|
|
12
11
|
/**
|
|
13
12
|
* 判断是否支持canvas
|
|
@@ -72,8 +71,15 @@ function calculateSize({ maxWidth, maxHeight, originWidth, originHeight }) {
|
|
|
72
71
|
*/
|
|
73
72
|
function scalingByAspectRatio({ sizeKB, originWidth, originHeight }) {
|
|
74
73
|
let targetWidth = originWidth, targetHeight = originHeight;
|
|
75
|
-
if (
|
|
76
|
-
// [
|
|
74
|
+
if (sizeKB <= 500) {
|
|
75
|
+
// [50KB, 500KB]
|
|
76
|
+
const maxWidth = 1200, maxHeight = 1200;
|
|
77
|
+
const { width, height } = calculateSize({ maxWidth, maxHeight, originWidth, originHeight });
|
|
78
|
+
targetWidth = width;
|
|
79
|
+
targetHeight = height;
|
|
80
|
+
}
|
|
81
|
+
else if (sizeKB < 10 * 1024) {
|
|
82
|
+
// (500KB, 10MB)
|
|
77
83
|
const maxWidth = 1600, maxHeight = 1600;
|
|
78
84
|
const { width, height } = calculateSize({ maxWidth, maxHeight, originWidth, originHeight });
|
|
79
85
|
targetWidth = width;
|
|
@@ -81,7 +87,7 @@ function scalingByAspectRatio({ sizeKB, originWidth, originHeight }) {
|
|
|
81
87
|
}
|
|
82
88
|
else if (10 * 1024 <= sizeKB) {
|
|
83
89
|
// [10MB, Infinity)
|
|
84
|
-
const maxWidth = originWidth > 15000 ? 8192 : originWidth > 10000 ? 4096 :
|
|
90
|
+
const maxWidth = originWidth > 15000 ? 8192 : originWidth > 10000 ? 4096 : 2048, maxHeight = originHeight > 15000 ? 8192 : originHeight > 10000 ? 4096 : 2048;
|
|
85
91
|
const { width, height } = calculateSize({ maxWidth, maxHeight, originWidth, originHeight });
|
|
86
92
|
targetWidth = width;
|
|
87
93
|
targetHeight = height;
|
|
@@ -92,43 +98,49 @@ function scalingByAspectRatio({ sizeKB, originWidth, originHeight }) {
|
|
|
92
98
|
* Web端:等比例压缩图片批量处理 (size小于200KB,不压缩)
|
|
93
99
|
*
|
|
94
100
|
* @param {File | FileList} file 图片或图片数组
|
|
95
|
-
* @param {ICompressOptions} options 压缩图片配置项,default: {
|
|
101
|
+
* @param {ICompressOptions} options 压缩图片配置项,default: {mime:'image/jpeg'}
|
|
96
102
|
* @returns {Promise<object> | undefined}
|
|
97
103
|
*/
|
|
98
|
-
function compressImg(file, options = {
|
|
104
|
+
function compressImg(file, options = { mime: 'image/jpeg' }) {
|
|
99
105
|
if (!(file instanceof File || file instanceof FileList)) {
|
|
100
106
|
throw new Error(`${file} require be File or FileList`);
|
|
101
107
|
}
|
|
102
108
|
else if (!supportCanvas()) {
|
|
103
109
|
throw new Error(`Current runtime environment not support Canvas`);
|
|
104
110
|
}
|
|
105
|
-
const { quality
|
|
111
|
+
const { quality, mime = 'image/jpeg' } = type.isObject(options) ? options : {};
|
|
106
112
|
let targetQuality = quality;
|
|
107
|
-
if (
|
|
113
|
+
if (quality) {
|
|
114
|
+
targetQuality = quality;
|
|
115
|
+
}
|
|
116
|
+
else if (file instanceof File) {
|
|
108
117
|
const sizeKB = +parseInt((file.size / 1024).toFixed(2));
|
|
109
|
-
if (sizeKB < 1 *
|
|
118
|
+
if (sizeKB < 1 * 50) {
|
|
119
|
+
targetQuality = 1;
|
|
120
|
+
}
|
|
121
|
+
else if (sizeKB < 1 * 1024) {
|
|
110
122
|
targetQuality = 0.85;
|
|
111
123
|
}
|
|
112
|
-
else if (sizeKB
|
|
113
|
-
targetQuality = 0.
|
|
124
|
+
else if (sizeKB < 5 * 1024) {
|
|
125
|
+
targetQuality = 0.8;
|
|
114
126
|
}
|
|
115
|
-
else
|
|
127
|
+
else {
|
|
116
128
|
targetQuality = 0.75;
|
|
117
129
|
}
|
|
118
|
-
else if (sizeKB >= 10 * 1024) {
|
|
119
|
-
targetQuality = 0.92;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
if (options.quality) {
|
|
123
|
-
targetQuality = options.quality;
|
|
124
130
|
}
|
|
125
131
|
if (file instanceof FileList) {
|
|
126
|
-
return Promise.all(Array.from(file).map(el => compressImg(el, { mime:
|
|
132
|
+
return Promise.all(Array.from(file).map(el => compressImg(el, { mime: mime, quality: targetQuality }))); // 如果是 file 数组返回 Promise 数组
|
|
127
133
|
}
|
|
128
134
|
else if (file instanceof File) {
|
|
129
135
|
return new Promise(resolve => {
|
|
136
|
+
const ext = {
|
|
137
|
+
'image/webp': 'webp',
|
|
138
|
+
'image/jpeg': 'jpg',
|
|
139
|
+
'image/png': 'png'
|
|
140
|
+
};
|
|
141
|
+
const fileName = [...file.name.split('.').slice(0, -1), ext[mime]].join('.');
|
|
130
142
|
const sizeKB = +parseInt((file.size / 1024).toFixed(2));
|
|
131
|
-
if (+(file.size / 1024).toFixed(2) <
|
|
143
|
+
if (+(file.size / 1024).toFixed(2) < 50) {
|
|
132
144
|
resolve({
|
|
133
145
|
file: file
|
|
134
146
|
});
|
|
@@ -149,14 +161,14 @@ function compressImg(file, options = { quality: 0.52, mime: 'image/jpeg' }) {
|
|
|
149
161
|
context.clearRect(0, 0, width, height);
|
|
150
162
|
context.drawImage(image, 0, 0, width, height); // 绘制 canvas
|
|
151
163
|
const canvasURL = canvas.toDataURL(mime, targetQuality);
|
|
152
|
-
const buffer =
|
|
164
|
+
const buffer = atob(canvasURL.split(',')[1]);
|
|
153
165
|
let length = buffer.length;
|
|
154
166
|
const bufferArray = new Uint8Array(new ArrayBuffer(length));
|
|
155
167
|
while (length--) {
|
|
156
168
|
bufferArray[length] = buffer.charCodeAt(length);
|
|
157
169
|
}
|
|
158
|
-
const miniFile = new File([bufferArray],
|
|
159
|
-
type:
|
|
170
|
+
const miniFile = new File([bufferArray], fileName, {
|
|
171
|
+
type: mime
|
|
160
172
|
});
|
|
161
173
|
resolve({
|
|
162
174
|
file: miniFile,
|
package/lib/cjs/func.js
CHANGED
package/lib/cjs/index.js
CHANGED
package/lib/cjs/isEqual.js
CHANGED
package/lib/cjs/math.js
CHANGED
package/lib/cjs/number.js
CHANGED
package/lib/cjs/object.js
CHANGED
package/lib/cjs/path.js
CHANGED
package/lib/cjs/qs.js
CHANGED
package/lib/cjs/random.js
CHANGED
package/lib/cjs/string.js
CHANGED
package/lib/cjs/tooltip.js
CHANGED
package/lib/cjs/tree.js
CHANGED
package/lib/cjs/type.js
CHANGED
package/lib/cjs/unique.js
CHANGED
package/lib/cjs/url.js
CHANGED
package/lib/cjs/validator.js
CHANGED
package/lib/cjs/variable.js
CHANGED
package/lib/cjs/watermark.js
CHANGED
package/lib/cjs/we-decode.js
CHANGED
package/lib/es/array.js
CHANGED
package/lib/es/async.js
CHANGED
package/lib/es/base64.js
CHANGED
package/lib/es/clipboard.js
CHANGED
package/lib/es/cloneDeep.js
CHANGED
package/lib/es/cookie.js
CHANGED
package/lib/es/date.js
CHANGED
package/lib/es/dom.js
CHANGED
package/lib/es/download.js
CHANGED
package/lib/es/easing.js
CHANGED
package/lib/es/file.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.10.
|
|
2
|
+
* sculp-js v1.10.2
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { isObject } from './type.js';
|
|
8
|
-
import { weAtob } from './we-decode.js';
|
|
9
8
|
|
|
10
9
|
/**
|
|
11
10
|
* 判断是否支持canvas
|
|
@@ -70,8 +69,15 @@ function calculateSize({ maxWidth, maxHeight, originWidth, originHeight }) {
|
|
|
70
69
|
*/
|
|
71
70
|
function scalingByAspectRatio({ sizeKB, originWidth, originHeight }) {
|
|
72
71
|
let targetWidth = originWidth, targetHeight = originHeight;
|
|
73
|
-
if (
|
|
74
|
-
// [
|
|
72
|
+
if (sizeKB <= 500) {
|
|
73
|
+
// [50KB, 500KB]
|
|
74
|
+
const maxWidth = 1200, maxHeight = 1200;
|
|
75
|
+
const { width, height } = calculateSize({ maxWidth, maxHeight, originWidth, originHeight });
|
|
76
|
+
targetWidth = width;
|
|
77
|
+
targetHeight = height;
|
|
78
|
+
}
|
|
79
|
+
else if (sizeKB < 10 * 1024) {
|
|
80
|
+
// (500KB, 10MB)
|
|
75
81
|
const maxWidth = 1600, maxHeight = 1600;
|
|
76
82
|
const { width, height } = calculateSize({ maxWidth, maxHeight, originWidth, originHeight });
|
|
77
83
|
targetWidth = width;
|
|
@@ -79,7 +85,7 @@ function scalingByAspectRatio({ sizeKB, originWidth, originHeight }) {
|
|
|
79
85
|
}
|
|
80
86
|
else if (10 * 1024 <= sizeKB) {
|
|
81
87
|
// [10MB, Infinity)
|
|
82
|
-
const maxWidth = originWidth > 15000 ? 8192 : originWidth > 10000 ? 4096 :
|
|
88
|
+
const maxWidth = originWidth > 15000 ? 8192 : originWidth > 10000 ? 4096 : 2048, maxHeight = originHeight > 15000 ? 8192 : originHeight > 10000 ? 4096 : 2048;
|
|
83
89
|
const { width, height } = calculateSize({ maxWidth, maxHeight, originWidth, originHeight });
|
|
84
90
|
targetWidth = width;
|
|
85
91
|
targetHeight = height;
|
|
@@ -90,43 +96,49 @@ function scalingByAspectRatio({ sizeKB, originWidth, originHeight }) {
|
|
|
90
96
|
* Web端:等比例压缩图片批量处理 (size小于200KB,不压缩)
|
|
91
97
|
*
|
|
92
98
|
* @param {File | FileList} file 图片或图片数组
|
|
93
|
-
* @param {ICompressOptions} options 压缩图片配置项,default: {
|
|
99
|
+
* @param {ICompressOptions} options 压缩图片配置项,default: {mime:'image/jpeg'}
|
|
94
100
|
* @returns {Promise<object> | undefined}
|
|
95
101
|
*/
|
|
96
|
-
function compressImg(file, options = {
|
|
102
|
+
function compressImg(file, options = { mime: 'image/jpeg' }) {
|
|
97
103
|
if (!(file instanceof File || file instanceof FileList)) {
|
|
98
104
|
throw new Error(`${file} require be File or FileList`);
|
|
99
105
|
}
|
|
100
106
|
else if (!supportCanvas()) {
|
|
101
107
|
throw new Error(`Current runtime environment not support Canvas`);
|
|
102
108
|
}
|
|
103
|
-
const { quality
|
|
109
|
+
const { quality, mime = 'image/jpeg' } = isObject(options) ? options : {};
|
|
104
110
|
let targetQuality = quality;
|
|
105
|
-
if (
|
|
111
|
+
if (quality) {
|
|
112
|
+
targetQuality = quality;
|
|
113
|
+
}
|
|
114
|
+
else if (file instanceof File) {
|
|
106
115
|
const sizeKB = +parseInt((file.size / 1024).toFixed(2));
|
|
107
|
-
if (sizeKB < 1 *
|
|
116
|
+
if (sizeKB < 1 * 50) {
|
|
117
|
+
targetQuality = 1;
|
|
118
|
+
}
|
|
119
|
+
else if (sizeKB < 1 * 1024) {
|
|
108
120
|
targetQuality = 0.85;
|
|
109
121
|
}
|
|
110
|
-
else if (sizeKB
|
|
111
|
-
targetQuality = 0.
|
|
122
|
+
else if (sizeKB < 5 * 1024) {
|
|
123
|
+
targetQuality = 0.8;
|
|
112
124
|
}
|
|
113
|
-
else
|
|
125
|
+
else {
|
|
114
126
|
targetQuality = 0.75;
|
|
115
127
|
}
|
|
116
|
-
else if (sizeKB >= 10 * 1024) {
|
|
117
|
-
targetQuality = 0.92;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
if (options.quality) {
|
|
121
|
-
targetQuality = options.quality;
|
|
122
128
|
}
|
|
123
129
|
if (file instanceof FileList) {
|
|
124
|
-
return Promise.all(Array.from(file).map(el => compressImg(el, { mime:
|
|
130
|
+
return Promise.all(Array.from(file).map(el => compressImg(el, { mime: mime, quality: targetQuality }))); // 如果是 file 数组返回 Promise 数组
|
|
125
131
|
}
|
|
126
132
|
else if (file instanceof File) {
|
|
127
133
|
return new Promise(resolve => {
|
|
134
|
+
const ext = {
|
|
135
|
+
'image/webp': 'webp',
|
|
136
|
+
'image/jpeg': 'jpg',
|
|
137
|
+
'image/png': 'png'
|
|
138
|
+
};
|
|
139
|
+
const fileName = [...file.name.split('.').slice(0, -1), ext[mime]].join('.');
|
|
128
140
|
const sizeKB = +parseInt((file.size / 1024).toFixed(2));
|
|
129
|
-
if (+(file.size / 1024).toFixed(2) <
|
|
141
|
+
if (+(file.size / 1024).toFixed(2) < 50) {
|
|
130
142
|
resolve({
|
|
131
143
|
file: file
|
|
132
144
|
});
|
|
@@ -147,14 +159,14 @@ function compressImg(file, options = { quality: 0.52, mime: 'image/jpeg' }) {
|
|
|
147
159
|
context.clearRect(0, 0, width, height);
|
|
148
160
|
context.drawImage(image, 0, 0, width, height); // 绘制 canvas
|
|
149
161
|
const canvasURL = canvas.toDataURL(mime, targetQuality);
|
|
150
|
-
const buffer =
|
|
162
|
+
const buffer = atob(canvasURL.split(',')[1]);
|
|
151
163
|
let length = buffer.length;
|
|
152
164
|
const bufferArray = new Uint8Array(new ArrayBuffer(length));
|
|
153
165
|
while (length--) {
|
|
154
166
|
bufferArray[length] = buffer.charCodeAt(length);
|
|
155
167
|
}
|
|
156
|
-
const miniFile = new File([bufferArray],
|
|
157
|
-
type:
|
|
168
|
+
const miniFile = new File([bufferArray], fileName, {
|
|
169
|
+
type: mime
|
|
158
170
|
});
|
|
159
171
|
resolve({
|
|
160
172
|
file: miniFile,
|
package/lib/es/func.js
CHANGED
package/lib/es/index.js
CHANGED
package/lib/es/isEqual.js
CHANGED
package/lib/es/math.js
CHANGED
package/lib/es/number.js
CHANGED
package/lib/es/object.js
CHANGED
package/lib/es/path.js
CHANGED
package/lib/es/qs.js
CHANGED
package/lib/es/random.js
CHANGED
package/lib/es/string.js
CHANGED
package/lib/es/tooltip.js
CHANGED
package/lib/es/tree.js
CHANGED
package/lib/es/type.js
CHANGED
package/lib/es/unique.js
CHANGED
package/lib/es/url.js
CHANGED
package/lib/es/validator.js
CHANGED
package/lib/es/variable.js
CHANGED
package/lib/es/watermark.js
CHANGED
package/lib/es/we-decode.js
CHANGED
package/lib/index.d.ts
CHANGED
|
@@ -608,7 +608,7 @@ interface ICompressOptions {
|
|
|
608
608
|
* Web端:等比例压缩图片批量处理 (size小于200KB,不压缩)
|
|
609
609
|
*
|
|
610
610
|
* @param {File | FileList} file 图片或图片数组
|
|
611
|
-
* @param {ICompressOptions} options 压缩图片配置项,default: {
|
|
611
|
+
* @param {ICompressOptions} options 压缩图片配置项,default: {mime:'image/jpeg'}
|
|
612
612
|
* @returns {Promise<object> | undefined}
|
|
613
613
|
*/
|
|
614
614
|
declare function compressImg(file: File | FileList, options?: ICompressOptions): Promise<object> | undefined;
|
package/lib/umd/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.10.
|
|
2
|
+
* sculp-js v1.10.2
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -1377,103 +1377,6 @@
|
|
|
1377
1377
|
});
|
|
1378
1378
|
}
|
|
1379
1379
|
|
|
1380
|
-
const b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
1381
|
-
// eslint-disable-next-line
|
|
1382
|
-
const b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
|
|
1383
|
-
/**
|
|
1384
|
-
* 字符串编码成Base64, 平替浏览器的btoa, 不包含中文的处理 (适用于任何环境,包括小程序)
|
|
1385
|
-
* @param {string} string
|
|
1386
|
-
* @returns {string}
|
|
1387
|
-
*/
|
|
1388
|
-
function weBtoa(string) {
|
|
1389
|
-
// 同window.btoa: 字符串编码成Base64
|
|
1390
|
-
string = String(string);
|
|
1391
|
-
let bitmap, a, b, c, result = '', i = 0;
|
|
1392
|
-
const strLen = string.length;
|
|
1393
|
-
const rest = strLen % 3;
|
|
1394
|
-
for (; i < strLen;) {
|
|
1395
|
-
if ((a = string.charCodeAt(i++)) > 255 || (b = string.charCodeAt(i++)) > 255 || (c = string.charCodeAt(i++)) > 255)
|
|
1396
|
-
throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");
|
|
1397
|
-
bitmap = (a << 16) | (b << 8) | c;
|
|
1398
|
-
result +=
|
|
1399
|
-
b64.charAt((bitmap >> 18) & 63) +
|
|
1400
|
-
b64.charAt((bitmap >> 12) & 63) +
|
|
1401
|
-
b64.charAt((bitmap >> 6) & 63) +
|
|
1402
|
-
b64.charAt(bitmap & 63);
|
|
1403
|
-
}
|
|
1404
|
-
return rest ? result.slice(0, rest - 3) + '==='.substring(rest) : result;
|
|
1405
|
-
}
|
|
1406
|
-
/**
|
|
1407
|
-
* Base64解码为原始字符串,平替浏览器的atob, 不包含中文的处理(适用于任何环境,包括小程序)
|
|
1408
|
-
* @param {string} string
|
|
1409
|
-
* @returns {string}
|
|
1410
|
-
*/
|
|
1411
|
-
function weAtob(string) {
|
|
1412
|
-
// 同window.atob: Base64解码为原始字符串
|
|
1413
|
-
string = String(string).replace(/[\t\n\f\r ]+/g, '');
|
|
1414
|
-
if (!b64re.test(string))
|
|
1415
|
-
throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");
|
|
1416
|
-
string += '=='.slice(2 - (string.length & 3));
|
|
1417
|
-
let bitmap, result = '', r1, r2, i = 0;
|
|
1418
|
-
for (const strLen = string.length; i < strLen;) {
|
|
1419
|
-
bitmap =
|
|
1420
|
-
(b64.indexOf(string.charAt(i++)) << 18) |
|
|
1421
|
-
(b64.indexOf(string.charAt(i++)) << 12) |
|
|
1422
|
-
((r1 = b64.indexOf(string.charAt(i++))) << 6) |
|
|
1423
|
-
(r2 = b64.indexOf(string.charAt(i++)));
|
|
1424
|
-
result +=
|
|
1425
|
-
r1 === 64
|
|
1426
|
-
? String.fromCharCode((bitmap >> 16) & 255)
|
|
1427
|
-
: r2 === 64
|
|
1428
|
-
? String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255)
|
|
1429
|
-
: String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255, bitmap & 255);
|
|
1430
|
-
}
|
|
1431
|
-
return result;
|
|
1432
|
-
}
|
|
1433
|
-
// function b64DecodeUnicode(str) {
|
|
1434
|
-
// return decodeURIComponent(
|
|
1435
|
-
// exports.weAtob(str).replace(/(.)/g, function (p) {
|
|
1436
|
-
// let code = p.charCodeAt(0).toString(16).toUpperCase();
|
|
1437
|
-
// if (code.length < 2) {
|
|
1438
|
-
// code = '0' + code;
|
|
1439
|
-
// }
|
|
1440
|
-
// return '%' + code;
|
|
1441
|
-
// })
|
|
1442
|
-
// );
|
|
1443
|
-
// }
|
|
1444
|
-
// function base64_url_decode(str) {
|
|
1445
|
-
// let output = str.replace(/-/g, '+').replace(/_/g, '/');
|
|
1446
|
-
// switch (output.length % 4) {
|
|
1447
|
-
// case 0:
|
|
1448
|
-
// break;
|
|
1449
|
-
// case 2:
|
|
1450
|
-
// output += '==';
|
|
1451
|
-
// break;
|
|
1452
|
-
// case 3:
|
|
1453
|
-
// output += '=';
|
|
1454
|
-
// break;
|
|
1455
|
-
// default:
|
|
1456
|
-
// throw new Error('Illegal base64url string!');
|
|
1457
|
-
// }
|
|
1458
|
-
// try {
|
|
1459
|
-
// return b64DecodeUnicode(output);
|
|
1460
|
-
// } catch (err) {
|
|
1461
|
-
// return exports.weAtob(output);
|
|
1462
|
-
// }
|
|
1463
|
-
// }
|
|
1464
|
-
// export function weAppJwtDecode(token, options) {
|
|
1465
|
-
// if (typeof token !== 'string') {
|
|
1466
|
-
// throw new Error('Invalid token specified');
|
|
1467
|
-
// }
|
|
1468
|
-
// options = options || {};
|
|
1469
|
-
// const pos = options.header === true ? 0 : 1;
|
|
1470
|
-
// try {
|
|
1471
|
-
// return JSON.parse(base64_url_decode(token.split('.')[pos]));
|
|
1472
|
-
// } catch (e) {
|
|
1473
|
-
// throw new Error('Invalid token specified: ' + (e as Error).message);
|
|
1474
|
-
// }
|
|
1475
|
-
// }
|
|
1476
|
-
|
|
1477
1380
|
/**
|
|
1478
1381
|
* 判断是否支持canvas
|
|
1479
1382
|
* @returns {boolean}
|
|
@@ -1537,8 +1440,15 @@
|
|
|
1537
1440
|
*/
|
|
1538
1441
|
function scalingByAspectRatio({ sizeKB, originWidth, originHeight }) {
|
|
1539
1442
|
let targetWidth = originWidth, targetHeight = originHeight;
|
|
1540
|
-
if (
|
|
1541
|
-
// [
|
|
1443
|
+
if (sizeKB <= 500) {
|
|
1444
|
+
// [50KB, 500KB]
|
|
1445
|
+
const maxWidth = 1200, maxHeight = 1200;
|
|
1446
|
+
const { width, height } = calculateSize({ maxWidth, maxHeight, originWidth, originHeight });
|
|
1447
|
+
targetWidth = width;
|
|
1448
|
+
targetHeight = height;
|
|
1449
|
+
}
|
|
1450
|
+
else if (sizeKB < 10 * 1024) {
|
|
1451
|
+
// (500KB, 10MB)
|
|
1542
1452
|
const maxWidth = 1600, maxHeight = 1600;
|
|
1543
1453
|
const { width, height } = calculateSize({ maxWidth, maxHeight, originWidth, originHeight });
|
|
1544
1454
|
targetWidth = width;
|
|
@@ -1546,7 +1456,7 @@
|
|
|
1546
1456
|
}
|
|
1547
1457
|
else if (10 * 1024 <= sizeKB) {
|
|
1548
1458
|
// [10MB, Infinity)
|
|
1549
|
-
const maxWidth = originWidth > 15000 ? 8192 : originWidth > 10000 ? 4096 :
|
|
1459
|
+
const maxWidth = originWidth > 15000 ? 8192 : originWidth > 10000 ? 4096 : 2048, maxHeight = originHeight > 15000 ? 8192 : originHeight > 10000 ? 4096 : 2048;
|
|
1550
1460
|
const { width, height } = calculateSize({ maxWidth, maxHeight, originWidth, originHeight });
|
|
1551
1461
|
targetWidth = width;
|
|
1552
1462
|
targetHeight = height;
|
|
@@ -1557,43 +1467,49 @@
|
|
|
1557
1467
|
* Web端:等比例压缩图片批量处理 (size小于200KB,不压缩)
|
|
1558
1468
|
*
|
|
1559
1469
|
* @param {File | FileList} file 图片或图片数组
|
|
1560
|
-
* @param {ICompressOptions} options 压缩图片配置项,default: {
|
|
1470
|
+
* @param {ICompressOptions} options 压缩图片配置项,default: {mime:'image/jpeg'}
|
|
1561
1471
|
* @returns {Promise<object> | undefined}
|
|
1562
1472
|
*/
|
|
1563
|
-
function compressImg(file, options = {
|
|
1473
|
+
function compressImg(file, options = { mime: 'image/jpeg' }) {
|
|
1564
1474
|
if (!(file instanceof File || file instanceof FileList)) {
|
|
1565
1475
|
throw new Error(`${file} require be File or FileList`);
|
|
1566
1476
|
}
|
|
1567
1477
|
else if (!supportCanvas()) {
|
|
1568
1478
|
throw new Error(`Current runtime environment not support Canvas`);
|
|
1569
1479
|
}
|
|
1570
|
-
const { quality
|
|
1480
|
+
const { quality, mime = 'image/jpeg' } = isObject(options) ? options : {};
|
|
1571
1481
|
let targetQuality = quality;
|
|
1572
|
-
if (
|
|
1482
|
+
if (quality) {
|
|
1483
|
+
targetQuality = quality;
|
|
1484
|
+
}
|
|
1485
|
+
else if (file instanceof File) {
|
|
1573
1486
|
const sizeKB = +parseInt((file.size / 1024).toFixed(2));
|
|
1574
|
-
if (sizeKB < 1 *
|
|
1487
|
+
if (sizeKB < 1 * 50) {
|
|
1488
|
+
targetQuality = 1;
|
|
1489
|
+
}
|
|
1490
|
+
else if (sizeKB < 1 * 1024) {
|
|
1575
1491
|
targetQuality = 0.85;
|
|
1576
1492
|
}
|
|
1577
|
-
else if (sizeKB
|
|
1578
|
-
targetQuality = 0.
|
|
1493
|
+
else if (sizeKB < 5 * 1024) {
|
|
1494
|
+
targetQuality = 0.8;
|
|
1579
1495
|
}
|
|
1580
|
-
else
|
|
1496
|
+
else {
|
|
1581
1497
|
targetQuality = 0.75;
|
|
1582
1498
|
}
|
|
1583
|
-
else if (sizeKB >= 10 * 1024) {
|
|
1584
|
-
targetQuality = 0.92;
|
|
1585
|
-
}
|
|
1586
|
-
}
|
|
1587
|
-
if (options.quality) {
|
|
1588
|
-
targetQuality = options.quality;
|
|
1589
1499
|
}
|
|
1590
1500
|
if (file instanceof FileList) {
|
|
1591
|
-
return Promise.all(Array.from(file).map(el => compressImg(el, { mime:
|
|
1501
|
+
return Promise.all(Array.from(file).map(el => compressImg(el, { mime: mime, quality: targetQuality }))); // 如果是 file 数组返回 Promise 数组
|
|
1592
1502
|
}
|
|
1593
1503
|
else if (file instanceof File) {
|
|
1594
1504
|
return new Promise(resolve => {
|
|
1505
|
+
const ext = {
|
|
1506
|
+
'image/webp': 'webp',
|
|
1507
|
+
'image/jpeg': 'jpg',
|
|
1508
|
+
'image/png': 'png'
|
|
1509
|
+
};
|
|
1510
|
+
const fileName = [...file.name.split('.').slice(0, -1), ext[mime]].join('.');
|
|
1595
1511
|
const sizeKB = +parseInt((file.size / 1024).toFixed(2));
|
|
1596
|
-
if (+(file.size / 1024).toFixed(2) <
|
|
1512
|
+
if (+(file.size / 1024).toFixed(2) < 50) {
|
|
1597
1513
|
resolve({
|
|
1598
1514
|
file: file
|
|
1599
1515
|
});
|
|
@@ -1614,14 +1530,14 @@
|
|
|
1614
1530
|
context.clearRect(0, 0, width, height);
|
|
1615
1531
|
context.drawImage(image, 0, 0, width, height); // 绘制 canvas
|
|
1616
1532
|
const canvasURL = canvas.toDataURL(mime, targetQuality);
|
|
1617
|
-
const buffer =
|
|
1533
|
+
const buffer = atob(canvasURL.split(',')[1]);
|
|
1618
1534
|
let length = buffer.length;
|
|
1619
1535
|
const bufferArray = new Uint8Array(new ArrayBuffer(length));
|
|
1620
1536
|
while (length--) {
|
|
1621
1537
|
bufferArray[length] = buffer.charCodeAt(length);
|
|
1622
1538
|
}
|
|
1623
|
-
const miniFile = new File([bufferArray],
|
|
1624
|
-
type:
|
|
1539
|
+
const miniFile = new File([bufferArray], fileName, {
|
|
1540
|
+
type: mime
|
|
1625
1541
|
});
|
|
1626
1542
|
resolve({
|
|
1627
1543
|
file: miniFile,
|
|
@@ -2539,6 +2455,103 @@
|
|
|
2539
2455
|
return +parseFloat(Number(num).toPrecision(precision));
|
|
2540
2456
|
}
|
|
2541
2457
|
|
|
2458
|
+
const b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
|
2459
|
+
// eslint-disable-next-line
|
|
2460
|
+
const b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
|
|
2461
|
+
/**
|
|
2462
|
+
* 字符串编码成Base64, 平替浏览器的btoa, 不包含中文的处理 (适用于任何环境,包括小程序)
|
|
2463
|
+
* @param {string} string
|
|
2464
|
+
* @returns {string}
|
|
2465
|
+
*/
|
|
2466
|
+
function weBtoa(string) {
|
|
2467
|
+
// 同window.btoa: 字符串编码成Base64
|
|
2468
|
+
string = String(string);
|
|
2469
|
+
let bitmap, a, b, c, result = '', i = 0;
|
|
2470
|
+
const strLen = string.length;
|
|
2471
|
+
const rest = strLen % 3;
|
|
2472
|
+
for (; i < strLen;) {
|
|
2473
|
+
if ((a = string.charCodeAt(i++)) > 255 || (b = string.charCodeAt(i++)) > 255 || (c = string.charCodeAt(i++)) > 255)
|
|
2474
|
+
throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");
|
|
2475
|
+
bitmap = (a << 16) | (b << 8) | c;
|
|
2476
|
+
result +=
|
|
2477
|
+
b64.charAt((bitmap >> 18) & 63) +
|
|
2478
|
+
b64.charAt((bitmap >> 12) & 63) +
|
|
2479
|
+
b64.charAt((bitmap >> 6) & 63) +
|
|
2480
|
+
b64.charAt(bitmap & 63);
|
|
2481
|
+
}
|
|
2482
|
+
return rest ? result.slice(0, rest - 3) + '==='.substring(rest) : result;
|
|
2483
|
+
}
|
|
2484
|
+
/**
|
|
2485
|
+
* Base64解码为原始字符串,平替浏览器的atob, 不包含中文的处理(适用于任何环境,包括小程序)
|
|
2486
|
+
* @param {string} string
|
|
2487
|
+
* @returns {string}
|
|
2488
|
+
*/
|
|
2489
|
+
function weAtob(string) {
|
|
2490
|
+
// 同window.atob: Base64解码为原始字符串
|
|
2491
|
+
string = String(string).replace(/[\t\n\f\r ]+/g, '');
|
|
2492
|
+
if (!b64re.test(string))
|
|
2493
|
+
throw new TypeError("Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");
|
|
2494
|
+
string += '=='.slice(2 - (string.length & 3));
|
|
2495
|
+
let bitmap, result = '', r1, r2, i = 0;
|
|
2496
|
+
for (const strLen = string.length; i < strLen;) {
|
|
2497
|
+
bitmap =
|
|
2498
|
+
(b64.indexOf(string.charAt(i++)) << 18) |
|
|
2499
|
+
(b64.indexOf(string.charAt(i++)) << 12) |
|
|
2500
|
+
((r1 = b64.indexOf(string.charAt(i++))) << 6) |
|
|
2501
|
+
(r2 = b64.indexOf(string.charAt(i++)));
|
|
2502
|
+
result +=
|
|
2503
|
+
r1 === 64
|
|
2504
|
+
? String.fromCharCode((bitmap >> 16) & 255)
|
|
2505
|
+
: r2 === 64
|
|
2506
|
+
? String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255)
|
|
2507
|
+
: String.fromCharCode((bitmap >> 16) & 255, (bitmap >> 8) & 255, bitmap & 255);
|
|
2508
|
+
}
|
|
2509
|
+
return result;
|
|
2510
|
+
}
|
|
2511
|
+
// function b64DecodeUnicode(str) {
|
|
2512
|
+
// return decodeURIComponent(
|
|
2513
|
+
// exports.weAtob(str).replace(/(.)/g, function (p) {
|
|
2514
|
+
// let code = p.charCodeAt(0).toString(16).toUpperCase();
|
|
2515
|
+
// if (code.length < 2) {
|
|
2516
|
+
// code = '0' + code;
|
|
2517
|
+
// }
|
|
2518
|
+
// return '%' + code;
|
|
2519
|
+
// })
|
|
2520
|
+
// );
|
|
2521
|
+
// }
|
|
2522
|
+
// function base64_url_decode(str) {
|
|
2523
|
+
// let output = str.replace(/-/g, '+').replace(/_/g, '/');
|
|
2524
|
+
// switch (output.length % 4) {
|
|
2525
|
+
// case 0:
|
|
2526
|
+
// break;
|
|
2527
|
+
// case 2:
|
|
2528
|
+
// output += '==';
|
|
2529
|
+
// break;
|
|
2530
|
+
// case 3:
|
|
2531
|
+
// output += '=';
|
|
2532
|
+
// break;
|
|
2533
|
+
// default:
|
|
2534
|
+
// throw new Error('Illegal base64url string!');
|
|
2535
|
+
// }
|
|
2536
|
+
// try {
|
|
2537
|
+
// return b64DecodeUnicode(output);
|
|
2538
|
+
// } catch (err) {
|
|
2539
|
+
// return exports.weAtob(output);
|
|
2540
|
+
// }
|
|
2541
|
+
// }
|
|
2542
|
+
// export function weAppJwtDecode(token, options) {
|
|
2543
|
+
// if (typeof token !== 'string') {
|
|
2544
|
+
// throw new Error('Invalid token specified');
|
|
2545
|
+
// }
|
|
2546
|
+
// options = options || {};
|
|
2547
|
+
// const pos = options.header === true ? 0 : 1;
|
|
2548
|
+
// try {
|
|
2549
|
+
// return JSON.parse(base64_url_decode(token.split('.')[pos]));
|
|
2550
|
+
// } catch (e) {
|
|
2551
|
+
// throw new Error('Invalid token specified: ' + (e as Error).message);
|
|
2552
|
+
// }
|
|
2553
|
+
// }
|
|
2554
|
+
|
|
2542
2555
|
function stringToUint8Array(str) {
|
|
2543
2556
|
const utf8 = encodeURIComponent(str); // 将字符串转换为 UTF-8 编码
|
|
2544
2557
|
const uint8Array = new Uint8Array(utf8.length); // 创建 Uint8Array
|