Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | 2x 10x 10x 10x 10x 10x 10x | import React from "react";
import { useState } from "react";
import useInterval from "use-interval";
import { useSpring, animated } from "@react-spring/web";
import { useDrag } from "@use-gesture/react";
import { apiUpdateMoveRaw } from "./rest";
export const Joystick = (props) => {
const [state, setState] = useState({active: false, position: {x: 0, y: 0}});
const [{ x, y }, set] = useSpring(() => ({ x: 0, y: 0 }));
const bind = useDrag(async ({ active, movement: [mx, my] }) => {
let distance = Math.sqrt(Math.pow(mx, 2) + Math.pow(my, 2));
if (active && distance > 100) {
return;
}
let newPos = { x: mx, y: my };
setState({active: active, position: newPos});
set({ x: active ? mx : 0, y: active ? my : 0, immediate: active });
if (!active) {
await apiUpdateMoveRaw(props.address, 0, 0).catch(error => console.log(error));
}
})
const moveToSpeeds = () => {
const dir = (128 * state.position.y / 200) * -1;
const angle = (128 * state.position.x / 200) * -1;
let leftSpeed = 1.5 * (dir - angle);
let rightSpeed = 1.5 * (dir + angle);
// Use speed offset
if (leftSpeed > 0) {
leftSpeed += 50;
}
if (rightSpeed > 0) {
rightSpeed += 50;
}
if (leftSpeed < 0) {
leftSpeed -= 50;
}
if (rightSpeed < 0) {
rightSpeed -= 50;
}
// Clamp speeds to int8 bounds
if (leftSpeed > 127) {
leftSpeed = 127;
}
if (rightSpeed > 127) {
rightSpeed = 127;
}
if (leftSpeed < -128) {
leftSpeed = -128;
}
if (rightSpeed < -128) {
rightSpeed = -128;
}
return { left: leftSpeed, right: rightSpeed };
};
useInterval(async () => {
const speeds = moveToSpeeds();
await apiUpdateMoveRaw(props.address, speeds.left, speeds.right).catch(error => console.log(error));
}, state.active ? 100 : null);
return (
<div style={{ height: '200px', width: '200px' }}>
<div style={{ height: '200px', width: '200px', position: "absolute" }} role="region">
<svg style={{ height: '199px', width: '199px'}}>
<circle cx={99} cy={99} r={98} fill="Lavender" opacity="80%" stroke="black" strokeWidth="1" />
</svg>
</div>
<div style={{ position: "relative", top: "50px", left: "50px" }}>
<animated.div {...bind()} style={{ x, y, touchAction: 'none' }} role="button">
<svg style={{ height: '100px', width: '100px' }}>
<defs>
<radialGradient id="joystickHandleGradient">
<stop offset="5%" stopColor="MediumSlateBlue" />
<stop offset="95%" stopColor="DarkSlateBlue" />
</radialGradient>
</defs>
<circle cx={50} cy={50} r={50} opacity="80%" fill="url('#joystickHandleGradient')" />
</svg>
</animated.div>
</div>
</div>
)
}
|