Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

131
Views
Select multiple cells in grid of canvas using a mouse drag

I want to implement the selecting feature by dragging, so if drag on the grid chart, the multiple cell in form of rectangle/square, but mine is not working properly - square should be formed while I moving the mouse. But now it draw a square when i drag it and move up the mouse.

I also want the cell is selecting by square in every direction of diagonals

How do I fix it?

function getSquare(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
        x: 1 + (evt.clientX - rect.left) - (evt.clientX - rect.left)%10,
        y: 1 + (evt.clientY - rect.top) - (evt.clientY - rect.top)%10
    };
}

function drawBoard(context) {
    for (var x = 0.5; x < 10001; x += 10) {
      context.moveTo(x, 0);
      context.lineTo(x, 10000);
    }

    for (var y = 0.5; y < 10001; y += 10) {
      context.moveTo(0, y);
      context.lineTo(10000, y);
    }

    context.strokeStyle = "#ddd";
    context.stroke();
}

function fillSquare(context, x, y){
    context.fillStyle = "#70B7B5"
    context.fillRect(x,y,9,9);
}

var canvas = document.getElementById('myBoard');
var context = canvas.getContext('2d');

drawBoard(context);

var isDrag=false;
var previousPos = (-1,-1);
canvas.addEventListener('mousedown', function(evt) {
    var mousePos = getSquare(canvas, evt);
    
    isDrag=true;
    fillSquare(context, mousePos.x, mousePos.y)
    previousPos = mousePos;

}, false);

canvas.addEventListener('mousemove', function(evt) {
    if (isDrag){
        var mousePos = getSquare(canvas, evt);
        
        if (mousePos.x-previousPos.x){
            for (i=0; i<(mousePos.x-previousPos.x)/10;i++){
                for(j=0; j<(mousePos.x-previousPos.x)/10;j++){
                fillSquare(context, mousePos.x-(j*10), mousePos.y-(i*10));
            }
            }
        }else{
            for (i=0; i<(previousPos.x-mousePos.x)/10;i++){
                for(j=0; j<(previousPos.x-mousePos.x)/10;j++){
                fillSquare(context, mousePos.x+(j*10), mousePos.y-(i*10));
            }
            }
        }
        previousPos = mousePos; 
               
    }
}, false);

canvas.addEventListener('mouseup', function(evt) {
    if (isDrag){

        isDrag = false;
        
    }
 
}, false);
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>

<body>
    <canvas id="myBoard" width="10000" height="10000"></canvas>
    <script type="text/javascript" src="myBoard2.js"></script>

</body>

about 4 years ago · Santiago Trujillo
2 answers
Answer question

0

you did everything well and i changed it a little as bellow: use this range function for selecting squares in every direction of diagonals

function range(start, end) {
    var ans = [];
    if (end > start) {
        for (let i = start; i <= end; i += 10) {
            ans.push(i);
        }
    } else {
        emptySquare(context);
        for (let i = start; i >= end; i -= 10) {
            ans.push(i);
    }}
    return ans;
}

and emptySquare() to clear color of context rect as bellow:

function emptySquare(context) {
    context.rect(0, 0, canvas.width, canvas.height);
    context.fillStyle = "#ffffff"
    context.fill();
    context.strokeStyle = "#ddd";
    context.stroke();
}

then u just need to rewrite mousemove handler like this:

canvas.addEventListener('mousemove', function(evt) {
    if (isDrag) {
        var mousePos = getSquare(canvas, evt);
        var x_dist = range(previousPos.x, mousePos.x);
        var y_dist = range(previousPos.y, mousePos.y);
        for (x in x_dist) {
            for (y in y_dist) {
                fillSquare(context, x_dist[x], y_dist[y]);
        }}}
}, false);

and call emptySquare(context); in mousedown handler too...

about 4 years ago · Santiago Trujillo Report

0

A little more readable design, and sped up a bit by throttling the mouse move logic.

const canvas = document.getElementById('board');
const context = canvas.getContext('2d');

let anchor = null;
let pos = null;
let lastPos = null;

// return x,y in grid coords from an event
function position(event) {
  const rect = canvas.getBoundingClientRect();
  return [
    Math.floor((event.clientX-rect.left)/10),
    Math.floor((event.clientY-rect.top)/10)
  ];
}

// color the rectangle with corners at posA, posB
function colorRegion(posA, posB, color) {
  const minX = Math.min(posA[0], posB[0]);
  const minY = Math.min(posA[1], posB[1]);
  const maxX = Math.max(posA[0], posB[0]);
  const maxY = Math.max(posA[1], posB[1]);
  
  context.fillStyle = color
  for (let i=minX; i<maxX; i++) {
    const tenI = i*10+1
    for (let j=minY; j<maxY; j++) {
      context.fillRect(tenI,10*j+1,9,9);
    }
  }
}


// mouse down, set the anchor
canvas.addEventListener('mousedown', function(evt) {
  anchor = position(evt);
  lastPos = position(evt);
})

// mouse up, clear the anchor
canvas.addEventListener('mouseup', function(evt) {
  anchor = null;
})

// mouse move, color the old rect white, color new rect green
// remember the last pos
function onmove() {
  if (!anchor) return;
  colorRegion(anchor, lastPos, 'white')
  colorRegion(anchor, pos, '#70B7B5')
  lastPos = pos;
}

// no need to run this on every pixel
// you could also measure absolute mouse move > 10x10 as a throttle
const throttledOnMove = _.throttle(onmove, 100);

canvas.addEventListener('mousemove', function(evt) {
  pos = position(evt);
  throttledOnMove()
})
.container {
  height: 10000px;
  width: 10000px;
}

.grid {
  box-sizing: border-box;
  margin: 0;
  height: 100%;
  width: 100%;
  background-image: repeating-linear-gradient(0deg, transparent, transparent 9px, #ccc 9px, #ccc 10px), repeating-linear-gradient(-90deg, transparent, transparent 9px, #ccc 9px, #ccc 10px);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<div class="container">
  <div class="grid">
    <canvas id="board" width="10000" height="10000"></canvas>
  </div>
</div>

about 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!