···
let videoElement: HTMLVideoElement;
8
+
let isDragging = false;
···
<video id="webcam" width="640" height="480" autoplay muted></video>
<canvas id="overlay" style="position: absolute;"></canvas>
30
-
<label>Left Motor (1) Rotations:</label>
31
-
<input type="range" id="motor1" min="-10" max="10" step="0.1" value="0">
32
-
<span id="motor1Value">0</span>
33
-
<button id="send1">Send</button>
32
+
<div id="joystick" style="width: 200px; height: 200px; border: 2px solid black; border-radius: 50%; position: relative; margin: 20px;">
33
+
<div id="joystickHandle" style="width: 20px; height: 20px; background: red; border-radius: 50%; position: absolute; top: 90px; left: 90px; cursor: pointer;"></div>
37
-
<label>Right Motor (2) Rotations:</label>
38
-
<input type="range" id="motor2" min="-10" max="10" step="0.1" value="0">
39
-
<span id="motor2Value">0</span>
40
-
<button id="send2">Send</button>
36
+
<span>Motor Values - X: </span><span id="motor1Value">0</span>
37
+
<span>, Y: </span><span id="motor2Value">0</span>
38
+
<button id="sendJoystick">Send</button>
<div style="width: 300px; padding: 20px; border-left: 1px solid #ccc; overflow-y: auto;">
···
175
+
function updateJoystickPosition(x: number, y: number) {
176
+
const joystick = document.getElementById("joystick");
177
+
const handle = document.getElementById("joystickHandle");
178
+
if (!joystick || !handle) return;
180
+
const bounds = joystick.getBoundingClientRect();
181
+
const radius = bounds.width / 2;
183
+
// Calculate relative position from center
184
+
const relX = x - bounds.left - radius;
185
+
const relY = y - bounds.top - radius;
187
+
// Calculate distance from center
188
+
const distance = Math.sqrt(relX * relX + relY * relY);
190
+
// Normalize to radius if outside circle
191
+
const normalizedX = distance > radius ? (relX / distance) * radius : relX;
192
+
const normalizedY = distance > radius ? (relY / distance) * radius : relY;
194
+
// Update handle position
195
+
handle.style.left = normalizedX + radius - 10 + "px";
196
+
handle.style.top = normalizedY + radius - 10 + "px";
198
+
// Update values (-0.5 to 0.5 range)
199
+
joystickX = normalizedX / (radius * 2);
200
+
joystickY = normalizedY / (radius * 2);
202
+
document.getElementById("motor1Value")!.textContent = joystickX.toFixed(2);
203
+
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;
184
-
document.getElementById("motor1")?.addEventListener("input", (e) => {
185
-
const value = (e.target as HTMLInputElement).value;
186
-
const display = document.getElementById("motor1Value");
187
-
if (display) display.textContent = value;
213
+
const joystick = document.getElementById("joystick");
214
+
const handle = document.getElementById("joystickHandle");
216
+
if (joystick && handle) {
217
+
handle.addEventListener("mousedown", () => {
221
+
document.addEventListener("mousemove", (e) => {
223
+
updateJoystickPosition(e.clientX, e.clientY);
190
-
document.getElementById("motor2")?.addEventListener("input", (e) => {
191
-
const value = (e.target as HTMLInputElement).value;
192
-
const display = document.getElementById("motor2Value");
193
-
if (display) display.textContent = value;
227
+
document.addEventListener("mouseup", () => {
229
+
isDragging = false;
document.getElementById("connect")?.addEventListener("click", connectSerial);
···
204
-
document.getElementById("send1")?.addEventListener("click", () => {
205
-
const value = (document.getElementById("motor1") as HTMLInputElement).value;
206
-
sendMotorCommand(1, parseFloat(value));
242
+
document.getElementById("sendJoystick")?.addEventListener("click", () => {
243
+
sendMotorCommand(1, joystickX);
244
+
sendMotorCommand(2, joystickY);
208
-
document.getElementById("send2")?.addEventListener("click", () => {
209
-
const value = (document.getElementById("motor2") as HTMLInputElement).value;
210
-
sendMotorCommand(2, parseFloat(value));
247
+
document.addEventListener("keydown", (e) => {
248
+
if (e.key === "Enter") {
249
+
sendMotorCommand(1, joystickX);
250
+
sendMotorCommand(2, joystickY);