Elliot Sones commited on
Commit
8a44149
·
1 Parent(s): 45278ff

Fix: Improve JS canvas initialization and event handling

Browse files
Files changed (1) hide show
  1. app.py +102 -99
app.py CHANGED
@@ -233,113 +233,116 @@ def predict(strokes_json):
233
  # ============================================================================
234
 
235
  CANVAS_HTML = """
236
- <div id="canvas-container" style="display: flex; flex-direction: column; align-items: center;">
237
  <canvas id="drawing-canvas" width="400" height="400"
238
- style="border: 2px solid #333; border-radius: 8px; background: white; cursor: crosshair;"></canvas>
239
  <div style="margin-top: 10px;">
240
- <button onclick="clearCanvas()" style="padding: 8px 16px; margin-right: 10px; cursor: pointer;">Clear</button>
241
  <button onclick="sendStrokes()" style="padding: 8px 16px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;">Predict</button>
242
  </div>
243
  <p style="color: #666; font-size: 12px; margin-top: 5px;">Draw an animal, then click Predict</p>
244
  </div>
245
 
246
  <script>
247
- const canvas = document.getElementById('drawing-canvas');
248
- const ctx = canvas.getContext('2d');
249
- let isDrawing = false;
250
- let strokes = [];
251
- let currentStroke = {x: [], y: []};
252
-
253
- ctx.strokeStyle = '#000';
254
- ctx.lineWidth = 3;
255
- ctx.lineCap = 'round';
256
- ctx.lineJoin = 'round';
257
-
258
- canvas.addEventListener('mousedown', (e) => {
259
- isDrawing = true;
260
- const rect = canvas.getBoundingClientRect();
261
- const x = e.clientX - rect.left;
262
- const y = e.clientY - rect.top;
263
- currentStroke = {x: [x], y: [y]};
264
- ctx.beginPath();
265
- ctx.moveTo(x, y);
266
- });
267
-
268
- canvas.addEventListener('mousemove', (e) => {
269
- if (!isDrawing) return;
270
- const rect = canvas.getBoundingClientRect();
271
- const x = e.clientX - rect.left;
272
- const y = e.clientY - rect.top;
273
- currentStroke.x.push(x);
274
- currentStroke.y.push(y);
275
- ctx.lineTo(x, y);
276
- ctx.stroke();
277
- });
278
-
279
- canvas.addEventListener('mouseup', () => {
280
- if (isDrawing && currentStroke.x.length > 1) {
281
- strokes.push([currentStroke.x, currentStroke.y]);
282
- }
283
- isDrawing = false;
284
- });
285
-
286
- canvas.addEventListener('mouseleave', () => {
287
- if (isDrawing && currentStroke.x.length > 1) {
288
- strokes.push([currentStroke.x, currentStroke.y]);
289
- }
290
- isDrawing = false;
291
- });
292
-
293
- // Touch support
294
- canvas.addEventListener('touchstart', (e) => {
295
- e.preventDefault();
296
- const touch = e.touches[0];
297
- const rect = canvas.getBoundingClientRect();
298
- const x = touch.clientX - rect.left;
299
- const y = touch.clientY - rect.top;
300
- isDrawing = true;
301
- currentStroke = {x: [x], y: [y]};
302
- ctx.beginPath();
303
- ctx.moveTo(x, y);
304
- });
305
-
306
- canvas.addEventListener('touchmove', (e) => {
307
- e.preventDefault();
308
- if (!isDrawing) return;
309
- const touch = e.touches[0];
310
- const rect = canvas.getBoundingClientRect();
311
- const x = touch.clientX - rect.left;
312
- const y = touch.clientY - rect.top;
313
- currentStroke.x.push(x);
314
- currentStroke.y.push(y);
315
- ctx.lineTo(x, y);
316
- ctx.stroke();
317
- });
318
-
319
- canvas.addEventListener('touchend', () => {
320
- if (isDrawing && currentStroke.x.length > 1) {
321
- strokes.push([currentStroke.x, currentStroke.y]);
322
- }
323
- isDrawing = false;
324
- });
325
-
326
- function clearCanvas() {
327
- ctx.clearRect(0, 0, canvas.width, canvas.height);
328
- strokes = [];
329
- }
330
-
331
- function sendStrokes() {
332
- const strokesJson = JSON.stringify(strokes);
333
- // Update the hidden textbox with strokes data
334
- const textbox = document.querySelector('#strokes-input textarea');
335
- if (textbox) {
336
- textbox.value = strokesJson;
337
- textbox.dispatchEvent(new Event('input', { bubbles: true }));
338
- }
339
- // Also trigger the button
340
- const btn = document.querySelector('#predict-btn');
341
- if (btn) btn.click();
342
- }
 
 
 
343
  </script>
344
  """
345
 
 
233
  # ============================================================================
234
 
235
  CANVAS_HTML = """
236
+ <div id="canvas-container" style="display: flex; flex-direction: column; align-items: center; position: relative; z-index: 10;">
237
  <canvas id="drawing-canvas" width="400" height="400"
238
+ style="border: 2px solid #333; border-radius: 8px; background: white; cursor: crosshair; touch-action: none;"></canvas>
239
  <div style="margin-top: 10px;">
240
+ <button onclick="clearCanvas()" style="padding: 8px 16px; margin-right: 10px; cursor: pointer; border: 1px solid #ccc; border-radius: 4px; background: #fff;">Clear</button>
241
  <button onclick="sendStrokes()" style="padding: 8px 16px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;">Predict</button>
242
  </div>
243
  <p style="color: #666; font-size: 12px; margin-top: 5px;">Draw an animal, then click Predict</p>
244
  </div>
245
 
246
  <script>
247
+ (function() {
248
+ // Wait for DOM
249
+ setTimeout(() => {
250
+ const canvas = document.getElementById('drawing-canvas');
251
+ if (!canvas) {
252
+ console.error("Canvas not found!");
253
+ return;
254
+ }
255
+
256
+ const ctx = canvas.getContext('2d', { willReadFrequently: true });
257
+ let isDrawing = false;
258
+ let strokes = [];
259
+ let currentStroke = {x: [], y: []};
260
+
261
+ ctx.strokeStyle = '#000';
262
+ ctx.lineWidth = 3;
263
+ ctx.lineCap = 'round';
264
+ ctx.lineJoin = 'round';
265
+
266
+ // Mouse Events
267
+ canvas.addEventListener('mousedown', (e) => {
268
+ isDrawing = true;
269
+ const rect = canvas.getBoundingClientRect();
270
+ const x = e.clientX - rect.left;
271
+ const y = e.clientY - rect.top;
272
+ currentStroke = {x: [x], y: [y]};
273
+ ctx.beginPath();
274
+ ctx.moveTo(x, y);
275
+ });
276
+
277
+ canvas.addEventListener('mousemove', (e) => {
278
+ if (!isDrawing) return;
279
+ const rect = canvas.getBoundingClientRect();
280
+ const x = e.clientX - rect.left;
281
+ const y = e.clientY - rect.top;
282
+ currentStroke.x.push(x);
283
+ currentStroke.y.push(y);
284
+ ctx.lineTo(x, y);
285
+ ctx.stroke();
286
+ });
287
+
288
+ const endStroke = () => {
289
+ if (isDrawing && currentStroke.x.length > 0) {
290
+ strokes.push([currentStroke.x, currentStroke.y]);
291
+ }
292
+ isDrawing = false;
293
+ };
294
+
295
+ canvas.addEventListener('mouseup', endStroke);
296
+ canvas.addEventListener('mouseleave', endStroke);
297
+
298
+ // Touch Events
299
+ canvas.addEventListener('touchstart', (e) => {
300
+ e.preventDefault();
301
+ const touch = e.touches[0];
302
+ const rect = canvas.getBoundingClientRect();
303
+ const x = touch.clientX - rect.left;
304
+ const y = touch.clientY - rect.top;
305
+ isDrawing = true;
306
+ currentStroke = {x: [x], y: [y]};
307
+ ctx.beginPath();
308
+ ctx.moveTo(x, y);
309
+ }, { passive: false });
310
+
311
+ canvas.addEventListener('touchmove', (e) => {
312
+ e.preventDefault();
313
+ if (!isDrawing) return;
314
+ const touch = e.touches[0];
315
+ const rect = canvas.getBoundingClientRect();
316
+ const x = touch.clientX - rect.left;
317
+ const y = touch.clientY - rect.top;
318
+ currentStroke.x.push(x);
319
+ currentStroke.y.push(y);
320
+ ctx.lineTo(x, y);
321
+ ctx.stroke();
322
+ }, { passive: false });
323
+
324
+ canvas.addEventListener('touchend', endStroke);
325
+
326
+ // Global functions for buttons
327
+ window.clearCanvas = function() {
328
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
329
+ strokes = [];
330
+ };
331
+
332
+ window.sendStrokes = function() {
333
+ const strokesJson = JSON.stringify(strokes);
334
+ const textbox = document.querySelector('#strokes-input textarea');
335
+ if (textbox) {
336
+ textbox.value = strokesJson;
337
+ textbox.dispatchEvent(new Event('input', { bubbles: true }));
338
+ }
339
+ const btn = document.querySelector('#predict-btn');
340
+ if (btn) btn.click();
341
+ };
342
+
343
+ console.log("Canvas initialized!");
344
+ }, 500); // Small delay to ensure render
345
+ })();
346
  </script>
347
  """
348