我正在开发一个使用 React Native 的项目。在该项目中,我有一个屏幕可以检测是否存在人脸。我试图在检测到面部时设置一个计时器,然后清除它,如果面部失去焦点或离开屏幕,则从 0 重新启动。我尝试查看许多使用
setTimeout()
和 clearTimeout()
的用例示例,但我似乎无法弄清楚为什么这不起作用。当一张脸从屏幕上消失时,它会停止计数,但是当一张脸回到屏幕上时,它会继续从最后一个值开始计数,而不是从 0 开始计数,因此,如果一张脸在 14932 处离开屏幕,那么当该脸回来时在屏幕上,它 (console.log('timer')
) 会显示 {"current": 14952}
而不是 0。我非常感谢任何有关如何使其正常工作的帮助或建议。谢谢!
const getCountTimeout = (set) => {
if (set === true ){
timer.current = setTimeout(() => {
setTimeoutCount(countRef.current);
setTimeExtended(true)
}, 15000)
}
else if (set === false) {
clearTimeout(timer.current);
setCount(0)
timer.current = null;
}
}
相机屏幕
export default function CameraScreen() {
const [hasPermission, setHasPermission] = React.useState(false)
const [isCameraReady, setIsCameraReady] = useState(false);
const [camera, setCamera] = useState(null);
const [state, dispatch] = React.useReducer(detectionReducer, initialState);
const [count, setCount] = useState(0);
const [timeoutCount, setTimeoutCount] = React.useState(0)
const [timeExtended, setTimeExtended] = React.useState(false)
const countRef = React.useRef<number>(count);
const timer = React.useRef(null);
//console.log('count', count)
React.useEffect(() => {
(async () => {
const {status} = await Camera.getCameraPermissionsAsync();
setHasPermission(status === "granted");
})();
}, []);
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
...
const PREVIEW_SIZE = 325
const PREVIEW_RECT = {
minX: (SCREEN_WIDTH - PREVIEW_SIZE) / 2,
minY: 50,
width: PREVIEW_SIZE,
height: PREVIEW_SIZE
}
const getCountTimeout = (set) => {
if (set === true ){
timer.current = setTimeout(() => {
setTimeoutCount(countRef.current);
setTimeExtended(true)
}, 15000)
}
else if (set === false) {
clearTimeout(timer.current);
setCount(0)
timer.current = null;
}
}
const onCameraReady = () => {
if (state.faceDetected === "yes") {
setIsCameraReady(true);
}
};
const onFacesDetected = (result: FaceDetectionResult) => {
const faceRect: Rect = {
minX: face.bounds.origin.x,
minY: face.bounds.origin.y,
width: face.bounds.size.width,
height: face.bounds.size.height
}
const edgeOffset = 50
const faceRectSmaller: Rect = {
width: faceRect.width - edgeOffset,
height: faceRect.height - edgeOffset,
minY: faceRect.minY + edgeOffset / 2,
minX: faceRect.minX + edgeOffset / 2
}
const previewContainsFace = Contains({
outside: PREVIEW_RECT,
inside: faceRectSmaller
})
if (!previewContainsFace) {
getCountTimeout(false)
dispatch({ type: "FACE_DETECTED", payload: "no" })
return
}
...
if (state.faceDetected === "yes") {
getCountTimeout(true)
dispatch({ type: "FACE_DETECTED", payload: "yes" })
}
}
return (
<View>
<SafeAreaView>
<MaskedView
style={styles.absoluteFill}
maskElement={<View style={styles.mask} />}
>
<Camera
style={styles.absoluteFill}
ref={ref => setCamera(ref)}
type={Camera.Constants.Type.front}
onFacesDetected={onFacesDetected}
onCameraReady={onCameraReady}
faceDetectorSettings={{
mode: FaceDetector.FaceDetectorMode.fast,
detectLandmarks: FaceDetector.FaceDetectorLandmarks.none,
runClassifications: FaceDetector.FaceDetectorClassifications.all,
minDetectionInterval: 125,
tracking: false
}}
>
<Svg height="100%" width="100%">
<Circle
cx={SCREEN_WIDTH/2}
cy={PREVIEW_SIZE/2 + PREVIEW_RECT.minY}
r={PREVIEW_SIZE/2}
stroke="hsl(0,0%, 80%)"
strokeWidth={15}
fill="transparent"
strokeLinecap="round"
/>
<Circle
cx={SCREEN_WIDTH/2}
cy={PREVIEW_SIZE/2 + PREVIEW_RECT.minY}
r={PREVIEW_SIZE/2}
stroke="hsl(100,50%,50%)"
strokeWidth={15}
fill="transparent"
strokeDasharray={Circle_Length}
strokeDashoffset={Circle_Length * position}
strokeLinecap="round"
/>
</Svg>
</Camera>
</MaskedView>
</View>
)
};
您的
countRef
是您存储计数的方式,但您还有一个 count
变量。当您停止计时器时,您正在调用 setCount(0)
,但在计时器中您正在增加 countRef.current
的计数。
我会摆脱
const [count, setCount] ...
并简单地使用 currentRef.current
。在您拨打 setCount(0);
的地方,将其更改为 currentRef.current = 0;