@unif/react-native-camera 1.0.10 → 1.1.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/lib/commonjs/camera/Camera.js +40 -7
- package/lib/commonjs/camera/Camera.js.map +1 -1
- package/lib/commonjs/camera/footer/Footer.js +3 -2
- package/lib/commonjs/camera/footer/Footer.js.map +1 -1
- package/lib/commonjs/camera/preview/PreView.js +6 -2
- package/lib/commonjs/camera/preview/PreView.js.map +1 -1
- package/lib/commonjs/camera/preview/PreViewContainer.js +3 -2
- package/lib/commonjs/camera/preview/PreViewContainer.js.map +1 -1
- package/lib/commonjs/camera/preview/PreviewFooter.js +1 -1
- package/lib/commonjs/camera/preview/SinglePre.js +7 -7
- package/lib/commonjs/camera/preview/SinglePre.js.map +1 -1
- package/lib/commonjs/camera/setup/SetUp.js +6 -10
- package/lib/commonjs/camera/setup/SetUp.js.map +1 -1
- package/lib/commonjs/camera/watermark/Render.js +110 -0
- package/lib/commonjs/camera/watermark/Render.js.map +1 -0
- package/lib/commonjs/camera/watermark/ViewShotWatermark.js +88 -0
- package/lib/commonjs/camera/watermark/ViewShotWatermark.js.map +1 -0
- package/lib/commonjs/camera/watermark/index.js +21 -0
- package/lib/commonjs/camera/watermark/index.js.map +1 -0
- package/lib/commonjs/utils/common.js +3 -2
- package/lib/commonjs/utils/common.js.map +1 -1
- package/lib/commonjs/utils/index.js +22 -0
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/commonjs/utils/interface.js +1 -1
- package/lib/commonjs/utils/render-item.js +3 -2
- package/lib/commonjs/utils/render-item.js.map +1 -1
- package/lib/commonjs/utils/util.js +23 -0
- package/lib/commonjs/utils/util.js.map +1 -0
- package/lib/commonjs/utils/watermark.js +43 -0
- package/lib/commonjs/utils/watermark.js.map +1 -0
- package/lib/module/camera/Camera.js +41 -7
- package/lib/module/camera/Camera.js.map +1 -1
- package/lib/module/camera/footer/Footer.js +4 -3
- package/lib/module/camera/footer/Footer.js.map +1 -1
- package/lib/module/camera/index.js +1 -1
- package/lib/module/camera/preview/PreView.js +6 -2
- package/lib/module/camera/preview/PreView.js.map +1 -1
- package/lib/module/camera/preview/PreViewContainer.js +3 -2
- package/lib/module/camera/preview/PreViewContainer.js.map +1 -1
- package/lib/module/camera/preview/PreviewFooter.js +1 -1
- package/lib/module/camera/preview/SinglePre.js +7 -7
- package/lib/module/camera/preview/SinglePre.js.map +1 -1
- package/lib/module/camera/setup/SetUp.js +6 -10
- package/lib/module/camera/setup/SetUp.js.map +1 -1
- package/lib/module/camera/watermark/Render.js +102 -0
- package/lib/module/camera/watermark/Render.js.map +1 -0
- package/lib/module/camera/watermark/ViewShotWatermark.js +78 -0
- package/lib/module/camera/watermark/ViewShotWatermark.js.map +1 -0
- package/lib/module/camera/watermark/index.js +13 -0
- package/lib/module/camera/watermark/index.js.map +1 -0
- package/lib/module/utils/common.js +2 -1
- package/lib/module/utils/common.js.map +1 -1
- package/lib/module/utils/index.js +3 -1
- package/lib/module/utils/index.js.map +1 -1
- package/lib/module/utils/interface.js +1 -1
- package/lib/module/utils/render-item.js +3 -2
- package/lib/module/utils/render-item.js.map +1 -1
- package/lib/module/utils/util.js +16 -0
- package/lib/module/utils/util.js.map +1 -0
- package/lib/module/utils/watermark.js +33 -0
- package/lib/module/utils/watermark.js.map +1 -0
- package/lib/typescript/src/camera/Camera.d.ts.map +1 -1
- package/lib/typescript/src/camera/footer/Footer.d.ts.map +1 -1
- package/lib/typescript/src/camera/preview/PreView.d.ts.map +1 -1
- package/lib/typescript/src/camera/preview/SinglePre.d.ts +2 -0
- package/lib/typescript/src/camera/preview/SinglePre.d.ts.map +1 -1
- package/lib/typescript/src/camera/watermark/Render.d.ts +26 -0
- package/lib/typescript/src/camera/watermark/Render.d.ts.map +1 -0
- package/lib/typescript/src/camera/watermark/ViewShotWatermark.d.ts +33 -0
- package/lib/typescript/src/camera/watermark/ViewShotWatermark.d.ts.map +1 -0
- package/lib/typescript/src/camera/watermark/index.d.ts +4 -0
- package/lib/typescript/src/camera/watermark/index.d.ts.map +1 -0
- package/lib/typescript/src/utils/common.d.ts +1 -0
- package/lib/typescript/src/utils/common.d.ts.map +1 -1
- package/lib/typescript/src/utils/index.d.ts +2 -0
- package/lib/typescript/src/utils/index.d.ts.map +1 -1
- package/lib/typescript/src/utils/interface.d.ts +10 -0
- package/lib/typescript/src/utils/interface.d.ts.map +1 -1
- package/lib/typescript/src/utils/render-item.d.ts.map +1 -1
- package/lib/typescript/src/utils/util.d.ts +2 -0
- package/lib/typescript/src/utils/util.d.ts.map +1 -0
- package/lib/typescript/src/utils/watermark.d.ts +11 -0
- package/lib/typescript/src/utils/watermark.d.ts.map +1 -0
- package/package.json +12 -5
- package/src/camera/Camera.tsx +144 -104
- package/src/camera/footer/Footer.tsx +3 -1
- package/src/camera/index.tsx +1 -1
- package/src/camera/preview/PreView.tsx +4 -2
- package/src/camera/preview/PreViewContainer.tsx +2 -1
- package/src/camera/preview/PreviewFooter.tsx +1 -1
- package/src/camera/preview/SinglePre.tsx +5 -10
- package/src/camera/setup/SetUp.tsx +4 -3
- package/src/camera/watermark/Render.tsx +128 -0
- package/src/camera/watermark/ViewShotWatermark.tsx +81 -0
- package/src/camera/watermark/index.tsx +12 -0
- package/src/utils/common.ts +3 -1
- package/src/utils/index.ts +3 -1
- package/src/utils/interface.ts +12 -1
- package/src/utils/render-item.tsx +3 -2
- package/src/utils/util.ts +15 -0
- package/src/utils/watermark.ts +45 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @Author: 刘利军
|
|
3
3
|
* @Date: 2024-12-02 11:52:31
|
|
4
4
|
* @LastEditors: 刘利军
|
|
5
|
-
* @LastEditTime: 2024-12-
|
|
5
|
+
* @LastEditTime: 2024-12-30 13:11:06
|
|
6
6
|
* @Description:
|
|
7
7
|
* @PageName:
|
|
8
8
|
*/
|
|
@@ -99,11 +99,11 @@ const SetUp: React.FC<{
|
|
|
99
99
|
return (
|
|
100
100
|
<>
|
|
101
101
|
{openHeader && (
|
|
102
|
-
<View style={
|
|
102
|
+
<View style={[styles.top, styles.header, { top: insets.top + 10 }]}>
|
|
103
103
|
{/* <Text style={styles.text}></Text> */}
|
|
104
104
|
</View>
|
|
105
105
|
)}
|
|
106
|
-
<View style={
|
|
106
|
+
<View style={[styles.top, styles.tools]}>
|
|
107
107
|
<View style={styles.tool}>
|
|
108
108
|
<TouchableOpacity
|
|
109
109
|
style={styles.toolImg}
|
|
@@ -237,6 +237,7 @@ const styles = StyleSheet.create({
|
|
|
237
237
|
...StyleSheet.absoluteFillObject,
|
|
238
238
|
marginHorizontal: 20,
|
|
239
239
|
bottom: undefined,
|
|
240
|
+
zIndex: 9,
|
|
240
241
|
},
|
|
241
242
|
header: {
|
|
242
243
|
display: 'flex',
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { Dimensions, Image, StyleSheet, View } from 'react-native';
|
|
2
|
+
import React, { useState } from 'react';
|
|
3
|
+
import {
|
|
4
|
+
getContentMeasure,
|
|
5
|
+
getMeasure,
|
|
6
|
+
lastPx,
|
|
7
|
+
type WatermarkType,
|
|
8
|
+
} from '../../utils';
|
|
9
|
+
import Canvas, { Image as CanvasImage } from 'react-native-canvas';
|
|
10
|
+
|
|
11
|
+
const Render: React.FC<{
|
|
12
|
+
data: WatermarkType;
|
|
13
|
+
zIndex?: number;
|
|
14
|
+
}> = ({ data, zIndex }) => {
|
|
15
|
+
const [waterBase64, setWaterBase64] = useState<string>();
|
|
16
|
+
|
|
17
|
+
const getMarkSize = async (width: number, height: number) => {
|
|
18
|
+
let defaultWidth = lastPx(120);
|
|
19
|
+
let defaultHeight = lastPx(64);
|
|
20
|
+
if (!data?.image) {
|
|
21
|
+
defaultWidth = width;
|
|
22
|
+
defaultHeight = height;
|
|
23
|
+
}
|
|
24
|
+
return [data?.width ?? defaultWidth, data?.height ?? defaultHeight];
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const handleImageRect = async (canvas: Canvas) => {
|
|
28
|
+
const ctx = canvas.getContext('2d');
|
|
29
|
+
const {
|
|
30
|
+
image,
|
|
31
|
+
content = [],
|
|
32
|
+
rotate = data.image ? 0 : -22,
|
|
33
|
+
gap = [100, 100],
|
|
34
|
+
} = data;
|
|
35
|
+
|
|
36
|
+
const measure = await getContentMeasure(ctx, content);
|
|
37
|
+
|
|
38
|
+
const [markWidth, markHeight] = await getMarkSize(
|
|
39
|
+
measure.width,
|
|
40
|
+
measure.height
|
|
41
|
+
);
|
|
42
|
+
const x = lastPx(gap[0] as number);
|
|
43
|
+
const y = lastPx(gap[1] as number);
|
|
44
|
+
|
|
45
|
+
const width = lastPx(markWidth as number);
|
|
46
|
+
const height = lastPx(markHeight as number);
|
|
47
|
+
canvas.width = width + x;
|
|
48
|
+
canvas.height = height + y;
|
|
49
|
+
|
|
50
|
+
const angle = (Math.PI * rotate) / 180;
|
|
51
|
+
ctx.translate(canvas.width * 0.5, canvas.height * 0.5);
|
|
52
|
+
const setDataURL = async () => {
|
|
53
|
+
const imgBase64 = await canvas.toDataURL();
|
|
54
|
+
const base = imgBase64.replace(/^"|"$/g, '');
|
|
55
|
+
setWaterBase64(base.split(',')[1]);
|
|
56
|
+
};
|
|
57
|
+
if (image) {
|
|
58
|
+
const canvasImage = new CanvasImage(canvas);
|
|
59
|
+
canvasImage.crossOrigin = 'anonymous';
|
|
60
|
+
canvasImage.src = image;
|
|
61
|
+
canvasImage.width = width;
|
|
62
|
+
canvasImage.height = height;
|
|
63
|
+
|
|
64
|
+
ctx.rotate(angle);
|
|
65
|
+
|
|
66
|
+
canvasImage.addEventListener('load', async () => {
|
|
67
|
+
ctx.drawImage(
|
|
68
|
+
canvasImage,
|
|
69
|
+
-canvas.height / 2,
|
|
70
|
+
-canvas.width / 2,
|
|
71
|
+
width,
|
|
72
|
+
height
|
|
73
|
+
);
|
|
74
|
+
setDataURL();
|
|
75
|
+
});
|
|
76
|
+
} else {
|
|
77
|
+
if (content.length > 0) {
|
|
78
|
+
ctx.font = `${lastPx(22)}px Arial`;
|
|
79
|
+
ctx.textAlign = 'center';
|
|
80
|
+
ctx.rotate(angle);
|
|
81
|
+
for (let index = 0; index < content.length; index++) {
|
|
82
|
+
const element = content[index];
|
|
83
|
+
const metrics = await getMeasure(ctx, element as string);
|
|
84
|
+
ctx.fillText(element as string, 0, metrics.height * (index + 1));
|
|
85
|
+
}
|
|
86
|
+
setDataURL();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
return (
|
|
91
|
+
<View style={[styles.container, { zIndex }]}>
|
|
92
|
+
<View style={styles.watermark}>
|
|
93
|
+
{waterBase64 ? (
|
|
94
|
+
<Image
|
|
95
|
+
resizeMode="repeat"
|
|
96
|
+
source={{ uri: `data:image/png;base64,${waterBase64}` }}
|
|
97
|
+
style={{
|
|
98
|
+
width: Dimensions.get('window').width,
|
|
99
|
+
height: Dimensions.get('window').height,
|
|
100
|
+
}}
|
|
101
|
+
/>
|
|
102
|
+
) : (
|
|
103
|
+
<Canvas
|
|
104
|
+
ref={(canvas: Canvas) => canvas && handleImageRect(canvas)}
|
|
105
|
+
style={styles.canvas}
|
|
106
|
+
/>
|
|
107
|
+
)}
|
|
108
|
+
</View>
|
|
109
|
+
</View>
|
|
110
|
+
);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export default Render;
|
|
114
|
+
|
|
115
|
+
export const styles = StyleSheet.create({
|
|
116
|
+
container: {
|
|
117
|
+
...StyleSheet.absoluteFillObject,
|
|
118
|
+
},
|
|
119
|
+
watermark: {
|
|
120
|
+
display: 'flex',
|
|
121
|
+
flexWrap: 'wrap',
|
|
122
|
+
flex: 1,
|
|
123
|
+
flexDirection: 'row',
|
|
124
|
+
},
|
|
125
|
+
canvas: {
|
|
126
|
+
display: 'none',
|
|
127
|
+
},
|
|
128
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: 刘利军
|
|
3
|
+
* @Date: 2024-12-25 16:56:42
|
|
4
|
+
* @LastEditors: 刘利军
|
|
5
|
+
* @LastEditTime: 2024-12-30 13:07:33
|
|
6
|
+
* @Description:
|
|
7
|
+
* @PageName:
|
|
8
|
+
*/
|
|
9
|
+
import { Image, StyleSheet, Text, View } from 'react-native';
|
|
10
|
+
import React, { useRef } from 'react';
|
|
11
|
+
import ViewShot from 'react-native-view-shot';
|
|
12
|
+
import WaterMarkRender from './Render';
|
|
13
|
+
import {
|
|
14
|
+
formatUri,
|
|
15
|
+
MAX_ZINDEX,
|
|
16
|
+
pxToDpWidth,
|
|
17
|
+
type CustomPhotoFile,
|
|
18
|
+
type WatermarkType,
|
|
19
|
+
} from '../../utils';
|
|
20
|
+
|
|
21
|
+
const ViewShotWatermark: React.FC<{
|
|
22
|
+
data?: CustomPhotoFile;
|
|
23
|
+
watermark?: WatermarkType;
|
|
24
|
+
onChange: (photo: CustomPhotoFile) => void;
|
|
25
|
+
}> = ({ data, watermark, onChange }) => {
|
|
26
|
+
const viewShotRef = useRef<ViewShot>(null);
|
|
27
|
+
if (!data || !watermark) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const autoSaveWatermark = async () => {
|
|
32
|
+
const img = await viewShotRef.current?.capture?.();
|
|
33
|
+
onChange({ ...data, path: img || data.path });
|
|
34
|
+
};
|
|
35
|
+
return (
|
|
36
|
+
<>
|
|
37
|
+
<ViewShot ref={viewShotRef} style={styles.container}>
|
|
38
|
+
<Image
|
|
39
|
+
source={{ uri: formatUri(data.path) }}
|
|
40
|
+
style={styles.container}
|
|
41
|
+
onLoadEnd={() => {
|
|
42
|
+
setTimeout(() => {
|
|
43
|
+
autoSaveWatermark();
|
|
44
|
+
}, 800);
|
|
45
|
+
}}
|
|
46
|
+
/>
|
|
47
|
+
<WaterMarkRender data={watermark} zIndex={MAX_ZINDEX + 1} />
|
|
48
|
+
</ViewShot>
|
|
49
|
+
<View style={styles.footer}>
|
|
50
|
+
<Text style={styles.text}>生成中...</Text>
|
|
51
|
+
</View>
|
|
52
|
+
</>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export default ViewShotWatermark;
|
|
57
|
+
|
|
58
|
+
export const styles = StyleSheet.create({
|
|
59
|
+
container: {
|
|
60
|
+
flex: 1,
|
|
61
|
+
position: 'absolute',
|
|
62
|
+
left: 0,
|
|
63
|
+
right: 0,
|
|
64
|
+
top: 0,
|
|
65
|
+
bottom: 0,
|
|
66
|
+
backgroundColor: '#fff',
|
|
67
|
+
zIndex: MAX_ZINDEX,
|
|
68
|
+
},
|
|
69
|
+
footer: {
|
|
70
|
+
position: 'absolute',
|
|
71
|
+
left: 0,
|
|
72
|
+
right: 0,
|
|
73
|
+
bottom: 24,
|
|
74
|
+
zIndex: MAX_ZINDEX + 2,
|
|
75
|
+
},
|
|
76
|
+
text: {
|
|
77
|
+
color: '#fff',
|
|
78
|
+
textAlign: 'center',
|
|
79
|
+
fontSize: pxToDpWidth(32),
|
|
80
|
+
},
|
|
81
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: 刘利军
|
|
3
|
+
* @Date: 2024-12-25 11:01:20
|
|
4
|
+
* @LastEditors: 刘利军
|
|
5
|
+
* @LastEditTime: 2024-12-30 13:08:49
|
|
6
|
+
* @Description:
|
|
7
|
+
* @PageName:
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import WaterMarkRender from './Render';
|
|
11
|
+
import ViewShotWatermark from './ViewShotWatermark';
|
|
12
|
+
export { WaterMarkRender, ViewShotWatermark };
|
package/src/utils/common.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @Author: 刘利军
|
|
3
3
|
* @Date: 2024-01-11 14:53:09
|
|
4
4
|
* @LastEditors: 刘利军
|
|
5
|
-
* @LastEditTime: 2024-12-
|
|
5
|
+
* @LastEditTime: 2024-12-25 17:43:07
|
|
6
6
|
* @Description:
|
|
7
7
|
* @PageName:
|
|
8
8
|
*/
|
|
@@ -26,6 +26,8 @@ export const MAX_ZOOM_FACTOR = 10;
|
|
|
26
26
|
// Control Button like Flash
|
|
27
27
|
export const CONTROL_BUTTON_SIZE = 44;
|
|
28
28
|
|
|
29
|
+
export const MAX_ZINDEX = 99999;
|
|
30
|
+
|
|
29
31
|
// 相机拍照模式
|
|
30
32
|
export const CameraModeList: CameraModeListItem[] = [
|
|
31
33
|
{ label: '连拍', value: 'continuous' },
|
package/src/utils/index.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @Author: 刘利军
|
|
3
3
|
* @Date: 2024-01-11 14:53:09
|
|
4
4
|
* @LastEditors: 刘利军
|
|
5
|
-
* @LastEditTime: 2024-12-17
|
|
5
|
+
* @LastEditTime: 2024-12-25 17:48:42
|
|
6
6
|
* @Description:
|
|
7
7
|
* @PageName:
|
|
8
8
|
*/
|
|
@@ -10,3 +10,5 @@ export * from './common';
|
|
|
10
10
|
export * from './render-item';
|
|
11
11
|
export * from './px-to-dp';
|
|
12
12
|
export * from './interface';
|
|
13
|
+
export * from './watermark';
|
|
14
|
+
export * from './util';
|
package/src/utils/interface.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @Author: 刘利军
|
|
3
3
|
* @Date: 2024-01-12 11:38:13
|
|
4
4
|
* @LastEditors: 刘利军
|
|
5
|
-
* @LastEditTime: 2024-12-
|
|
5
|
+
* @LastEditTime: 2024-12-27 10:42:36
|
|
6
6
|
* @Description:
|
|
7
7
|
* @PageName:
|
|
8
8
|
*/
|
|
@@ -45,6 +45,7 @@ export type DataRetainedModeType = 'retain' | 'clear';
|
|
|
45
45
|
export type CameraProps = {
|
|
46
46
|
cameraMode: CameraModeType[];
|
|
47
47
|
dataRetainedMode: DataRetainedModeType;
|
|
48
|
+
watermark?: WatermarkType;
|
|
48
49
|
};
|
|
49
50
|
|
|
50
51
|
export type CameraModeListItem = {
|
|
@@ -77,6 +78,7 @@ import type { PhotoFile } from 'react-native-vision-camera';
|
|
|
77
78
|
|
|
78
79
|
export interface CustomPhotoFile extends PhotoFile {
|
|
79
80
|
mode: CameraMode;
|
|
81
|
+
frontTime: number;
|
|
80
82
|
}
|
|
81
83
|
|
|
82
84
|
export interface ConfirmConfigProps {
|
|
@@ -88,3 +90,12 @@ export interface ConfirmRef {
|
|
|
88
90
|
open: (config?: ConfirmConfigProps) => Promise<boolean>;
|
|
89
91
|
close: () => void;
|
|
90
92
|
}
|
|
93
|
+
|
|
94
|
+
export type WatermarkType = {
|
|
95
|
+
content?: string[];
|
|
96
|
+
image?: string;
|
|
97
|
+
gap?: number[]; // 水印之间距离
|
|
98
|
+
rotate?: number; // 水印旋转角度
|
|
99
|
+
width?: number;
|
|
100
|
+
height?: number;
|
|
101
|
+
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @Author: 刘利军
|
|
3
3
|
* @Date: 2024-12-17 16:02:49
|
|
4
4
|
* @LastEditors: 刘利军
|
|
5
|
-
* @LastEditTime: 2024-12-
|
|
5
|
+
* @LastEditTime: 2024-12-25 17:50:26
|
|
6
6
|
* @Description:
|
|
7
7
|
* @PageName:
|
|
8
8
|
*/
|
|
@@ -11,6 +11,7 @@ import type { CarouselRenderItem } from 'react-native-reanimated-carousel';
|
|
|
11
11
|
import { SlideItem } from '../components';
|
|
12
12
|
import React from 'react';
|
|
13
13
|
import type { PhotoFile } from 'react-native-vision-camera';
|
|
14
|
+
import { formatUri } from './util';
|
|
14
15
|
|
|
15
16
|
interface Options {
|
|
16
17
|
rounded?: boolean;
|
|
@@ -28,7 +29,7 @@ export const renderItem =
|
|
|
28
29
|
return (
|
|
29
30
|
<SlideItem
|
|
30
31
|
key={index}
|
|
31
|
-
source={{ uri:
|
|
32
|
+
source={{ uri: formatUri(item.path) }}
|
|
32
33
|
index={index}
|
|
33
34
|
rounded={rounded}
|
|
34
35
|
style={style}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: 刘利军
|
|
3
|
+
* @Date: 2024-12-25 17:48:18
|
|
4
|
+
* @LastEditors: 刘利军
|
|
5
|
+
* @LastEditTime: 2024-12-25 17:48:44
|
|
6
|
+
* @Description:
|
|
7
|
+
* @PageName:
|
|
8
|
+
*/
|
|
9
|
+
export const formatUri = (uri: string) => {
|
|
10
|
+
const startPath = 'file://';
|
|
11
|
+
if (uri.startsWith(startPath)) {
|
|
12
|
+
return uri;
|
|
13
|
+
}
|
|
14
|
+
return `${startPath}${uri}`;
|
|
15
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: 刘利军
|
|
3
|
+
* @Date: 2024-12-25 13:51:40
|
|
4
|
+
* @LastEditors: 刘利军
|
|
5
|
+
* @LastEditTime: 2024-12-25 13:53:40
|
|
6
|
+
* @Description:
|
|
7
|
+
* @PageName:
|
|
8
|
+
*/
|
|
9
|
+
import { PixelRatio, Platform } from 'react-native';
|
|
10
|
+
import { pxToDpWidth } from './px-to-dp';
|
|
11
|
+
import type { CanvasRenderingContext2D } from 'react-native-canvas';
|
|
12
|
+
|
|
13
|
+
export const lastPx = (v: number) =>
|
|
14
|
+
pxToDpWidth(v) / (Platform.OS === 'ios' ? PixelRatio.get() : 1);
|
|
15
|
+
|
|
16
|
+
export const getMeasure = async (
|
|
17
|
+
ctx: CanvasRenderingContext2D,
|
|
18
|
+
content: string
|
|
19
|
+
) => {
|
|
20
|
+
const metrics = await ctx.measureText(content);
|
|
21
|
+
return {
|
|
22
|
+
width: metrics.width,
|
|
23
|
+
height: metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent,
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const getContentMeasure = async (
|
|
28
|
+
ctx: CanvasRenderingContext2D,
|
|
29
|
+
content: string[]
|
|
30
|
+
) => {
|
|
31
|
+
let sizes: number[][] = [];
|
|
32
|
+
|
|
33
|
+
for (let index = 0; index < content.length; index++) {
|
|
34
|
+
const element = content[index];
|
|
35
|
+
const metrics = await getMeasure(ctx, element as string);
|
|
36
|
+
sizes.push([metrics.width, metrics.height]);
|
|
37
|
+
}
|
|
38
|
+
const defaultWidth = Math.ceil(
|
|
39
|
+
Math.max(...sizes.map((size) => size[0] as number))
|
|
40
|
+
);
|
|
41
|
+
const defaultHeight =
|
|
42
|
+
Math.ceil(Math.max(...sizes.map((size) => size[1] as number))) *
|
|
43
|
+
content.length;
|
|
44
|
+
return { width: defaultWidth, height: defaultHeight };
|
|
45
|
+
};
|