···
let videoElement: HTMLVideoElement;
+
let isDragging = false;
···
<video id="webcam" width="640" height="480" autoplay muted></video>
<canvas id="overlay" style="position: absolute;"></canvas>
+
<div id="joystick" style="width: 200px; height: 200px; border: 2px solid black; border-radius: 50%; position: relative; margin: 20px;">
+
<div id="joystickHandle" style="width: 20px; height: 20px; background: red; border-radius: 50%; position: absolute; top: 90px; left: 90px; cursor: pointer;"></div>
+
<span>Motor Values - X: </span><span id="motor1Value">0</span>
+
<span>, Y: </span><span id="motor2Value">0</span>
+
<button id="sendJoystick">Send</button>
<div style="width: 300px; padding: 20px; border-left: 1px solid #ccc; overflow-y: auto;">
···
+
function updateJoystickPosition(x: number, y: number) {
+
const joystick = document.getElementById("joystick");
+
const handle = document.getElementById("joystickHandle");
+
if (!joystick || !handle) return;
+
const bounds = joystick.getBoundingClientRect();
+
const radius = bounds.width / 2;
+
// Calculate relative position from center
+
const relX = x - bounds.left - radius;
+
const relY = y - bounds.top - radius;
+
// Calculate distance from center
+
const distance = Math.sqrt(relX * relX + relY * relY);
+
// Normalize to radius if outside circle
+
const normalizedX = distance > radius ? (relX / distance) * radius : relX;
+
const normalizedY = distance > radius ? (relY / distance) * radius : relY;
+
// Update handle position
+
handle.style.left = normalizedX + radius - 10 + "px";
+
handle.style.top = normalizedY + radius - 10 + "px";
+
// Update values (-0.5 to 0.5 range)
+
joystickX = normalizedX / (radius * 2);
+
joystickY = normalizedY / (radius * 2);
+
document.getElementById("motor1Value")!.textContent = joystickX.toFixed(2);
+
document.getElementById("motor2Value")!.textContent = joystickY.toFixed(2);
function defaultPageRender() {
const app = document.querySelector<HTMLDivElement>("#app");
if (!app) throw new Error("App element not found");
···
videoElement = document.getElementById("webcam") as HTMLVideoElement;
+
const joystick = document.getElementById("joystick");
+
const handle = document.getElementById("joystickHandle");
+
if (joystick && handle) {
+
handle.addEventListener("mousedown", () => {
+
document.addEventListener("mousemove", (e) => {
+
updateJoystickPosition(e.clientX, e.clientY);
+
document.addEventListener("mouseup", () => {
document.getElementById("connect")?.addEventListener("click", connectSerial);
···
+
document.getElementById("sendJoystick")?.addEventListener("click", () => {
+
sendMotorCommand(1, joystickX);
+
sendMotorCommand(2, joystickY);
+
document.addEventListener("keydown", (e) => {
+
if (e.key === "Enter") {
+
sendMotorCommand(1, joystickX);
+
sendMotorCommand(2, joystickY);