@hzab/utils 0.0.1
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/CHANGELOG.md +2 -0
- package/README.md +120 -0
- package/package.json +58 -0
- package/src/array.ts +8 -0
- package/src/color.ts +302 -0
- package/src/file/file.ts +37 -0
- package/src/file/fileName.ts +75 -0
- package/src/file/fileType.ts +152 -0
- package/src/formily/schema-merge.ts +68 -0
- package/src/img-utils.ts +340 -0
- package/src/locationUtils.ts +26 -0
- package/src/nanoid.ts +10 -0
- package/src/options.ts +226 -0
- package/src/string.ts +19 -0
- package/src/upload/OfflineUpload.ts +338 -0
- package/src/upload/ossUpload.ts +181 -0
- package/src/upload/uploadUtils.ts +118 -0
- package/src/url.ts +120 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
export const TYPE_VIDEO = "video";
|
|
2
|
+
export const TYPE_IMG = "image";
|
|
3
|
+
export const TYPE_AUDIO = "audio";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 检查 url 是否带有指定后缀
|
|
7
|
+
* @param {string} url url 地址
|
|
8
|
+
* @param {Array} types 后缀数组
|
|
9
|
+
* @returns
|
|
10
|
+
*/
|
|
11
|
+
export function checkUrlSuffix(url, types = [], caseSensitive = false) {
|
|
12
|
+
if (!url) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
let _url = url?.replace(/\?.+/, "");
|
|
16
|
+
const reg = new RegExp(`\.(${types.join("|")})$`, caseSensitive ? undefined : "i");
|
|
17
|
+
if (reg.test(_url)) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 获取文件类型(文件自身类型,如:video/mp4、image/jpeg)
|
|
24
|
+
* @param file
|
|
25
|
+
* @returns
|
|
26
|
+
*/
|
|
27
|
+
export function getFileType(file) {
|
|
28
|
+
if (typeof file === "object" && file?.type) {
|
|
29
|
+
return file?.type;
|
|
30
|
+
}
|
|
31
|
+
if (typeof file === "string") {
|
|
32
|
+
let type = null;
|
|
33
|
+
if (checkVideoUrl(file)) {
|
|
34
|
+
type = "video/mp4";
|
|
35
|
+
} else if (checkImageUrl(file)) {
|
|
36
|
+
type = "image/jpeg";
|
|
37
|
+
} else if (checkAudioUrl(file)) {
|
|
38
|
+
type = "audio/3gpp";
|
|
39
|
+
} else if (checkUrlSuffix(file, ["pdf"])) {
|
|
40
|
+
type = "application/pdf";
|
|
41
|
+
} else if (checkUrlSuffix(file, ["pdf"])) {
|
|
42
|
+
type = "application/pdf";
|
|
43
|
+
} else if (checkUrlSuffix(file, ["xlsx", "xls", "csv", "xlsm", "xlsb"])) {
|
|
44
|
+
type = "application/vnd.ms-excel";
|
|
45
|
+
} else if (checkUrlSuffix(file, ["doc", "docx"])) {
|
|
46
|
+
type = "application/msword";
|
|
47
|
+
} else if (checkUrlSuffix(file, ["ppt", "pptx"])) {
|
|
48
|
+
type = "application/vnd.ms-powerpoint";
|
|
49
|
+
}
|
|
50
|
+
return type;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 判断 url 是否带有指定图片后缀
|
|
56
|
+
* @param {string} url
|
|
57
|
+
* @returns
|
|
58
|
+
*/
|
|
59
|
+
export function checkImageUrl(url) {
|
|
60
|
+
// base64
|
|
61
|
+
if (/^data:image\/\w+;base64/i.test(url)) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
const imgTypes = [
|
|
65
|
+
"apng",
|
|
66
|
+
"avif",
|
|
67
|
+
"bmp",
|
|
68
|
+
"gif",
|
|
69
|
+
"ico",
|
|
70
|
+
"cur",
|
|
71
|
+
"jpg",
|
|
72
|
+
"jpeg",
|
|
73
|
+
"jfif",
|
|
74
|
+
"pjpeg",
|
|
75
|
+
"pjp",
|
|
76
|
+
"png",
|
|
77
|
+
"svg",
|
|
78
|
+
"tif",
|
|
79
|
+
"tiff",
|
|
80
|
+
"webp",
|
|
81
|
+
];
|
|
82
|
+
return checkUrlSuffix(url, imgTypes);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* 判断是否是合法的媒体类型
|
|
87
|
+
* @param {String} input
|
|
88
|
+
* @returns
|
|
89
|
+
*/
|
|
90
|
+
export function isValidMediaType(input) {
|
|
91
|
+
const validPrefixes = ["image/", "video/", "audio/"];
|
|
92
|
+
return validPrefixes.some((prefix) => input?.startsWith(prefix));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 判断 url 是否带有指定视频后缀
|
|
97
|
+
* @param {string} url
|
|
98
|
+
* @returns
|
|
99
|
+
*/
|
|
100
|
+
export function checkVideoUrl(url) {
|
|
101
|
+
const imgTypes = ["3gp", "mpg", "mpeg", "mp4", "m4v", "m4p", "ogv", "ogg", "mov", "webm"];
|
|
102
|
+
return checkUrlSuffix(url, imgTypes);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 判断 url 是否带有指定音频后缀
|
|
107
|
+
* @param {string} url
|
|
108
|
+
* @returns
|
|
109
|
+
*/
|
|
110
|
+
export function checkAudioUrl(url) {
|
|
111
|
+
const imgTypes = ["3gp", "adts", "mpeg", "mp3", "mp4", "ogg", "mov", "webm", "rtp", "amr", "wav"];
|
|
112
|
+
return checkUrlSuffix(url, imgTypes);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 获取文件类型(项目内部枚举,如:图片-image、视频-video)
|
|
117
|
+
* @param file
|
|
118
|
+
* @returns
|
|
119
|
+
*/
|
|
120
|
+
export function getFileTypeStr(file) {
|
|
121
|
+
const { type, url = file?.ossUrl } = file || {};
|
|
122
|
+
let fileType = "";
|
|
123
|
+
// 判断文件类型,获取对应展示的数据
|
|
124
|
+
if (url) {
|
|
125
|
+
// 图片
|
|
126
|
+
if (url.startsWith("data:image/") || checkImageUrl(url)) {
|
|
127
|
+
fileType = TYPE_IMG;
|
|
128
|
+
} else if (checkVideoUrl(url)) {
|
|
129
|
+
// 视频
|
|
130
|
+
fileType = TYPE_VIDEO;
|
|
131
|
+
} else if (checkAudioUrl(url)) {
|
|
132
|
+
// 音频
|
|
133
|
+
fileType = TYPE_AUDIO;
|
|
134
|
+
}
|
|
135
|
+
} else if (type) {
|
|
136
|
+
// 图片
|
|
137
|
+
if (type?.startsWith("image/")) {
|
|
138
|
+
fileType = TYPE_IMG;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 视频
|
|
142
|
+
if (type?.startsWith("video/")) {
|
|
143
|
+
fileType = TYPE_VIDEO;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// 音频
|
|
147
|
+
if (type?.startsWith("audio/")) {
|
|
148
|
+
fileType = TYPE_AUDIO;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return fileType || type;
|
|
152
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import _ from "lodash";
|
|
2
|
+
|
|
3
|
+
export function mergeSchema(BaseSchema, InsideSchema, title = "") {
|
|
4
|
+
const _schema = {
|
|
5
|
+
form: BaseSchema.form,
|
|
6
|
+
schema: _.cloneDeep(BaseSchema.schema),
|
|
7
|
+
};
|
|
8
|
+
let idx = Object.keys(_schema.schema.properties).length;
|
|
9
|
+
|
|
10
|
+
if (title) {
|
|
11
|
+
_schema.schema.properties.insideTitle = {
|
|
12
|
+
type: "string",
|
|
13
|
+
"x-component": "Text",
|
|
14
|
+
"x-component-props": {
|
|
15
|
+
content: title || "内部情况",
|
|
16
|
+
},
|
|
17
|
+
"x-designable-id": "insideTitle" + idx,
|
|
18
|
+
"x-index": idx,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
Object.keys(InsideSchema.schema.properties).forEach((key) => {
|
|
23
|
+
const obj = InsideSchema.schema.properties[key];
|
|
24
|
+
idx += 1;
|
|
25
|
+
obj["x-index"] = idx;
|
|
26
|
+
_schema.schema.properties[key] = obj;
|
|
27
|
+
});
|
|
28
|
+
return _schema;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function mergeSchemas(schemas) {
|
|
32
|
+
if (!(Array.isArray(schemas) && schemas.length > 0)) {
|
|
33
|
+
console.error("请传入 schema");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const _schemaList = _.cloneDeep(schemas);
|
|
37
|
+
const _schema = {
|
|
38
|
+
form: _schemaList[0].json.form,
|
|
39
|
+
schema: {
|
|
40
|
+
type: "object",
|
|
41
|
+
properties: {},
|
|
42
|
+
"x-designable-id": _.uniqueId("schema-merge-"),
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
let idx = 0;
|
|
47
|
+
_schemaList.forEach((schema, i) => {
|
|
48
|
+
const titleName = `insideTitle-${i}`;
|
|
49
|
+
_schema.schema.properties[titleName] = {
|
|
50
|
+
type: "string",
|
|
51
|
+
"x-component": "Text",
|
|
52
|
+
"x-component-props": {
|
|
53
|
+
content: schema.title,
|
|
54
|
+
},
|
|
55
|
+
"x-designable-id": titleName,
|
|
56
|
+
"x-index": idx,
|
|
57
|
+
};
|
|
58
|
+
idx += 1;
|
|
59
|
+
Object.keys(schema.json.schema.properties).forEach((key) => {
|
|
60
|
+
const obj = schema.json.schema.properties[key];
|
|
61
|
+
obj["x-index"] = idx;
|
|
62
|
+
_schema.schema.properties[key] = obj;
|
|
63
|
+
idx += 1;
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return _schema;
|
|
68
|
+
}
|
package/src/img-utils.ts
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
export class IMAGE_TYPES {
|
|
2
|
+
static JPEG = "image/jpeg";
|
|
3
|
+
static PNG = "image/png";
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 检测空图片
|
|
8
|
+
* @param img
|
|
9
|
+
* @returns
|
|
10
|
+
*/
|
|
11
|
+
export function checkEmptyImg(img: HTMLImageElement) {
|
|
12
|
+
// 创建一个 Canvas 元素
|
|
13
|
+
const canvas = document.createElement("canvas");
|
|
14
|
+
const ctx = canvas.getContext("2d");
|
|
15
|
+
if (!ctx) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 设置 Canvas 的宽度和高度与图片一致
|
|
20
|
+
canvas.width = img.width;
|
|
21
|
+
canvas.height = img.height;
|
|
22
|
+
// 将图片绘制到Canvas上
|
|
23
|
+
ctx.drawImage(img, 0, 0);
|
|
24
|
+
// 获取Canvas中的像素数据
|
|
25
|
+
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
26
|
+
const data = imageData.data;
|
|
27
|
+
|
|
28
|
+
// 判断从左上角到右下角的像素是否都是黑色
|
|
29
|
+
let topLeftToBottomRight = true;
|
|
30
|
+
|
|
31
|
+
const iUp = 0;
|
|
32
|
+
const redUp = data[iUp];
|
|
33
|
+
const greenUp = data[iUp + 1];
|
|
34
|
+
const blueUp = data[iUp + 2];
|
|
35
|
+
const alphaUp = data[iUp + 3];
|
|
36
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
37
|
+
const red = data[i];
|
|
38
|
+
const green = data[i + 1];
|
|
39
|
+
const blue = data[i + 2];
|
|
40
|
+
const alpha = data[i + 3];
|
|
41
|
+
|
|
42
|
+
if (red !== redUp || green !== greenUp || blue !== blueUp || alpha !== alphaUp) {
|
|
43
|
+
topLeftToBottomRight = false;
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 判断从右上角到左下角的像素是否都是黑色
|
|
49
|
+
let topRightToBottomLeft = true;
|
|
50
|
+
const jDown = data.length - 4;
|
|
51
|
+
const redDown = data[jDown];
|
|
52
|
+
const greenDown = data[jDown + 1];
|
|
53
|
+
const blueDown = data[jDown + 2];
|
|
54
|
+
const alphaDown = data[jDown + 3];
|
|
55
|
+
|
|
56
|
+
for (let j = jDown; j >= 0; j -= 4) {
|
|
57
|
+
const red = data[j];
|
|
58
|
+
const green = data[j + 1];
|
|
59
|
+
const blue = data[j + 2];
|
|
60
|
+
const alpha = data[j + 3];
|
|
61
|
+
|
|
62
|
+
if (red !== redDown || green !== greenDown || blue !== blueDown || alpha !== alphaDown) {
|
|
63
|
+
topRightToBottomLeft = false;
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 打印结果
|
|
69
|
+
if (topLeftToBottomRight && topRightToBottomLeft) {
|
|
70
|
+
return false;
|
|
71
|
+
} else {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 获取dom元素宽高
|
|
78
|
+
* @param d dom元素
|
|
79
|
+
* @returns {{width: number, height: number}}
|
|
80
|
+
*/
|
|
81
|
+
export function getDomWH(d: HTMLElement | HTMLImageElement | HTMLCanvasElement) {
|
|
82
|
+
if (d instanceof Image || d instanceof HTMLCanvasElement) {
|
|
83
|
+
return {
|
|
84
|
+
width: d.width || d.offsetWidth,
|
|
85
|
+
height: d.width || d.offsetHeight,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
width: d.offsetWidth,
|
|
90
|
+
height: d.offsetHeight,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 设置dom元素宽高
|
|
96
|
+
* @param d dom元素
|
|
97
|
+
* @param w 宽
|
|
98
|
+
* @param h 高
|
|
99
|
+
*/
|
|
100
|
+
export function setDomWH(dom: HTMLElement, w: number, h: number) {
|
|
101
|
+
dom.setAttribute("width", `${w}`);
|
|
102
|
+
dom.setAttribute("height", `${h}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 获取当前 canvas 图片 Blob 对象
|
|
107
|
+
* @param canvas
|
|
108
|
+
* @returns {Promise<Blob>}
|
|
109
|
+
*/
|
|
110
|
+
export function getCanvasPic(canvas: HTMLCanvasElement): Blob {
|
|
111
|
+
var gl = canvas.getContext("2d", { preserveDrawingBuffer: true });
|
|
112
|
+
|
|
113
|
+
return dataURItoBlob(canvas.toDataURL(IMAGE_TYPES.PNG, 1));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* base64 字符串转 blob
|
|
118
|
+
* @param base64
|
|
119
|
+
* @returns
|
|
120
|
+
*/
|
|
121
|
+
export function dataURItoBlob(base64: string): Blob {
|
|
122
|
+
let arr = base64.split(",");
|
|
123
|
+
let mime = arr[0]?.match(/:(.*?);/)?.[1];
|
|
124
|
+
let bstr = atob(arr[1]);
|
|
125
|
+
let n = bstr.length;
|
|
126
|
+
let u8arr = new Uint8Array(n);
|
|
127
|
+
while (n--) {
|
|
128
|
+
u8arr[n] = bstr.charCodeAt(n);
|
|
129
|
+
}
|
|
130
|
+
return new Blob([u8arr], { type: mime });
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* 获取图片元素
|
|
135
|
+
* @param imgSrc
|
|
136
|
+
* @returns
|
|
137
|
+
*/
|
|
138
|
+
export function getImgEle(imgSrc: string): Promise<HTMLImageElement> {
|
|
139
|
+
return new Promise((resolve) => {
|
|
140
|
+
const img = new Image();
|
|
141
|
+
img.onload = function () {
|
|
142
|
+
resolve(img);
|
|
143
|
+
};
|
|
144
|
+
img.src = imgSrc;
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 获取图片 Base64 字符串
|
|
150
|
+
* @param imgSrc
|
|
151
|
+
* @returns
|
|
152
|
+
*/
|
|
153
|
+
export function getImgBase64(imgSrc: string): Promise<string> {
|
|
154
|
+
return getImgEle(imgSrc).then((img) => {
|
|
155
|
+
const canvas = document.createElement("canvas");
|
|
156
|
+
let { width, height } = getDomWH(img);
|
|
157
|
+
setDomWH(canvas, width, height);
|
|
158
|
+
const ctx = canvas.getContext("2d");
|
|
159
|
+
ctx && ctx.drawImage(img, 0, 0, width, height, 0, 0, width, height);
|
|
160
|
+
return canvas.toDataURL(IMAGE_TYPES.PNG, 1);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* 通过图片地址获取对应 canvas
|
|
166
|
+
* @param imgSrc
|
|
167
|
+
* @returns
|
|
168
|
+
*/
|
|
169
|
+
export function getCanvas(imgSrc: string): Promise<HTMLCanvasElement> {
|
|
170
|
+
return getImgEle(imgSrc).then((img) => {
|
|
171
|
+
const canvas = document.createElement("canvas");
|
|
172
|
+
let { width, height } = getDomWH(img);
|
|
173
|
+
setDomWH(canvas, width, height);
|
|
174
|
+
const ctx = canvas.getContext("2d");
|
|
175
|
+
ctx && ctx.drawImage(img, 0, 0, width, height, 0, 0, width, height);
|
|
176
|
+
return canvas;
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* 通过图片地址获取对应 canvas
|
|
182
|
+
* @param img
|
|
183
|
+
* @returns
|
|
184
|
+
*/
|
|
185
|
+
export function getCanvasByImg(img: HTMLImageElement): HTMLCanvasElement {
|
|
186
|
+
const canvas = document.createElement("canvas");
|
|
187
|
+
let { width, height } = getDomWH(img);
|
|
188
|
+
setDomWH(canvas, width, height);
|
|
189
|
+
const ctx = canvas.getContext("2d");
|
|
190
|
+
ctx && ctx.drawImage(img, 0, 0, width, height, 0, 0, width, height);
|
|
191
|
+
return canvas;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* 截取图片
|
|
196
|
+
* @param img
|
|
197
|
+
* @param opt
|
|
198
|
+
* @param opt.startX
|
|
199
|
+
* @param opt.startY
|
|
200
|
+
* @param opt.width
|
|
201
|
+
* @param opt.height
|
|
202
|
+
* @returns Promise<string>
|
|
203
|
+
*/
|
|
204
|
+
export function cropImage(
|
|
205
|
+
img: HTMLImageElement | HTMLCanvasElement,
|
|
206
|
+
opt: { startX: number; startY: number; width: number; height: number },
|
|
207
|
+
) {
|
|
208
|
+
return cropImageToCanvas(img, opt).toDataURL(IMAGE_TYPES.PNG, 1);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* 截取图片
|
|
213
|
+
* @param img
|
|
214
|
+
* @param opt
|
|
215
|
+
* @param opt.startX
|
|
216
|
+
* @param opt.startY
|
|
217
|
+
* @param opt.width
|
|
218
|
+
* @param opt.height
|
|
219
|
+
* @returns Promise<HTMLCanvasElement>
|
|
220
|
+
*/
|
|
221
|
+
export function cropImageToCanvas(
|
|
222
|
+
img: HTMLImageElement | HTMLCanvasElement,
|
|
223
|
+
opt: { startX: number; startY: number; width: number; height: number },
|
|
224
|
+
) {
|
|
225
|
+
const { startX, startY, width, height } = opt;
|
|
226
|
+
const canvas = document.createElement("canvas");
|
|
227
|
+
const ctx = canvas.getContext("2d");
|
|
228
|
+
// 设置 canvas 的宽度和高度为裁剪后的尺寸
|
|
229
|
+
canvas.width = width; // 裁剪后的宽度
|
|
230
|
+
canvas.height = height; // 裁剪后的高度
|
|
231
|
+
// 在 canvas 上绘制裁剪后的图像
|
|
232
|
+
ctx?.drawImage(img, startX, startY, width, height, 0, 0, width, height);
|
|
233
|
+
// 可以将裁剪后的图像数据获取出来
|
|
234
|
+
return canvas;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* 绘制图片
|
|
239
|
+
* @param img
|
|
240
|
+
* @param opt
|
|
241
|
+
* @param opt.startX
|
|
242
|
+
* @param opt.startY
|
|
243
|
+
* @param opt.width
|
|
244
|
+
* @param opt.height
|
|
245
|
+
* @returns Promise<string>
|
|
246
|
+
*/
|
|
247
|
+
export function imgToCanvas(img: HTMLImageElement) {
|
|
248
|
+
const canvas = document.createElement("canvas");
|
|
249
|
+
const ctx = canvas.getContext("2d");
|
|
250
|
+
canvas.width = img.width;
|
|
251
|
+
canvas.height = img.height;
|
|
252
|
+
ctx?.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
|
|
253
|
+
return canvas;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* 缩放图片
|
|
258
|
+
* @param img
|
|
259
|
+
* @param opt
|
|
260
|
+
* @returns base64
|
|
261
|
+
*/
|
|
262
|
+
export function scaleImage(img: HTMLImageElement | HTMLCanvasElement, opt = { scaleFactor: 1 }) {
|
|
263
|
+
return scaleImageToCanvas(img, opt).toDataURL(IMAGE_TYPES.PNG, 1);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* 缩放图片,返回 canvas
|
|
268
|
+
* @param img
|
|
269
|
+
* @param opt
|
|
270
|
+
* @returns canvas
|
|
271
|
+
*/
|
|
272
|
+
export function scaleImageToCanvas(img: HTMLImageElement | HTMLCanvasElement, opt = { scaleFactor: 1 }) {
|
|
273
|
+
const { scaleFactor = 1 } = opt;
|
|
274
|
+
const canvas = document.createElement("canvas");
|
|
275
|
+
const ctx = canvas.getContext("2d");
|
|
276
|
+
canvas.width = img.width * scaleFactor;
|
|
277
|
+
canvas.height = img.height * scaleFactor;
|
|
278
|
+
ctx?.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height);
|
|
279
|
+
return canvas;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* 图片转为 base64
|
|
284
|
+
* @param img
|
|
285
|
+
* @returns
|
|
286
|
+
*/
|
|
287
|
+
export async function imgToBase64(img: string | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement) {
|
|
288
|
+
if (!img || img instanceof Blob) {
|
|
289
|
+
return img;
|
|
290
|
+
}
|
|
291
|
+
let _img = img;
|
|
292
|
+
if (img instanceof Image) {
|
|
293
|
+
_img = img.src;
|
|
294
|
+
} else if (img instanceof HTMLVideoElement) {
|
|
295
|
+
// 从视频中获取图片
|
|
296
|
+
const canvas = document.createElement("canvas");
|
|
297
|
+
let { width, height } = getDomWH(img);
|
|
298
|
+
setDomWH(canvas, width, height);
|
|
299
|
+
const ctx = canvas.getContext("2d");
|
|
300
|
+
ctx && ctx.drawImage(img, 0, 0, width, height, 0, 0, width, height);
|
|
301
|
+
_img = canvas.toDataURL(IMAGE_TYPES.PNG, 1);
|
|
302
|
+
} else if (img instanceof HTMLCanvasElement) {
|
|
303
|
+
_img = img.toDataURL(IMAGE_TYPES.PNG, 1);
|
|
304
|
+
} else if (typeof _img === "string" && !_img.startsWith("data:image/")) {
|
|
305
|
+
// 加载图片,并获取图片 base64
|
|
306
|
+
_img = await getImgBase64(_img);
|
|
307
|
+
}
|
|
308
|
+
return _img;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* 图片转为 Blob
|
|
313
|
+
* @param img
|
|
314
|
+
* @returns
|
|
315
|
+
*/
|
|
316
|
+
export async function imgToBlob(img: string | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement): Promise<Blob> {
|
|
317
|
+
if (!img) {
|
|
318
|
+
throw new Error("请传入图片数据");
|
|
319
|
+
}
|
|
320
|
+
if (img instanceof Blob) {
|
|
321
|
+
return Promise.resolve(img);
|
|
322
|
+
}
|
|
323
|
+
const _img = await imgToBase64(img);
|
|
324
|
+
if (typeof _img !== "string") {
|
|
325
|
+
throw new Error("传入的图片数据不正确");
|
|
326
|
+
}
|
|
327
|
+
return dataURItoBlob(_img);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* 获取图片的 base64、blob 格式
|
|
332
|
+
* @param img
|
|
333
|
+
*/
|
|
334
|
+
export async function getAllTypeImg(img: string | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement) {
|
|
335
|
+
const base64 = await imgToBase64(img);
|
|
336
|
+
return {
|
|
337
|
+
base64,
|
|
338
|
+
blob: typeof base64 === "string" && dataURItoBlob(base64),
|
|
339
|
+
};
|
|
340
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const DEFAULT_POSITION = {
|
|
2
|
+
lon: 120.168893,
|
|
3
|
+
lat: 30.225404,
|
|
4
|
+
addr: "浙江省杭州市上城区南星街道杭州西湖风景名胜区",
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 获取当前定位
|
|
9
|
+
* @param config
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
export function getCurrentPosition(config?: any): Promise<any> {
|
|
13
|
+
return new Promise((resolve, reject) => {
|
|
14
|
+
navigator?.geolocation?.getCurrentPosition(
|
|
15
|
+
(position) => {
|
|
16
|
+
resolve(position);
|
|
17
|
+
},
|
|
18
|
+
reject,
|
|
19
|
+
{
|
|
20
|
+
enableHighAccuracy: true,
|
|
21
|
+
timeout: 5000,
|
|
22
|
+
...config,
|
|
23
|
+
},
|
|
24
|
+
);
|
|
25
|
+
});
|
|
26
|
+
}
|
package/src/nanoid.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { customAlphabet } from "nanoid";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 指定 nanoid 字符集合
|
|
5
|
+
* 数字和大小写字母
|
|
6
|
+
*/
|
|
7
|
+
export const numALetters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
8
|
+
|
|
9
|
+
/** nanoid 数字和大小写字母 */
|
|
10
|
+
export const nanoidNumALetters = customAlphabet(numALetters, 8);
|