Tips for creating a drawing grid with a table

I am currently working on a project where I need to create a canvas-like table with around 10,000 cells. The goal is to allow users to draw on this canvas by moving their mouse over it while holding down specific keys (e.g. ctrl for blue, shift for red).

While I have successfully generated the HTML code for the table, I am facing an issue with the functionality. It seems that instead of filling in the cells with color, my script is trying to select them.

Below is a preview of what I am experiencing:

HTML:

<html>
  <head>
<meta charset="utf-8">
<title>Drawing Program</title>
<h1>Drawing Demonstration</h1>
<link rel = "stylesheet" type = "text/css" href = "style.css">
<script src = "draw.js"></script>
</head>
<body>
<table id = "canvas">
  <caption>Hold Ctrl (or Control) to draw in blue.
    Hold Shift to draw in red.</caption>
    <tbody id = "tablebody"></tbody>
</table>
</body>
</html>

CSS:

table{
width: 400px;
height: 400px;
border-collapse: collapse;
}

td {
width: 4px;
height: 4px;
border-collapse: collapse;
}

JavaScript:

function createCanvas()
{
    var side = 100;
    var tbody = document.getElementById( "tablebody" );

for( var i = 0; i < side; i++) 
{
    var row = document.createElement( "tr" );

    for( var j = 0; j < side; j++)
    {
        var cell = document.createElement( "td" );
        row.appendChild( cell );
    }
    tbody.appendChild( row );
}
document.getElementById( "canvas" ).addEventListener( "mousemove", processMouseMove, false );
}

function processMouseMove( e )
{
  if( e.target.tagName.toLowerCase() == "td" )
{
    if( e.ctrlKey )
    {
        e.target.setAttribute( "class", "blue" );
    }
    if ( e.shiftKey )
    {
        e.target.setAttribute( "class", "red" );
    }
}
}
window.addEventListener( "load", createCanvas, false );

Answer №1

Instead of creating numerous table cells, I suggest using a canvas element and filling it with pixels that match the size of table cells. By utilizing modulo arithmetic, you can translate mouse coordinates into pixel positions.

For instance, if the mouse is positioned at (x, y) and each pixel is 4 units in size, the mouse aligns with the pixel where:

  • row = x - x % 4

  • column = y - y % 4

The code snippet below illustrates this method. Upon running the snippet, ensure to click inside the canvas's frame to enable mouse focus within the frame.

var Paint = {
  pixel: { size: 4 },
  grid: { numRows: 100, numCols: 100 }
};

window.onload = function () {
  var canvas = document.getElementById('paintCanvas'),
      context = canvas.getContext('2d'),
      offset = getOffset(canvas, document.body),
      pixelSize = Paint.pixel.size,
      numRows = Paint.grid.numRows,
      numCols = Paint.grid.numCols,
      painting = false;
  
  canvas.width = numCols * pixelSize;
  canvas.height = numRows * pixelSize;
  
  window.onkeydown = function (event) {
    var code = event.which;
    if (code == 17 || code == 16) {
      painting = true;
      context.fillStyle = (code == 17 ? '#1b6bb5' : '#b53a31');
    }
  };
  
  window.onkeyup = function (event) {
    var code = event.which;
    if (code == 17 || code == 16) {
      painting = false;
    }
  };
  
  canvas.onmousemove = function (event) {
    if (!painting) {
      return;
    }
    event = event || window.event;
    var mouse = getMousePosition(event),
        x = mouse.x - offset.left,
        y = mouse.y - offset.top;
    x -= x % pixelSize;
    y -= y % pixelSize;
    context.fillRect(x, y, pixelSize, pixelSize);
  };
};
  
function getOffset(element, ancestor) { 
  var left = 0,
      top = 0;
  while (element != ancestor) { 
    left += element.offsetLeft;
    top += element.offsetTop;
    element = element.parentNode;
  } 
  return { left: left, top: top };
} 

function getMousePosition(event) { 
  if (event.pageX !== undefined) { 
    return { x: event.pageX, y: event.pageY };
  } 
  return { 
    x: event.clientX + document.body.scrollLeft + 
        document.documentElement.scrollLeft,
    y: event.clientY + document.body.scrollTop + 
        document.documentElement.scrollTop
  };
}
body {
  font-family: sans-serif;
}

canvas {
  border: 2px solid #ccc;
}
<p> <b>Click here to start.</b> Hold Ctrl to draw in blue, Shift to draw in red. </p>

<canvas id="paintCanvas"></canvas>

Answer №2

To enhance the table functionality, I suggest inserting an empty absolute positioned div before the table. By assessing the height and width of the td elements, we can determine the precise xy coordinates within the table based on mouse movements. This would allow us to perform various table manipulations seamlessly.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing Regular Input with Material-UI's Autocomplete Feature

Is there a way to replace TextField with a regular input in an Autocomplete? ...

What is the method for obtaining a unique id that changes dynamically?

Having trouble accessing the dynamically generated ID in jQuery? It seems to work fine in JavaScript but not in jQuery. Here's an example of the issue: My jQuery code: var img = $("#MAP"+current_img_height); $("#map").css({'height': img.h ...

Using vue.js to customize the items shown in the ox carousel

Greetings, I am currently utilizing the "carousel" component from Buefy with Vue.js. In desktop resolution, I need to display 3 elements, but on mobile devices, I want only one article to be visible. I have created a function that adjusts the property of t ...

Having trouble with the `npm run dev` command in a Laravel project? You may be encountering a `TypeError: program.parseAsync is not

Recently, I integrated Vue.js into my ongoing Laravel project using npm to delve into front-end development with the framework. Following the installation, the instructions guided me to execute npm run dev in order to visualize the modifications made in . ...

Guide to sending client-to-client notifications in Angular/Ionic with Firebase Cloud Messaging

I am looking to implement client-client push notifications (not server-to-client). My goal is to send a notification when one user messages another. Is this feasible? How can I achieve this using the structure in the Firebase real-time database? Here is a ...

Displaying a JQuery loading image on a webpage for a designated amount of time

I am trying to display an image in a div once a price calculation function is called. The image should cover the whole page. Can someone assist me with this? <div class="Progress_Layout" style="display:none"> <div class="Progress_Content"> ...

Implementing an Ajax function for handling multiple button clicks

So, here's the situation - I've inherited a form with two buttons that inexplicably have the same name and id (seriously, don't ask me why, I didn't design this form haha). I'm attempting to utilize the Ajax .click function to trig ...

Integrate predictive text suggestions in JavaServer Pages for efficient form filling

After some research, I have managed to solve the issue I was facing. On my jsp page, I have three text boxes. When I enter data into the first text box, it triggers a call to get.jsp to fetch data from the database and populate the second text box. However ...

Accessing Elements by Class Name

I've been searching for information on the capabilities of getElementsByClassName for hours. While some sources mention it returns an HTML collection of items, length, and named items, w3schools provides an example where innerHTML is utilized: var x ...

I am interested in retrieving a variable from a function

this is some unique HTML code <form id="upload"> <label for="file">Choose a File to Upload</label> <input type="file" id="file" accept=".json"> <butto ...

Launching an image link within the same location on the subsequent page to which it is directed

I'm completely new to creating websites so I may not be using the correct terminology. I've searched with various terms and ideas but haven't found any solutions to help me ask my question effectively or find examples of what I'm lookin ...

What are the best ways to stop jQuery events from propagating to ancestor elements?

I have a collection of nested UL's that follow this structure: <ul class="categorySelect" id=""> <li class="selected">Root<span class='catID'>1</span> <ul class="" id=""> <li>First Cat<span ...

Implementing a full-width search bar within the Bootstrap navbar

I'm trying to create a navbar using Bootstrap 3.7.7 with a logo on the left, links on the right in two rows, and a large search bar in the center. I've managed to align the logo and links correctly, but I'm struggling with sizing the search ...

Managing large datasets effectively in NestJS using fast-csv

Currently leveraging NestJS v9, fast-csv v4, and BigQuery for my project. Controller (CSV Upload): @Post('upload') @ApiOperation({ description: 'Upload CSV File' }) @ApiConsumes('multipart/form-data') ... // Code shorten ...

Implementing Multiple HTML Files Loading in QUnit

Currently, I am utilizing QUnit for unit testing JavaScript and jQuery. The structure of my HTML document is as follows: <!DOCTYPE html> <html> <head> <title>QUnit Test Suite</title> <script src="../lib/jquery.js">< ...

How to use jQuery to remove the last element from an array when the back button

Currently encountering an issue with removing the last element from an array when a back button is clicked. The console is displaying the correct elements in the array, but it seems that the array.slice function is not working as expected, and I'm str ...

What is the best way to position the content area to the right of the menu on my website?

Hey there! I'm currently facing an issue with Bootstrap 4 where my content area is appearing below the vertical navbar instead of next to it on the right side. Any suggestions on how to adjust my code to fix this? Thanks in advance! <div class=&qu ...

What is the best way to transmit a 500x500 2D Integer Array using Websockets?

I'm encountering an issue where I believe it may be too time-consuming to JSON.stringify and send data to each individual user. For example, if 4 people connect at the same time, the server will become stalled during array parsing, resulting in signif ...

Developing a jQuery loop

I am in the process of creating a function that will change the background color (color A), box color (color B), and text color (color A) when a user clicks on the refresh button. I have already defined an array called 'colors', but I am struggli ...

What is the best way to compare a JSON object and a string in JavaScript?

Currently, I am working on developing the website layout for . Most of the data retrieval and display have been successful so far. However, when attempting to filter my search results to show only stop names associated with Subways, I encountered some err ...