janky animation engine for approve/deny

This commit is contained in:
thetek 2024-05-23 01:07:44 +02:00
parent f52e3e9723
commit 18e41566b4
3 changed files with 98 additions and 5 deletions

View File

@ -9,7 +9,7 @@
<link href="https://fonts.googleapis.com/css2?family=Roboto+Condensed:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Roboto+Condensed:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<title>React Redux App</title> <title>React Redux App</title>
</head> </head>
<body> <body oncontextmenu="return false;">
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div> <div id="root"></div>
<script type="module" src="/src/main.tsx"></script> <script type="module" src="/src/main.tsx"></script>

View File

@ -1,4 +1,6 @@
import { useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { useAppSelector } from 'src/redux/hooks';
import { getGazesAndKeys } from 'src/redux/slices/gazeSlice';
import type { ApproveDenyButtonElement as ApproveDenyButtonElementType } from 'src/types/element'; import type { ApproveDenyButtonElement as ApproveDenyButtonElementType } from 'src/types/element';
type ApproveDenyButtonElementProps = { type ApproveDenyButtonElementProps = {
@ -24,8 +26,10 @@ type KeyframeParameters = {
tinyDotOpacity: number, tinyDotOpacity: number,
approveButtonPosition: number, approveButtonPosition: number,
approveButtonOpacity: number, approveButtonOpacity: number,
approveArrowOpacity: number,
denyButtonPosition: number, denyButtonPosition: number,
denyButtonOpacity: number, denyButtonOpacity: number,
denyArrowOpacity: number,
}; };
const INITIAL_KEYFRAME: KeyframeParameters = { const INITIAL_KEYFRAME: KeyframeParameters = {
@ -37,8 +41,10 @@ const INITIAL_KEYFRAME: KeyframeParameters = {
tinyDotOpacity: 0.8, tinyDotOpacity: 0.8,
approveButtonPosition: 1, approveButtonPosition: 1,
approveButtonOpacity: 1, approveButtonOpacity: 1,
approveArrowOpacity: 1,
denyButtonPosition: 0, denyButtonPosition: 0,
denyButtonOpacity: 1, denyButtonOpacity: 1,
denyArrowOpacity: 1,
} as const; } as const;
const KEYFRAMES_APPROVE = [ const KEYFRAMES_APPROVE = [
@ -52,13 +58,15 @@ const KEYFRAMES_APPROVE = [
bigCircleRadius: SIZES.bigCircle, bigCircleRadius: SIZES.bigCircle,
bigCircleGradientStart: 0x646464, bigCircleGradientStart: 0x646464,
bigCircleGradientEnd: 0x00C007, bigCircleGradientEnd: 0x00C007,
smallTurqoiseCirclePosition: 0.5, smallTurqoiseCirclePosition: 0.7,
smallTurqoiseCircleOpacity: 1, smallTurqoiseCircleOpacity: 1,
tinyDotOpacity: 0.8, tinyDotOpacity: 0.8,
approveButtonPosition: 1, approveButtonPosition: 1,
approveButtonOpacity: 1, approveButtonOpacity: 1,
approveArrowOpacity: 1,
denyButtonPosition: 0, denyButtonPosition: 0,
denyButtonOpacity: 1, denyButtonOpacity: 1,
denyArrowOpacity: 0.2,
}, },
}, },
{ {
@ -72,8 +80,10 @@ const KEYFRAMES_APPROVE = [
tinyDotOpacity: 0, tinyDotOpacity: 0,
approveButtonPosition: 0.5, approveButtonPosition: 0.5,
approveButtonOpacity: 1, approveButtonOpacity: 1,
approveArrowOpacity: 0,
denyButtonPosition: 0, denyButtonPosition: 0,
denyButtonOpacity: 0, denyButtonOpacity: 0,
denyArrowOpacity: 0,
}, },
}, },
{ {
@ -87,8 +97,10 @@ const KEYFRAMES_APPROVE = [
tinyDotOpacity: 0, tinyDotOpacity: 0,
approveButtonPosition: 0.5, approveButtonPosition: 0.5,
approveButtonOpacity: 1, approveButtonOpacity: 1,
approveArrowOpacity: 0,
denyButtonPosition: 0, denyButtonPosition: 0,
denyButtonOpacity: 0, denyButtonOpacity: 0,
denyArrowOpacity: 0,
}, },
}, },
]; ];
@ -104,13 +116,15 @@ const KEYFRAMES_DENY = [
bigCircleRadius: SIZES.bigCircle, bigCircleRadius: SIZES.bigCircle,
bigCircleGradientStart: 0x646464, bigCircleGradientStart: 0x646464,
bigCircleGradientEnd: 0xBC2503, bigCircleGradientEnd: 0xBC2503,
smallTurqoiseCirclePosition: 0.5, smallTurqoiseCirclePosition: 0.3,
smallTurqoiseCircleOpacity: 1, smallTurqoiseCircleOpacity: 1,
tinyDotOpacity: 0.8, tinyDotOpacity: 0.8,
approveButtonPosition: 1, approveButtonPosition: 1,
approveButtonOpacity: 1, approveButtonOpacity: 1,
approveArrowOpacity: 0.2,
denyButtonPosition: 0, denyButtonPosition: 0,
denyButtonOpacity: 1, denyButtonOpacity: 1,
denyArrowOpacity: 1,
}, },
}, },
{ {
@ -124,8 +138,10 @@ const KEYFRAMES_DENY = [
tinyDotOpacity: 0, tinyDotOpacity: 0,
approveButtonPosition: 1, approveButtonPosition: 1,
approveButtonOpacity: 0, approveButtonOpacity: 0,
approveArrowOpacity: 0,
denyButtonPosition: 0.5, denyButtonPosition: 0.5,
denyButtonOpacity: 1, denyButtonOpacity: 1,
denyArrowOpacity: 0,
}, },
}, },
{ {
@ -139,8 +155,10 @@ const KEYFRAMES_DENY = [
tinyDotOpacity: 0, tinyDotOpacity: 0,
approveButtonPosition: 1, approveButtonPosition: 1,
approveButtonOpacity: 0, approveButtonOpacity: 0,
approveArrowOpacity: 0,
denyButtonPosition: 0.5, denyButtonPosition: 0.5,
denyButtonOpacity: 1, denyButtonOpacity: 1,
denyArrowOpacity: 0,
}, },
}, },
]; ];
@ -157,6 +175,8 @@ const KEYFRAMES_DENY = [
// - 2: pos turqoise circle left of entire button, "deny" in middle of button, button red // - 2: pos turqoise circle left of entire button, "deny" in middle of button, button red
// - 3: no turqoise circle, "deny" in middle of button, button red // - 3: no turqoise circle, "deny" in middle of button, button red
const FRAMETIME = 1.0 / 60.0;
const ApproveDenyButtonElement = ({ const ApproveDenyButtonElement = ({
element, element,
}: ApproveDenyButtonElementProps) => { }: ApproveDenyButtonElementProps) => {
@ -166,6 +186,78 @@ const ApproveDenyButtonElement = ({
const buttonStyle = { fontSize: w * SIZES.fontSize, height: w * SIZES.button - 2, lineHeight: `${w * SIZES.button - 2}px`, width: w * SIZES.sideLabel }; const buttonStyle = { fontSize: w * SIZES.fontSize, height: w * SIZES.button - 2, lineHeight: `${w * SIZES.button - 2}px`, width: w * SIZES.sideLabel };
const [state, setState] = useState(INITIAL_KEYFRAME); const [state, setState] = useState(INITIAL_KEYFRAME);
const [animation, setAnimation] = useState<"approve" | "deny" | undefined>(undefined);
const [time, setTime] = useState(0);
const intervalRef = useRef<any>(undefined); // this is really just `number | undefined` but typescript is stoopid
useEffect(() => {
let intervalHandle: any;
const animationTick = () => {
setState({...state, bigCircleRadius: state.bigCircleRadius + 0.01});
setTime(prevTime => {
const newTime = prevTime + FRAMETIME;
if (newTime >= 1000) {
stopAnimation();
}
return newTime;
});
};
if (animation) {
intervalRef.current = setInterval(animationTick, FRAMETIME);
} else {
if (intervalRef.current !== undefined) {
clearInterval(intervalRef.current);
intervalRef.current = undefined;
}
}
return () => {
if (intervalRef.current !== undefined) {
clearInterval(intervalRef.current);
intervalRef.current = undefined;
}
};
});
//const [intervalHandle, setIntervalHandle] = useState<number | undefined>(undefined);
//const [time, setTime] = useState(0);
//const animationTick = (action: "approve" | "deny") => {
// setTime(time + FRAMETIME);
// setState({...state, bigCircleRadius: state.bigCircleRadius * 1.1})
// if (time >= 1) {
// setAnimation(undefined);
// clearInterval(intervalHandle);
// }
//}
const stopAnimation = () => {
setState(INITIAL_KEYFRAME);
setAnimation(undefined);
if (intervalRef.current !== undefined) {
clearInterval(intervalRef.current);
intervalRef.current = undefined;
}
setTime(0);
};
const gazeAndKeys = useAppSelector(getGazesAndKeys);
useEffect(() => {
for (const i of gazeAndKeys) {
if (animation !== "deny" && i.keyPress === "0") { // left mouse button
setAnimation("deny");
return;
} else if (animation !== "approve" && i.keyPress === "2") { // right mouse button
setAnimation("approve");
return;
}
}
if (!gazeAndKeys.some(x => x.keyPress === "0") && !gazeAndKeys.some(x => x.keyPress === "2")) {
stopAnimation();
}
}, [gazeAndKeys]);
return ( return (
<div <div
@ -187,8 +279,8 @@ const ApproveDenyButtonElement = ({
</div> </div>
<svg className="" style={{ width: w, height: w * SIZES.button, marginTop: -w * SIZES.button }}> <svg className="" style={{ width: w, height: w * SIZES.button, marginTop: -w * SIZES.button }}>
<clipPath id="clip"> <clipPath id="clip">
<rect />
</clipPath> </clipPath>
<circle cx={10} cy={10} r={state.bigCircleRadius * 100} fill="red" />
</svg> </svg>
</div> </div>
</div> </div>

View File

@ -16,6 +16,7 @@ export function useMouseButtonDown() {
useEffect(() => { useEffect(() => {
function handleMouseButtonDown(ev: MouseEvent) { function handleMouseButtonDown(ev: MouseEvent) {
//console.log('Mouse button pressed: ' + ev.button); //console.log('Mouse button pressed: ' + ev.button);
ev.preventDefault();
if (ev.button === 0 || ev.button === 1 || ev.button === 2 || ev.button === 3 ) { if (ev.button === 0 || ev.button === 1 || ev.button === 2 || ev.button === 3 ) {
setMouseButtDown(ev.button.toString()); setMouseButtDown(ev.button.toString());
//console.log('Mouse button pressed: ' + ev.button); //console.log('Mouse button pressed: ' + ev.button);