@rick427/react-native-liveness 0.1.9 → 0.2.0
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.
|
@@ -1,25 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
-
import { Animated, StyleSheet, Text, View } from 'react-native';
|
|
4
|
+
import { Animated, Easing, StyleSheet, Text, View } from 'react-native';
|
|
5
5
|
import { Camera, useCameraDevice, useCameraFormat, useCameraPermission } from 'react-native-vision-camera';
|
|
6
|
-
import { Circle, Path, Svg } from 'react-native-svg';
|
|
6
|
+
import { Circle, ClipPath, Defs, G, LinearGradient, Path, Rect, Stop, Svg } from 'react-native-svg';
|
|
7
7
|
import { useLivenessCamera } from "./useLivenessCamera.js";
|
|
8
8
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
|
-
|
|
9
|
+
// ─── Animated SVG components ─────────────────────────────────────────────────
|
|
10
|
+
// Created once at module level so React never recreates the component class.
|
|
11
|
+
const AnimatedCircle = Animated.createAnimatedComponent(Circle);
|
|
12
|
+
const AnimatedG = Animated.createAnimatedComponent(G);
|
|
13
|
+
const AnimatedRect = Animated.createAnimatedComponent(Rect);
|
|
10
14
|
|
|
11
|
-
//
|
|
12
|
-
|
|
15
|
+
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
16
|
+
const DEFAULT_FONT = 'Baloo-Medium';
|
|
13
17
|
const CIRCLE_DIAMETER_RATIO = 0.82;
|
|
14
18
|
const STROKE_WIDTH = 3;
|
|
15
|
-
|
|
16
|
-
const
|
|
19
|
+
const K = 0.5523; // cubic bezier ellipse approximation
|
|
20
|
+
const SCAN_LINE_HEIGHT = 44; // px — height of the sweep bar
|
|
21
|
+
const BRACKET_SPAN_DEG = 44; // degrees each corner bracket spans
|
|
22
|
+
const BRACKET_STROKE = STROKE_WIDTH + 1;
|
|
17
23
|
|
|
24
|
+
// ─── Colour helper ────────────────────────────────────────────────────────────
|
|
18
25
|
/**
|
|
19
|
-
* Returns the stroke colour for the circle guide.
|
|
20
|
-
*
|
|
21
26
|
* ● White – no face / scanning (score < 0.4)
|
|
22
|
-
* ● Yellow – face detected, confidence building
|
|
27
|
+
* ● Yellow – face detected, confidence building
|
|
23
28
|
* ● Green – liveness confirmed / countdown / capture
|
|
24
29
|
* ● Red – error
|
|
25
30
|
*/
|
|
@@ -37,44 +42,210 @@ function getCircleColor(state, score) {
|
|
|
37
42
|
}
|
|
38
43
|
}
|
|
39
44
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
* using cubic bezier curves. Used inside a compound path with
|
|
43
|
-
* fillRule="evenodd" to punch a transparent hole through the dark scrim.
|
|
44
|
-
*/
|
|
45
|
+
// ─── SVG path helpers ─────────────────────────────────────────────────────────
|
|
46
|
+
/** Cubic bezier circle path — used inside compound evenodd scrim. */
|
|
45
47
|
function circlePath(cx, cy, r) {
|
|
46
48
|
return [`M ${cx + r} ${cy}`, `C ${cx + r} ${cy - r * K} ${cx + r * K} ${cy - r} ${cx} ${cy - r}`, `C ${cx - r * K} ${cy - r} ${cx - r} ${cy - r * K} ${cx - r} ${cy}`, `C ${cx - r} ${cy + r * K} ${cx - r * K} ${cy + r} ${cx} ${cy + r}`, `C ${cx + r * K} ${cy + r} ${cx + r} ${cy + r * K} ${cx + r} ${cy}`, 'Z'].join(' ');
|
|
47
49
|
}
|
|
50
|
+
|
|
51
|
+
/** One corner bracket arc centred at `centerDeg`, spanning `spanDeg`. */
|
|
52
|
+
function bracketArcPath(cx, cy, r, centerDeg, spanDeg) {
|
|
53
|
+
const toRad = d => d * Math.PI / 180;
|
|
54
|
+
const a1 = toRad(centerDeg - spanDeg / 2);
|
|
55
|
+
const a2 = toRad(centerDeg + spanDeg / 2);
|
|
56
|
+
const x1 = cx + r * Math.cos(a1);
|
|
57
|
+
const y1 = cy + r * Math.sin(a1);
|
|
58
|
+
const x2 = cx + r * Math.cos(a2);
|
|
59
|
+
const y2 = cy + r * Math.sin(a2);
|
|
60
|
+
return `M ${x1} ${y1} A ${r} ${r} 0 0 1 ${x2} ${y2}`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ─── CircleOverlay ────────────────────────────────────────────────────────────
|
|
48
64
|
function CircleOverlay({
|
|
49
65
|
width,
|
|
50
66
|
height,
|
|
51
67
|
state,
|
|
52
|
-
score
|
|
68
|
+
score,
|
|
69
|
+
livenessThreshold
|
|
53
70
|
}) {
|
|
71
|
+
// ── Animation values (must be declared before any early return) ────────────
|
|
72
|
+
const scanAnim = useRef(new Animated.Value(0)).current;
|
|
73
|
+
const scanOpacity = useRef(new Animated.Value(1)).current;
|
|
74
|
+
const progressAnim = useRef(new Animated.Value(0)).current;
|
|
75
|
+
const bracketAnim = useRef(new Animated.Value(0)).current;
|
|
76
|
+
const scanLoopRef = useRef(null);
|
|
77
|
+
const bracketLoopRef = useRef(null);
|
|
78
|
+
|
|
79
|
+
// ── Start scan line + bracket rotation on mount ───────────────────────────
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
// Scan line: ping-pong top → bottom → top, 1.8 s each leg
|
|
82
|
+
scanLoopRef.current = Animated.loop(Animated.sequence([Animated.timing(scanAnim, {
|
|
83
|
+
toValue: 1,
|
|
84
|
+
duration: 1800,
|
|
85
|
+
easing: Easing.linear,
|
|
86
|
+
useNativeDriver: false
|
|
87
|
+
}), Animated.timing(scanAnim, {
|
|
88
|
+
toValue: 0,
|
|
89
|
+
duration: 1800,
|
|
90
|
+
easing: Easing.linear,
|
|
91
|
+
useNativeDriver: false
|
|
92
|
+
})]));
|
|
93
|
+
scanLoopRef.current.start();
|
|
94
|
+
|
|
95
|
+
// Brackets: one full rotation every 6 s — slow, atmospheric
|
|
96
|
+
bracketLoopRef.current = Animated.loop(Animated.timing(bracketAnim, {
|
|
97
|
+
toValue: 360,
|
|
98
|
+
duration: 6000,
|
|
99
|
+
easing: Easing.linear,
|
|
100
|
+
useNativeDriver: false
|
|
101
|
+
}));
|
|
102
|
+
bracketLoopRef.current.start();
|
|
103
|
+
return () => {
|
|
104
|
+
scanLoopRef.current?.stop();
|
|
105
|
+
bracketLoopRef.current?.stop();
|
|
106
|
+
};
|
|
107
|
+
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
108
|
+
|
|
109
|
+
// ── On confirmed: stop scan + brackets, fade out scan line ────────────────
|
|
110
|
+
useEffect(() => {
|
|
111
|
+
const isActive = state === 'scanning';
|
|
112
|
+
if (!isActive) {
|
|
113
|
+
scanLoopRef.current?.stop();
|
|
114
|
+
bracketLoopRef.current?.stop();
|
|
115
|
+
Animated.timing(scanOpacity, {
|
|
116
|
+
toValue: 0,
|
|
117
|
+
duration: 350,
|
|
118
|
+
useNativeDriver: false
|
|
119
|
+
}).start();
|
|
120
|
+
}
|
|
121
|
+
}, [state, scanOpacity]);
|
|
122
|
+
|
|
123
|
+
// ── Drive progress arc from live score ────────────────────────────────────
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
Animated.timing(progressAnim, {
|
|
126
|
+
toValue: Math.min(score, livenessThreshold),
|
|
127
|
+
duration: 180,
|
|
128
|
+
useNativeDriver: false
|
|
129
|
+
}).start();
|
|
130
|
+
}, [score, livenessThreshold, progressAnim]);
|
|
131
|
+
|
|
132
|
+
// ── Guard — render nothing until dimensions are known ─────────────────────
|
|
54
133
|
if (width === 0 || height === 0) return null;
|
|
134
|
+
|
|
135
|
+
// ── Geometry ──────────────────────────────────────────────────────────────
|
|
55
136
|
const cx = width / 2;
|
|
56
137
|
const cy = height * 0.42;
|
|
57
138
|
const r = width * CIRCLE_DIAMETER_RATIO / 2;
|
|
139
|
+
const circumference = 2 * Math.PI * r;
|
|
58
140
|
const color = getCircleColor(state, score);
|
|
141
|
+
|
|
142
|
+
// Scrim: full-screen dark rect with transparent circle hole
|
|
59
143
|
const scrimD = `M0 0H${width}V${height}H0Z ${circlePath(cx, cy, r)}`;
|
|
144
|
+
|
|
145
|
+
// Scan line Y: sweeps from just inside top to just inside bottom of circle
|
|
146
|
+
const scanLineY = scanAnim.interpolate({
|
|
147
|
+
inputRange: [0, 1],
|
|
148
|
+
outputRange: [cy - r + 2, cy + r - SCAN_LINE_HEIGHT - 2]
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// Progress arc: strokeDashoffset goes from full (no arc) → 0 (full arc)
|
|
152
|
+
const strokeDashoffset = progressAnim.interpolate({
|
|
153
|
+
inputRange: [0, livenessThreshold],
|
|
154
|
+
outputRange: [circumference, 0],
|
|
155
|
+
extrapolate: 'clamp'
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// Bracket group rotation — centred on the circle
|
|
159
|
+
const bracketTransform = bracketAnim.interpolate({
|
|
160
|
+
inputRange: [0, 360],
|
|
161
|
+
outputRange: [`rotate(0, ${cx}, ${cy})`, `rotate(360, ${cx}, ${cy})`]
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// 4 corner brackets at NE / SE / SW / NW diagonal positions
|
|
165
|
+
const bracketD = [45, 135, 225, 315].map(deg => bracketArcPath(cx, cy, r, deg, BRACKET_SPAN_DEG)).join(' ');
|
|
60
166
|
return /*#__PURE__*/_jsxs(Svg, {
|
|
61
167
|
style: StyleSheet.absoluteFill,
|
|
62
168
|
width: width,
|
|
63
169
|
height: height,
|
|
64
|
-
children: [/*#__PURE__*/
|
|
170
|
+
children: [/*#__PURE__*/_jsxs(Defs, {
|
|
171
|
+
children: [/*#__PURE__*/_jsx(ClipPath, {
|
|
172
|
+
id: "liveness-circle-clip",
|
|
173
|
+
children: /*#__PURE__*/_jsx(Circle, {
|
|
174
|
+
cx: cx,
|
|
175
|
+
cy: cy,
|
|
176
|
+
r: r
|
|
177
|
+
})
|
|
178
|
+
}), /*#__PURE__*/_jsxs(LinearGradient, {
|
|
179
|
+
id: "scan-gradient",
|
|
180
|
+
x1: "0",
|
|
181
|
+
y1: "0",
|
|
182
|
+
x2: "0",
|
|
183
|
+
y2: "1",
|
|
184
|
+
children: [/*#__PURE__*/_jsx(Stop, {
|
|
185
|
+
offset: "0",
|
|
186
|
+
stopColor: "#fff",
|
|
187
|
+
stopOpacity: "0"
|
|
188
|
+
}), /*#__PURE__*/_jsx(Stop, {
|
|
189
|
+
offset: "0.25",
|
|
190
|
+
stopColor: "#fff",
|
|
191
|
+
stopOpacity: "0.65"
|
|
192
|
+
}), /*#__PURE__*/_jsx(Stop, {
|
|
193
|
+
offset: "0.75",
|
|
194
|
+
stopColor: "#fff",
|
|
195
|
+
stopOpacity: "0.65"
|
|
196
|
+
}), /*#__PURE__*/_jsx(Stop, {
|
|
197
|
+
offset: "1",
|
|
198
|
+
stopColor: "#fff",
|
|
199
|
+
stopOpacity: "0"
|
|
200
|
+
})]
|
|
201
|
+
})]
|
|
202
|
+
}), /*#__PURE__*/_jsx(Path, {
|
|
65
203
|
d: scrimD,
|
|
66
204
|
fill: "rgba(0,0,0,0.55)",
|
|
67
205
|
fillRule: "evenodd"
|
|
68
206
|
}), /*#__PURE__*/_jsx(Circle, {
|
|
207
|
+
cx: cx,
|
|
208
|
+
cy: cy,
|
|
209
|
+
r: r,
|
|
210
|
+
fill: "none",
|
|
211
|
+
stroke: "rgba(255,255,255,0.18)",
|
|
212
|
+
strokeWidth: 1
|
|
213
|
+
}), /*#__PURE__*/_jsx(G, {
|
|
214
|
+
clipPath: "url(#liveness-circle-clip)",
|
|
215
|
+
children: /*#__PURE__*/_jsx(AnimatedRect, {
|
|
216
|
+
x: cx - r,
|
|
217
|
+
y: scanLineY,
|
|
218
|
+
width: r * 2,
|
|
219
|
+
height: SCAN_LINE_HEIGHT,
|
|
220
|
+
fill: "url(#scan-gradient)",
|
|
221
|
+
opacity: scanOpacity
|
|
222
|
+
})
|
|
223
|
+
}), /*#__PURE__*/_jsx(AnimatedG, {
|
|
224
|
+
transform: bracketTransform,
|
|
225
|
+
children: /*#__PURE__*/_jsx(Path, {
|
|
226
|
+
d: bracketD,
|
|
227
|
+
fill: "none",
|
|
228
|
+
stroke: color,
|
|
229
|
+
strokeWidth: BRACKET_STROKE,
|
|
230
|
+
strokeLinecap: "round",
|
|
231
|
+
opacity: 0.85
|
|
232
|
+
})
|
|
233
|
+
}), /*#__PURE__*/_jsx(AnimatedCircle, {
|
|
69
234
|
cx: cx,
|
|
70
235
|
cy: cy,
|
|
71
236
|
r: r,
|
|
72
237
|
fill: "none",
|
|
73
238
|
stroke: color,
|
|
74
|
-
strokeWidth: STROKE_WIDTH
|
|
239
|
+
strokeWidth: STROKE_WIDTH,
|
|
240
|
+
strokeDasharray: circumference,
|
|
241
|
+
strokeDashoffset: strokeDashoffset,
|
|
242
|
+
strokeLinecap: "round",
|
|
243
|
+
transform: `rotate(-90, ${cx}, ${cy})`
|
|
75
244
|
})]
|
|
76
245
|
});
|
|
77
246
|
}
|
|
247
|
+
|
|
248
|
+
// ─── CountdownBubble ──────────────────────────────────────────────────────────
|
|
78
249
|
function CountdownBubble({
|
|
79
250
|
value,
|
|
80
251
|
fontFamily
|
|
@@ -121,6 +292,8 @@ function CountdownBubble({
|
|
|
121
292
|
})
|
|
122
293
|
});
|
|
123
294
|
}
|
|
295
|
+
|
|
296
|
+
// ─── LivenessCamera ───────────────────────────────────────────────────────────
|
|
124
297
|
export function LivenessCamera({
|
|
125
298
|
onCapture,
|
|
126
299
|
onLivenessConfirmed,
|
|
@@ -218,7 +391,8 @@ export function LivenessCamera({
|
|
|
218
391
|
width: containerSize.width,
|
|
219
392
|
height: containerSize.height,
|
|
220
393
|
state: livenessState,
|
|
221
|
-
score: livenessScore
|
|
394
|
+
score: livenessScore,
|
|
395
|
+
livenessThreshold: livenessThreshold
|
|
222
396
|
}), livenessState !== 'done' && /*#__PURE__*/_jsx(View, {
|
|
223
397
|
style: styles.feedbackContainer,
|
|
224
398
|
children: /*#__PURE__*/_jsx(Text, {
|
|
@@ -239,6 +413,8 @@ export function LivenessCamera({
|
|
|
239
413
|
})]
|
|
240
414
|
});
|
|
241
415
|
}
|
|
416
|
+
|
|
417
|
+
// ─── Styles ───────────────────────────────────────────────────────────────────
|
|
242
418
|
const styles = StyleSheet.create({
|
|
243
419
|
root: {
|
|
244
420
|
flex: 1,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useCallback","useEffect","useRef","useState","Animated","StyleSheet","Text","View","Camera","useCameraDevice","useCameraFormat","useCameraPermission","Circle","Path","Svg","useLivenessCamera","jsx","_jsx","jsxs","_jsxs","DEFAULT_FONT","CIRCLE_DIAMETER_RATIO","STROKE_WIDTH","K","getCircleColor","state","score","circlePath","cx","cy","r","join","CircleOverlay","width","height","color","scrimD","style","absoluteFill","children","d","fill","fillRule","stroke","strokeWidth","CountdownBubble","value","fontFamily","scale","Value","current","opacity","parallel","sequence","spring","toValue","stiffness","damping","useNativeDriver","timing","duration","start","styles","countdownBubble","transform","countdownText","LivenessCamera","onCapture","onLivenessConfirmed","onError","countdownFrom","livenessThreshold","confirmFrames","soundEnabled","hasPermission","requestPermission","device","format","fps","Math","min","maxFps","cameraRef","containerSize","setContainerSize","frameProcessor","livenessState","livenessScore","countdown","feedback","handleLayout","e","nativeEvent","layout","catch","Error","root","centered","permissionText","onLayout","ref","isActive","photo","pixelFormat","feedbackContainer","feedbackText","countdownContainer","captureFlash","pointerEvents","create","flex","backgroundColor","overflow","justifyContent","alignItems","fontSize","textAlign","paddingHorizontal","position","bottom","left","right","textShadowColor","textShadowOffset","textShadowRadius","absoluteFillObject","borderRadius","borderWidth","borderColor","lineHeight"],"sourceRoot":"../../src","sources":["LivenessCamera.tsx"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["useCallback","useEffect","useRef","useState","Animated","Easing","StyleSheet","Text","View","Camera","useCameraDevice","useCameraFormat","useCameraPermission","Circle","ClipPath","Defs","G","LinearGradient","Path","Rect","Stop","Svg","useLivenessCamera","jsx","_jsx","jsxs","_jsxs","AnimatedCircle","createAnimatedComponent","AnimatedG","AnimatedRect","DEFAULT_FONT","CIRCLE_DIAMETER_RATIO","STROKE_WIDTH","K","SCAN_LINE_HEIGHT","BRACKET_SPAN_DEG","BRACKET_STROKE","getCircleColor","state","score","circlePath","cx","cy","r","join","bracketArcPath","centerDeg","spanDeg","toRad","d","Math","PI","a1","a2","x1","cos","y1","sin","x2","y2","CircleOverlay","width","height","livenessThreshold","scanAnim","Value","current","scanOpacity","progressAnim","bracketAnim","scanLoopRef","bracketLoopRef","loop","sequence","timing","toValue","duration","easing","linear","useNativeDriver","start","stop","isActive","min","circumference","color","scrimD","scanLineY","interpolate","inputRange","outputRange","strokeDashoffset","extrapolate","bracketTransform","bracketD","map","deg","style","absoluteFill","children","id","offset","stopColor","stopOpacity","fill","fillRule","stroke","strokeWidth","clipPath","x","y","opacity","transform","strokeLinecap","strokeDasharray","CountdownBubble","value","fontFamily","scale","parallel","spring","stiffness","damping","styles","countdownBubble","countdownText","LivenessCamera","onCapture","onLivenessConfirmed","onError","countdownFrom","confirmFrames","soundEnabled","hasPermission","requestPermission","device","format","fps","maxFps","cameraRef","containerSize","setContainerSize","frameProcessor","livenessState","livenessScore","countdown","feedback","handleLayout","e","nativeEvent","layout","catch","Error","root","centered","permissionText","onLayout","ref","photo","pixelFormat","feedbackContainer","feedbackText","countdownContainer","captureFlash","pointerEvents","create","flex","backgroundColor","overflow","justifyContent","alignItems","fontSize","textAlign","paddingHorizontal","position","bottom","left","right","textShadowColor","textShadowOffset","textShadowRadius","absoluteFillObject","borderRadius","borderWidth","borderColor","lineHeight"],"sourceRoot":"../../src","sources":["LivenessCamera.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LivenessCamera.d.ts","sourceRoot":"","sources":["../../../src/LivenessCamera.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LivenessCamera.d.ts","sourceRoot":"","sources":["../../../src/LivenessCamera.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,mBAAmB,EAAiB,MAAM,SAAS,CAAC;AA4TlE,wBAAgB,cAAc,CAAC,EAC7B,SAAS,EACT,mBAAmB,EACnB,OAAO,EACP,aAAiB,EACjB,iBAAwB,EACxB,aAAkB,EAClB,YAAmB,EACnB,UAAyB,EACzB,KAAK,GACN,EAAE,mBAAmB,2CA+FrB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rick427/react-native-liveness",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Liveness detection library for React Native using Vision Camera v4 and ML Kit",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
package/src/LivenessCamera.tsx
CHANGED
|
@@ -1,29 +1,44 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
-
import { Animated, StyleSheet, Text, View } from 'react-native';
|
|
2
|
+
import { Animated, Easing, StyleSheet, Text, View } from 'react-native';
|
|
3
3
|
import {
|
|
4
4
|
Camera,
|
|
5
5
|
useCameraDevice,
|
|
6
6
|
useCameraFormat,
|
|
7
7
|
useCameraPermission,
|
|
8
8
|
} from 'react-native-vision-camera';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
Circle,
|
|
11
|
+
ClipPath,
|
|
12
|
+
Defs,
|
|
13
|
+
G,
|
|
14
|
+
LinearGradient,
|
|
15
|
+
Path,
|
|
16
|
+
Rect,
|
|
17
|
+
Stop,
|
|
18
|
+
Svg,
|
|
19
|
+
} from 'react-native-svg';
|
|
10
20
|
import { useLivenessCamera } from './useLivenessCamera';
|
|
11
21
|
import type { LivenessCameraProps, LivenessState } from './types';
|
|
12
22
|
|
|
13
|
-
|
|
23
|
+
// ─── Animated SVG components ─────────────────────────────────────────────────
|
|
24
|
+
// Created once at module level so React never recreates the component class.
|
|
25
|
+
const AnimatedCircle = Animated.createAnimatedComponent(Circle);
|
|
26
|
+
const AnimatedG = Animated.createAnimatedComponent(G);
|
|
27
|
+
const AnimatedRect = Animated.createAnimatedComponent(Rect);
|
|
14
28
|
|
|
15
|
-
//
|
|
16
|
-
|
|
29
|
+
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
30
|
+
const DEFAULT_FONT = 'Baloo-Medium';
|
|
17
31
|
const CIRCLE_DIAMETER_RATIO = 0.82;
|
|
18
32
|
const STROKE_WIDTH = 3;
|
|
19
|
-
|
|
20
|
-
const
|
|
33
|
+
const K = 0.5523; // cubic bezier ellipse approximation
|
|
34
|
+
const SCAN_LINE_HEIGHT = 44; // px — height of the sweep bar
|
|
35
|
+
const BRACKET_SPAN_DEG = 44; // degrees each corner bracket spans
|
|
36
|
+
const BRACKET_STROKE = STROKE_WIDTH + 1;
|
|
21
37
|
|
|
38
|
+
// ─── Colour helper ────────────────────────────────────────────────────────────
|
|
22
39
|
/**
|
|
23
|
-
* Returns the stroke colour for the circle guide.
|
|
24
|
-
*
|
|
25
40
|
* ● White – no face / scanning (score < 0.4)
|
|
26
|
-
* ● Yellow – face detected, confidence building
|
|
41
|
+
* ● Yellow – face detected, confidence building
|
|
27
42
|
* ● Green – liveness confirmed / countdown / capture
|
|
28
43
|
* ● Red – error
|
|
29
44
|
*/
|
|
@@ -41,11 +56,8 @@ function getCircleColor(state: LivenessState, score: number): string {
|
|
|
41
56
|
}
|
|
42
57
|
}
|
|
43
58
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
* using cubic bezier curves. Used inside a compound path with
|
|
47
|
-
* fillRule="evenodd" to punch a transparent hole through the dark scrim.
|
|
48
|
-
*/
|
|
59
|
+
// ─── SVG path helpers ─────────────────────────────────────────────────────────
|
|
60
|
+
/** Cubic bezier circle path — used inside compound evenodd scrim. */
|
|
49
61
|
function circlePath(cx: number, cy: number, r: number): string {
|
|
50
62
|
return [
|
|
51
63
|
`M ${cx + r} ${cy}`,
|
|
@@ -57,41 +69,219 @@ function circlePath(cx: number, cy: number, r: number): string {
|
|
|
57
69
|
].join(' ');
|
|
58
70
|
}
|
|
59
71
|
|
|
72
|
+
/** One corner bracket arc centred at `centerDeg`, spanning `spanDeg`. */
|
|
73
|
+
function bracketArcPath(
|
|
74
|
+
cx: number,
|
|
75
|
+
cy: number,
|
|
76
|
+
r: number,
|
|
77
|
+
centerDeg: number,
|
|
78
|
+
spanDeg: number
|
|
79
|
+
): string {
|
|
80
|
+
const toRad = (d: number) => (d * Math.PI) / 180;
|
|
81
|
+
const a1 = toRad(centerDeg - spanDeg / 2);
|
|
82
|
+
const a2 = toRad(centerDeg + spanDeg / 2);
|
|
83
|
+
const x1 = cx + r * Math.cos(a1);
|
|
84
|
+
const y1 = cy + r * Math.sin(a1);
|
|
85
|
+
const x2 = cx + r * Math.cos(a2);
|
|
86
|
+
const y2 = cy + r * Math.sin(a2);
|
|
87
|
+
return `M ${x1} ${y1} A ${r} ${r} 0 0 1 ${x2} ${y2}`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ─── CircleOverlay ────────────────────────────────────────────────────────────
|
|
60
91
|
function CircleOverlay({
|
|
61
92
|
width,
|
|
62
93
|
height,
|
|
63
94
|
state,
|
|
64
95
|
score,
|
|
96
|
+
livenessThreshold,
|
|
65
97
|
}: {
|
|
66
98
|
width: number;
|
|
67
99
|
height: number;
|
|
68
100
|
state: LivenessState;
|
|
69
101
|
score: number;
|
|
102
|
+
livenessThreshold: number;
|
|
70
103
|
}) {
|
|
104
|
+
// ── Animation values (must be declared before any early return) ────────────
|
|
105
|
+
const scanAnim = useRef(new Animated.Value(0)).current;
|
|
106
|
+
const scanOpacity = useRef(new Animated.Value(1)).current;
|
|
107
|
+
const progressAnim = useRef(new Animated.Value(0)).current;
|
|
108
|
+
const bracketAnim = useRef(new Animated.Value(0)).current;
|
|
109
|
+
|
|
110
|
+
const scanLoopRef = useRef<Animated.CompositeAnimation | null>(null);
|
|
111
|
+
const bracketLoopRef = useRef<Animated.CompositeAnimation | null>(null);
|
|
112
|
+
|
|
113
|
+
// ── Start scan line + bracket rotation on mount ───────────────────────────
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
// Scan line: ping-pong top → bottom → top, 1.8 s each leg
|
|
116
|
+
scanLoopRef.current = Animated.loop(
|
|
117
|
+
Animated.sequence([
|
|
118
|
+
Animated.timing(scanAnim, {
|
|
119
|
+
toValue: 1,
|
|
120
|
+
duration: 1800,
|
|
121
|
+
easing: Easing.linear,
|
|
122
|
+
useNativeDriver: false,
|
|
123
|
+
}),
|
|
124
|
+
Animated.timing(scanAnim, {
|
|
125
|
+
toValue: 0,
|
|
126
|
+
duration: 1800,
|
|
127
|
+
easing: Easing.linear,
|
|
128
|
+
useNativeDriver: false,
|
|
129
|
+
}),
|
|
130
|
+
])
|
|
131
|
+
);
|
|
132
|
+
scanLoopRef.current.start();
|
|
133
|
+
|
|
134
|
+
// Brackets: one full rotation every 6 s — slow, atmospheric
|
|
135
|
+
bracketLoopRef.current = Animated.loop(
|
|
136
|
+
Animated.timing(bracketAnim, {
|
|
137
|
+
toValue: 360,
|
|
138
|
+
duration: 6000,
|
|
139
|
+
easing: Easing.linear,
|
|
140
|
+
useNativeDriver: false,
|
|
141
|
+
})
|
|
142
|
+
);
|
|
143
|
+
bracketLoopRef.current.start();
|
|
144
|
+
|
|
145
|
+
return () => {
|
|
146
|
+
scanLoopRef.current?.stop();
|
|
147
|
+
bracketLoopRef.current?.stop();
|
|
148
|
+
};
|
|
149
|
+
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
150
|
+
|
|
151
|
+
// ── On confirmed: stop scan + brackets, fade out scan line ────────────────
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
const isActive = state === 'scanning';
|
|
154
|
+
if (!isActive) {
|
|
155
|
+
scanLoopRef.current?.stop();
|
|
156
|
+
bracketLoopRef.current?.stop();
|
|
157
|
+
Animated.timing(scanOpacity, {
|
|
158
|
+
toValue: 0,
|
|
159
|
+
duration: 350,
|
|
160
|
+
useNativeDriver: false,
|
|
161
|
+
}).start();
|
|
162
|
+
}
|
|
163
|
+
}, [state, scanOpacity]);
|
|
164
|
+
|
|
165
|
+
// ── Drive progress arc from live score ────────────────────────────────────
|
|
166
|
+
useEffect(() => {
|
|
167
|
+
Animated.timing(progressAnim, {
|
|
168
|
+
toValue: Math.min(score, livenessThreshold),
|
|
169
|
+
duration: 180,
|
|
170
|
+
useNativeDriver: false,
|
|
171
|
+
}).start();
|
|
172
|
+
}, [score, livenessThreshold, progressAnim]);
|
|
173
|
+
|
|
174
|
+
// ── Guard — render nothing until dimensions are known ─────────────────────
|
|
71
175
|
if (width === 0 || height === 0) return null;
|
|
72
176
|
|
|
177
|
+
// ── Geometry ──────────────────────────────────────────────────────────────
|
|
73
178
|
const cx = width / 2;
|
|
74
179
|
const cy = height * 0.42;
|
|
75
180
|
const r = (width * CIRCLE_DIAMETER_RATIO) / 2;
|
|
181
|
+
const circumference = 2 * Math.PI * r;
|
|
76
182
|
const color = getCircleColor(state, score);
|
|
77
183
|
|
|
184
|
+
// Scrim: full-screen dark rect with transparent circle hole
|
|
78
185
|
const scrimD = `M0 0H${width}V${height}H0Z ${circlePath(cx, cy, r)}`;
|
|
79
186
|
|
|
187
|
+
// Scan line Y: sweeps from just inside top to just inside bottom of circle
|
|
188
|
+
const scanLineY = scanAnim.interpolate({
|
|
189
|
+
inputRange: [0, 1],
|
|
190
|
+
outputRange: [cy - r + 2, cy + r - SCAN_LINE_HEIGHT - 2],
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Progress arc: strokeDashoffset goes from full (no arc) → 0 (full arc)
|
|
194
|
+
const strokeDashoffset = progressAnim.interpolate({
|
|
195
|
+
inputRange: [0, livenessThreshold],
|
|
196
|
+
outputRange: [circumference, 0],
|
|
197
|
+
extrapolate: 'clamp',
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// Bracket group rotation — centred on the circle
|
|
201
|
+
const bracketTransform = bracketAnim.interpolate({
|
|
202
|
+
inputRange: [0, 360],
|
|
203
|
+
outputRange: [`rotate(0, ${cx}, ${cy})`, `rotate(360, ${cx}, ${cy})`],
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// 4 corner brackets at NE / SE / SW / NW diagonal positions
|
|
207
|
+
const bracketD = [45, 135, 225, 315]
|
|
208
|
+
.map((deg) => bracketArcPath(cx, cy, r, deg, BRACKET_SPAN_DEG))
|
|
209
|
+
.join(' ');
|
|
210
|
+
|
|
80
211
|
return (
|
|
81
212
|
<Svg style={StyleSheet.absoluteFill} width={width} height={height}>
|
|
213
|
+
{/* ── Definitions ─────────────────────────────────────────────────── */}
|
|
214
|
+
<Defs>
|
|
215
|
+
{/* Clip path: restrict scan line to circle area */}
|
|
216
|
+
<ClipPath id="liveness-circle-clip">
|
|
217
|
+
<Circle cx={cx} cy={cy} r={r} />
|
|
218
|
+
</ClipPath>
|
|
219
|
+
|
|
220
|
+
{/* Vertical gradient for the scan bar — fades at top and bottom */}
|
|
221
|
+
<LinearGradient id="scan-gradient" x1="0" y1="0" x2="0" y2="1">
|
|
222
|
+
<Stop offset="0" stopColor="#fff" stopOpacity="0" />
|
|
223
|
+
<Stop offset="0.25" stopColor="#fff" stopOpacity="0.65" />
|
|
224
|
+
<Stop offset="0.75" stopColor="#fff" stopOpacity="0.65" />
|
|
225
|
+
<Stop offset="1" stopColor="#fff" stopOpacity="0" />
|
|
226
|
+
</LinearGradient>
|
|
227
|
+
</Defs>
|
|
228
|
+
|
|
229
|
+
{/* ── Dark scrim with transparent circle cutout ────────────────────── */}
|
|
82
230
|
<Path d={scrimD} fill="rgba(0,0,0,0.55)" fillRule="evenodd" />
|
|
231
|
+
|
|
232
|
+
{/* ── Dim base ring — always shows the circle boundary ─────────────── */}
|
|
83
233
|
<Circle
|
|
234
|
+
cx={cx}
|
|
235
|
+
cy={cy}
|
|
236
|
+
r={r}
|
|
237
|
+
fill="none"
|
|
238
|
+
stroke="rgba(255,255,255,0.18)"
|
|
239
|
+
strokeWidth={1}
|
|
240
|
+
/>
|
|
241
|
+
|
|
242
|
+
{/* ── Scan line — sweeps top → bottom, clipped to circle ───────────── */}
|
|
243
|
+
<G clipPath="url(#liveness-circle-clip)">
|
|
244
|
+
<AnimatedRect
|
|
245
|
+
x={cx - r}
|
|
246
|
+
y={scanLineY}
|
|
247
|
+
width={r * 2}
|
|
248
|
+
height={SCAN_LINE_HEIGHT}
|
|
249
|
+
fill="url(#scan-gradient)"
|
|
250
|
+
opacity={scanOpacity}
|
|
251
|
+
/>
|
|
252
|
+
</G>
|
|
253
|
+
|
|
254
|
+
{/* ── Rotating corner brackets ─────────────────────────────────────── */}
|
|
255
|
+
<AnimatedG transform={bracketTransform}>
|
|
256
|
+
<Path
|
|
257
|
+
d={bracketD}
|
|
258
|
+
fill="none"
|
|
259
|
+
stroke={color}
|
|
260
|
+
strokeWidth={BRACKET_STROKE}
|
|
261
|
+
strokeLinecap="round"
|
|
262
|
+
opacity={0.85}
|
|
263
|
+
/>
|
|
264
|
+
</AnimatedG>
|
|
265
|
+
|
|
266
|
+
{/* ── Progress arc — draws in as liveness confidence builds ────────── */}
|
|
267
|
+
{/* Rotated -90° so it starts at 12 o'clock and goes clockwise */}
|
|
268
|
+
<AnimatedCircle
|
|
84
269
|
cx={cx}
|
|
85
270
|
cy={cy}
|
|
86
271
|
r={r}
|
|
87
272
|
fill="none"
|
|
88
273
|
stroke={color}
|
|
89
274
|
strokeWidth={STROKE_WIDTH}
|
|
275
|
+
strokeDasharray={circumference}
|
|
276
|
+
strokeDashoffset={strokeDashoffset}
|
|
277
|
+
strokeLinecap="round"
|
|
278
|
+
transform={`rotate(-90, ${cx}, ${cy})`}
|
|
90
279
|
/>
|
|
91
280
|
</Svg>
|
|
92
281
|
);
|
|
93
282
|
}
|
|
94
283
|
|
|
284
|
+
// ─── CountdownBubble ──────────────────────────────────────────────────────────
|
|
95
285
|
function CountdownBubble({
|
|
96
286
|
value,
|
|
97
287
|
fontFamily,
|
|
@@ -143,6 +333,7 @@ function CountdownBubble({
|
|
|
143
333
|
);
|
|
144
334
|
}
|
|
145
335
|
|
|
336
|
+
// ─── LivenessCamera ───────────────────────────────────────────────────────────
|
|
146
337
|
export function LivenessCamera({
|
|
147
338
|
onCapture,
|
|
148
339
|
onLivenessConfirmed,
|
|
@@ -227,6 +418,7 @@ export function LivenessCamera({
|
|
|
227
418
|
height={containerSize.height}
|
|
228
419
|
state={livenessState}
|
|
229
420
|
score={livenessScore}
|
|
421
|
+
livenessThreshold={livenessThreshold}
|
|
230
422
|
/>
|
|
231
423
|
{livenessState !== 'done' && (
|
|
232
424
|
<View style={styles.feedbackContainer}>
|
|
@@ -249,6 +441,7 @@ export function LivenessCamera({
|
|
|
249
441
|
);
|
|
250
442
|
}
|
|
251
443
|
|
|
444
|
+
// ─── Styles ───────────────────────────────────────────────────────────────────
|
|
252
445
|
const styles = StyleSheet.create({
|
|
253
446
|
root: {
|
|
254
447
|
flex: 1,
|