I'm using a event handler on a HTML canvas to track the coordinates of where a user clicks, and my idea is to connect coordinates together with a line.
The code below creates an Array and keeps a list of coordinates within the canvas element that the user has clicked on, and also contains logic to draw a line between the currently clicked point and the point that's been previously clicked on.
The problem I'm encountering is that, no matter how many times I click, even though my Array is being populated with coordinates, the lines are not being drawn between the points.
I'm not entirely sure what I am doing wrong, or if there is some re-rendering being done that might be wiping away the drawings I make on the canvas.
var coords = [];
var canvas = document.getElementById('canvas');
canvas.addEventListener('click', function (event) {
var coord = { "x": event.screenX, "y": event.screenY };
document.getElementById("coords").innerText = "{" + coord.x + ", " + coord.y + "}";
coords.push(coord);
var max = coords.length - 1;
if (typeof coords[max - 1] !== "undefined") {
var curr = coords[max], prev = coords[max - 1];
var context = canvas.getContext("2d");
context.beginPath();
context.moveTo(prev.x, prev.y);
context.lineTo(curr.x, curr.y);
context.stroke();
}
});
<!doctype html>
</html>
<head>
<title>Drawing canvas</title>
<style>
canvas {
width: 200px;
height: 200px;
border: 2px solid black;
border-radius: 5px;
}
</style>
</head>
<body>
<p id='coords'></p>
<canvas id='canvas'></canvas>
</body>
</html>
Move your context outside the click event and use canvas coordinates instead of screen one: event.x and event.y
Do not use CSS dimensions for the canvas. Check this post
var coords = [];
var canvas = document.getElementById('canvas');
var context = canvas.getContext("2d");
canvas.addEventListener('click', function (event) {
var coord = { "x": event.x, "y": event.y};
document.getElementById("coords").innerText = "{" + coord.x + ", " + coord.y + "}";
coords.push(coord);
var max = coords.length - 1;
if (typeof coords[max - 1] !== "undefined") {
var curr = coords[max], prev = coords[max - 1];
context.beginPath();
context.moveTo(prev.x, prev.y);
context.lineTo(curr.x, curr.y);
context.stroke();
}
});
<style>
canvas {
border: 1px solid black;
border-radius: 0px;
}
body {
margin: 0;
padding: 0;
}
</style>
<canvas id='canvas' width="200" height="200"></canvas>
<p id='coords'></p>
Related
I'm working on a script which is supposed to do the following. You lock your mouse to a canvas. It will show you an "artificial" cursor instead that you can also move by using your mouse. Under this cursor, you will have a circle which also moves with the mouse.
All of this worked perfectly fine with my script which was until I added another nice feature: I want to have an Arrow in the middle of the canvas which stays there, exact same size, but rotates according to your cursor movement. To give you an idea what I'm talking about, I made these example graphs (don't worry about dimensions and colour).
https://i.stack.imgur.com/poO6n.jpg
https://i.stack.imgur.com/twXhY.jpg
https://i.stack.imgur.com/RFFBe.jpg
I did some calculations to do this, implemented them, hoped for the best, but it doesn't work. I thought when it works, it will be a cool feature for everyone to have on this site. But so far I didn't see where my mistake is. If you have a clue, I'm absolutely grateful for every answer.
Many thanks!
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>ArrowSpin</title>
<style>
html, body {
margin: 0;
padding: 0;
}
html {
font-family: sans-serif;
}
canvas {
display: block;
margin: 0 auto;
border: 1px solid black;
}
.information {
width: 640px;
margin: 0 auto 50px;
}
#tracker {
position: absolute;
top: 0;
right: 10px;
background-color: white;
}
h1 {
font-size: 200%;
}
</style>
</head>
<body>
<div class="information">
<img id="mousecursor" hidden="true" width="13" height="20.5" src="mousecursor.png" alt="Cursor">
<p id="demo" style="color: black" oncl></p>
<p id="Message" style="color: black" oncl></p>
<canvas id="myCanvas" width="640" height="360">
Your browser does not support HTML5 canvas
</canvas>
<div id="tracker"></div>
</div>
<script>
try {
// helper functions
const RADIUS = 20;
// this image is you mousecursor
var img = document.getElementById("mousecursor");
// degree to radians
function degToRad(degrees) {
var result = Math.PI / 180 * degrees;
return result;
}
// generate a random number, later on, mouse cursor should start at random position, now unused
function generateRandomNumber() {
var minangle = 0;
var maxangle = 2*Math.PI;
randangle = Math.random() * (maxangle- minangle) + minangle;
return randangle;
};
//this function draws the actual arrow
function drawArrow(fromx, fromy, tox, toy, colourarrow){
//variables to be used when creating the arrow
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var headlen = 3;
var angle = Math.atan2(toy-fromy,tox-fromx);
//starting path of the arrow from the start square to the end square and drawing the stroke
ctx.beginPath();
ctx.moveTo(fromx, fromy);
ctx.lineTo(tox, toy);
ctx.strokeStyle = colourarrow;
ctx.lineWidth = 20;
ctx.stroke();
//starting a new path from the head of the arrow to one of the sides of the point
ctx.beginPath();
ctx.moveTo(tox, toy);
ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7));
//path from the side point of the arrow, to the other side point
ctx.lineTo(tox-headlen*Math.cos(angle+Math.PI/7),toy-headlen*Math.sin(angle+Math.PI/7));
//path from the side point back to the tip of the arrow, and then again to the opposite side point
ctx.lineTo(tox, toy);
ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7));
//draws the paths created above
ctx.strokeStyle = colourarrow;
ctx.lineWidth = 20;
ctx.stroke();
ctx.fillStyle = colourarrow
ctx.fill();
}
// this function calculates the current angle of the cursor from the exact middle of the canvas (x0,y0) by using two simple assumptions which are a) radius=sqrt(sqr(xfrom)+sqr(y)) b) x=x0+radius*cos(alpha) <=> alpha=arccos((x-x0)/radius)
function CursorAngle() {
var currentrad=Math.sqrt([Math.pow(x-canvas.width/2)+Math.pow(y+canvas.height)]);
var currentangle=Math.acos([(x-canvas.width/2)/currentrad]);
return currentangle
}
//in this function I use the just calculated cursor angle to now calculate where my arrow shall begin and end, again I use x=x0+radius*cos(alpha) and y=y0+radius*sin(alpha). In this case I always want my arrow to have a radius of 50 and I always want it to be drawn in the center of the canvas.
function ProbeAngle(alpha) {
var x1 = canvas.width/2+50*cos(alpha)
var y1 = canvas.width/2+50*sin(alpha)
var x2 = canvas.width/2+50*cos(alpha+Math.PI)
var y2 = canvas.width/2+50*sin(alpha+Math.PI)
return [x1; y1; x2; y2]
}
// setup of the canvas
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
var x = canvas.width/2;
var y = canvas.height/2;
//refresh the canvas
function canvasDraw() {
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#f00";
ctx.beginPath();
ctx.arc(x, y, RADIUS, 0, degToRad(360), true);
ctx.fill();
ctx.drawImage(img, x, y);
}
canvasDraw();
// pointer lock object forking for cross browser
canvas.requestPointerLock = canvas.requestPointerLock ||
canvas.mozRequestPointerLock;
document.exitPointerLock = document.exitPointerLock ||
document.mozExitPointerLock;
canvas.onclick = function() {
canvas.requestPointerLock();
canvasDraw();
};
// pointer lock event listeners
// Hook pointer lock state change events for different browsers
document.addEventListener('pointerlockchange', lockChangeAlert, false);
document.addEventListener('mozpointerlockchange', lockChangeAlert, false);
function lockChangeAlert() {
if (document.pointerLockElement === canvas ||
document.mozPointerLockElement === canvas) {
console.log('The pointer lock status is now locked');
document.addEventListener("mousemove", updatePosition, false);
} else {
console.log('The pointer lock status is now unlocked');
document.removeEventListener("mousemove", updatePosition, false);
}
}
//tracker shows x and y coordinates of "pseudo" cursor
var tracker = document.getElementById('tracker');
//border protection for our image not to move out of the canvas
var animation;
function updatePosition(e) {
x += e.movementX;
y += e.movementY;
if (x > canvas.width) {
x = canvas.width;
}
if (y > canvas.height) {
y = canvas.height;
}
if (x < 0) {
x = 0;
}
if (y < 0) {
y = 0;
}
tracker.textContent = "X position: " + x + ", Y position: " + y;
if (!animation) {
animation = requestAnimationFrame(function() {
animation = null;
canvasDraw();
//receive the ProbeCoords by using the functions CursorAngle and ProbeAngle and draw it!
var ProbeCoord = ProbeAngle(CursorAngle());
drawArrow(ProbeCoord[0],ProbeCoord[1],ProbeCoord[2],ProbeCoord[3],'white')
});
}
}
}
catch(err) {
document.getElementById("demo").innerHTML = err.message;
}
document.getElementById("Message").innerHTML = "potential Errorcode above";
</script>
</body>
</html>
Have you tried using Fabric JS? In the linked example you can click an object and a handle appears at the top. After that you can click handle and it will follow the mouse. I'm suggesting this because most likely there is a way to change the click event to a hover event and then get the handle to follow the mouse.
I wrote this code to try to get the myCanvas to move towards myCanvas1. I tried doing this using the Math.atan2() method. However it doesn't work. Any ideas?
Please don't use any JQuery.
HTML:
<canvas id="myCanvas"></canvas>
<canvas id="myCanvas1"></canvas>
JS:
var follower = document.getElementById('myCanvas');
var flw = follower.getContext('2d');
var runner = document.getElementById('myCanvas1');
var rnr = runner.getContext('2d');
document.addEventListener('keydown', moveShot);
//Cordinates of sPositions 1 and two
var sPosition0 = [700, 700];
var sPosition1 = [400, 400];
var xPosition0 = sPosition0[0], yPosition0 = sPosition0[1];
var xPosition1 = sPosition1[0], yPosition1 = sPosition1[1];
//This should be the arctan between sPosition0 and sPosition1
var angleRadians0 = Math.atan2(sPosition0[0] - sPosition1[0], sPosition0[1] - Position1[1]);
/*The speed of the object is 4. To get it to move diagonally towards sPosition1 I need to divide dy with the angle arctan between the two objects */
var dx = 4;
var dy = 4 / angleRadians0;
function moveShot(){
// Deleting the "old" square
flw.clearRect(0, 0, 700, 700);
//Drawing the square at its appropriate position
flw.fillRect(xPosition0, yPosition0, 100, 100);
//Adding the movement after every frame
xPosition0 += dx;
yPosition0 += dy;
setTimeout(moveShot, 20);
}
CSS:
#myCanvas1{
height: 100px;
width: 100px;
background-color: '#ff0000';
}
Thanks!
EDIT:
As to what actually happens, I'm very confused. Nothing happens at all, I didn't say that because it's 3am and I thought someone would point out some very obvious mistake I've made and everything would make sence. So, what happens is well, nothing, I cannot understand why. Then again though, its 3am and I might have screwed up somewhere but I don't see where.
Here's a fiddle https://jsfiddle.net/Snubben/15tf0svd/3/
Well, the reason NOTHING happens, is that your canvas is using the default size. 300x150;
Your initial position is drawing the square OUTSIDE the canvas, and then your dx and dy variables are adding to x and y, making it move even further away (down and to the right).
See the following for an example of keeping it within the container and moving the square up and to the left.
var follower = document.getElementById('myCanvas');
var flw = follower.getContext('2d');
var runner = document.getElementById('myCanvas1');
var rnr = runner.getContext('2d');
document.addEventListener('keydown', moveShot);
//Cordinates of sPositions 1 and two
var sPosition0 = [70, 70]; //within the canvas
var sPosition1 = [40, 40]; //within the canvas
var xPosition0 = sPosition0[0],
yPosition0 = sPosition0[1];
var xPosition1 = sPosition1[0],
yPosition1 = sPosition1[1];
//This should be the arctan between sPosition0 and sPosition1
var angleRadians0 = Math.atan2(sPosition0[0] - sPosition1[0], sPosition0[1] - sPosition1[1]);
/*The speed of the object is 4. To get it to move diagonally towards sPosition1 I need to divide dy with the angle arctan between the two objects */
var dx = 4;
var dy = 4 / angleRadians0;
function moveShot() {
if(yPosition0 < 10) return;
// Deleting the "old" square
flw.fillStyle = "green";
flw.clearRect(0, 0, 700, 700);
//Drawing the square at its appropriate position
flw.fillRect(xPosition0, yPosition0, 10, 10);
//Adding the movement after every frame
xPosition0 -= dx; //move left
yPosition0 -= dy; //move up.
setTimeout(moveShot, 20);
}
#myCanvas1 {
height: 100px;
width: 100px;
background-color: #ff0000;
}
#myCanvas {
width: 300px;
height: 300px;
background-color: blue;
}
<canvas id="myCanvas" height="300" width="300"></canvas>
<canvas id="myCanvas1" height="100" width="100"></canvas>
press a key to make it work.
I have been working on a canvas animation of a circle that moves in a random direction, and every second the direction changes. I do that by changing a velocity vector every second by repeatedly calling a function using setInterval, while changing the position of the circle's center and drawing it in another function using requestAnimationFrame. The result is an empty canvas, and I'm not sure why. The code is split into the following three files:
random_ball.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Random Ball</title>
<link rel="stylesheet" href="random_ball.css">
</head>
<body>
<canvas id="canvas"></canvas>
<script src="random_ball.js"></script>
</body>
</html>
random_ball.css
html, body{
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
overflow: hidden;
margin: 0;
padding: 0;
}
canvas{
position: absolute;
width: 50vw;
height: 50vh;
top: 25vh;
left: 25vw;
border-style: solid;
margin: 0;
padding: 0;
}
random_ball.js
const canvas = document.getElementById('canvas')
const bounds = canvas.getBoundingClientRect()
const TWO_PI = 2*Math.Pi
const R = 25
const MAX_Y = bounds.height - R
const MAX_X = bounds.width - R
const ctx = canvas.getContext('2d')
function randomInterval(min, max){
return Math.random()*(max - min) + min
}
function randomVelocity(){ // velocity is pixels/sec
VEL.X = randomInterval(-POS.X + R, MAX_X - POS.X)
VEL.Y = randomInterval(-POS.Y + R, MAX_Y - POS.Y)
console.log('VEL: ' + JSON.stringify(VEL))
}
var POS = {X: bounds.height/2, Y: bounds.width/2}
var VEL = {X: 0, Y: 0}
var LAST_TIME = window.performance.now()
function drawCircle(color){
ctx.strokeStyle = color
ctx.beginPath()
ctx.moveTo(POS.X, POS.Y)
ctx.arc(POS.X, POS.Y, R, 0, TWO_PI, true)
ctx.stroke()
}
function draw(timestamp){
var dt = (timestamp - LAST_TIME)/1000
var dx = VEL.X*dt
var dy = VEL.Y*dt
drawCircle('#FFFFFF') // erase the old drawing by making it white
POS.X += dx
POS.Y += dy
//console.log('POS: ' + JSON.stringify(POS))
drawCircle('#000000')
LAST_TIME = timestamp
requestAnimationFrame(draw)
}
randomVelocity()
drawCircle('#000000')
setInterval(randomVelocity, 1000) //change velocity every second
requestAnimationFrame(draw)
I suspect that drawing white over the old circle means the picture is changing too fast for me to see it.
You might want to familiarize yourself with JavaScript syntax rules, and possibly a code checker like JSHint.
The main problem with your code is that you're referencing a nonexistent property of the Math object. Math has no Pi property. It's spelled PI (all caps). JavaScript is case sensitive about these things.
Next: a more common practice for clearing the canvas is to use ctx.clearRect(0, 0, width, height). Here's a JSFiddle to help you see the difference: https://jsfiddle.net/Hatchet/dy2dognp/
I'm currently learning canvas touch event function,I 'm able to draw line on the canvas, now I want to get the x and y coordinates when I draw any lines and show on the screen.please help and teach me how to get the x and y values, thank You!
here is the coding
<!DOCTYPE html>
<html><head>
<style>
#contain {
width: 500px;
height: 120px;
top : 15px;
margin: 0 auto;
position: relative;
}
</style>
<script>
var canvas;
var ctx;
var lastPt=null;
var letsdraw = false;
var offX = 10, offY = 20;
function init() {
var touchzone = document.getElementById("layer1");
touchzone.addEventListener("touchmove", draw, false);
touchzone.addEventListener("touchend", end, false);
ctx = touchzone.getContext("2d");
}
function draw(e) {
e.preventDefault();
if (lastPt != null) {
ctx.beginPath();
ctx.moveTo(lastPt.x, lastPt.y);
ctx.lineTo(e.touches[0].pageX - offX,
e.touches[0].pageY - offY);
ctx.stroke();
}
lastPt = {
x: e.touches[0].pageX - offX,
y: e.touches[0].pageY - offY
};
}
function end(e) {
var touchzone = document.getElementById("layer1");
e.preventDefault();
// Terminate touch path
lastPt = null;
}
function clear_canvas_width ()
{
var s = document.getElementById ("layer1");
var w = s.width;
s.width = 10;
s.width = w;
}
</script>
</head>
<body onload="init()">
<div id="contain">
<canvas id="layer1" width="450" height="440"
style="position: absolute; left: 0; top: 0;z-index:0; border: 1px solid #ccc;"></canvas>
</div>
</body>
</html>
Still not entirely confident I understand your question.
In the code you posted, you are already obtaining coordinates using e.touches[0].pageX/Y. The main problem with that is that the pageX/Y values are relative to the page origin. You are then subtracting fixed offX/Y in your code to try and convert these to canvas-relative coordinates. Right idea, wrong values. You need to subtract off the position of the canvas element which can be obtained by summing the offsetX/Y values as you traverse the tree upward using the offsetParent reference.
Something like:
offX=0;offY=0;
node = document.getElementById ("layer1");
do {
offX += node.offsetX;
offY += node.offsetY;
node = node.offsetParent;
} while(node);
should give you a better value for offX and offY.
If you just want to locate the actual drawing at the end, it would be easiest just to track a bounding box while the user draws.
I'm trying to draw a rectangle by a user click, mouse move, and click. There are two problems with my code.
Firstly, after one rectangle is drawn it is automatically assumed that another one will be drawn. Secondly, the starting point on the second rectangle is the last click that created the first rectangle.
http://jsbin.com/uqonuw/3/edit
You were close. So, the question isn't really about the "canvas" element in HTML5, but a canvas that is really a div.
http://jsfiddle.net/d9BPz/546/
In order for me to see what your code was trying to accomplish, I had to tidy it up. What needed to happen was tracking of the square element.
We are doing one of two things everytime we click on the canvas. We are either creating a rectangle element, or finishing a rectangle element. So, when we're finished it makes sense to set 'element' (previously named 'd') to null. When creating an element, we have to assign the new DOM element to 'element'.
Everytime the mouse moves, we want to get the mouse position. If the element is in the process of creation (or "not null"), then we need to resize the element.
Then we wrap it all up in a function, and that's all there is to it:
function initDraw(canvas) {
var mouse = {
x: 0,
y: 0,
startX: 0,
startY: 0
};
function setMousePosition(e) {
var ev = e || window.event; //Moz || IE
if (ev.pageX) { //Moz
mouse.x = ev.pageX + window.pageXOffset;
mouse.y = ev.pageY + window.pageYOffset;
} else if (ev.clientX) { //IE
mouse.x = ev.clientX + document.body.scrollLeft;
mouse.y = ev.clientY + document.body.scrollTop;
}
};
var element = null;
canvas.onmousemove = function (e) {
setMousePosition(e);
if (element !== null) {
element.style.width = Math.abs(mouse.x - mouse.startX) + 'px';
element.style.height = Math.abs(mouse.y - mouse.startY) + 'px';
element.style.left = (mouse.x - mouse.startX < 0) ? mouse.x + 'px' : mouse.startX + 'px';
element.style.top = (mouse.y - mouse.startY < 0) ? mouse.y + 'px' : mouse.startY + 'px';
}
}
canvas.onclick = function (e) {
if (element !== null) {
element = null;
canvas.style.cursor = "default";
console.log("finsihed.");
} else {
console.log("begun.");
mouse.startX = mouse.x;
mouse.startY = mouse.y;
element = document.createElement('div');
element.className = 'rectangle'
element.style.left = mouse.x + 'px';
element.style.top = mouse.y + 'px';
canvas.appendChild(element)
canvas.style.cursor = "crosshair";
}
}
}
Usage: Pass the block-level element that you would like to make a rectangle canvas.
Example:
<!doctype html>
<html>
<head>
<style>
#canvas {
width:2000px;
height:2000px;
border: 10px solid transparent;
}
.rectangle {
border: 1px solid #FF0000;
position: absolute;
}
</style>
</head>
<body>
<div id="canvas"></div>
<script src="js/initDraw.js"></script>
<script>
initDraw(document.getElementById('canvas'));
</script>
</body>
</html>
Here's how to click-move-click to create a rectangle
Create these variables:
var isDrawing=false;
var startX;
var startY;
In your mousedown event handler:
If this is the starting click, set the isDrawing flag and set the startX/Y.
If this is the ending click, clear the isDrawing flage and draw the rectangle.
You might also want to change the mouse cursor so the user knows they are drawing.
if(isDrawing){
isDrawing=false;
ctx.beginPath();
ctx.rect(startX,startY,mouseX-startX,mouseY-startY);
ctx.fill();
canvas.style.cursor="default";
}else{
isDrawing=true;
startX=mouseX;
startY=mouseY;
canvas.style.cursor="crosshair";
}
Here is a Fiddle: http://jsfiddle.net/m1erickson/7uNfW/
Instead of click-move-click, how about using drag to create a rectangle?
Create these variables:
var mouseIsDown=false;
var startX;
var startY;
In your mousedown event handler, set the mouseIsDown flag and set the startX/Y.
Optionally, change the cursor so the user knows their dragging a rectangle.
mouseIsDown=true;
startX=mouseX;
startY=mouseY;
canvas.style.cursor="crosshair";
In your mouseup event handler, clear the mouseIsDown flag and draw the rect
If you changed the cursor, change it back.
mouseIsDown=false;
ctx.beginPath();
ctx.rect(startX,startY,mouseX-startX,mouseY-startY);
ctx.fill();
canvas.style.cursor="default";
For those who encountered the scrolling problem, I've found a fix.
You need to get the offset (using window.pageYOffset) and reduce it from the mouse position in any of the recommended snippets given. You should take it off from the height as well.
i was also working on a project, so here's my code
enjoy.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Selection</title>
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
<style>
body {
margin: 0px;
background-color: #f1f1f1;
}
canvas {
border: none;
}
</style>
</head>
<body>
<canvas id="canvas" width="800" height="500"></canvas>
<div id="output"></div>
<script>
//Canvas
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
//Variables
var canvasx = $(canvas).offset().left;
var canvasy = $(canvas).offset().top;
var last_mousex = last_mousey = 0;
var mousex = mousey = 0;
var mousedown = false;
//Mousedown
$(canvas).on('mousedown', function(e) {
last_mousex = parseInt(e.clientX-canvasx);
last_mousey = parseInt(e.clientY-canvasy);
mousedown = true;
});
//Mouseup
$(canvas).on('mouseup', function(e) {
mousedown = false;
ctx.clearRect(0, 0, canvas.width, canvas.height);
});
//Mousemove
$(canvas).on('mousemove', function(e) {
mousex = parseInt(e.clientX-canvasx);
mousey = parseInt(e.clientY-canvasy);
if(mousedown) {
ctx.clearRect(0,0,canvas.width,canvas.height); //clear canvas
ctx.beginPath();
var width = mousex-last_mousex;
var height = mousey-last_mousey;
ctx.rect(last_mousex,last_mousey,width,height);
//ctx.fillStyle = "#8ED6FF";
ctx.fillStyle = 'rgba(164, 221, 249, 0.3)'
ctx.fill();
ctx.strokeStyle = '#1B9AFF';
ctx.lineWidth = 1;
ctx.fillRect(last_mousex, last_mousey, width, height)
ctx.stroke();
}
//Output
$('#output').html('current: '+mousex+', '+mousey+'<br/>last: '+last_mousex+', '+last_mousey+'<br/>mousedown: '+mousedown);
});
</script>
</body>
</html>
Below is the solution I created in React. There might be some corner cases but it is working as per my knowledge.
Solution approach.
You must have start (x,y position) and the end (x,y) position
Once the user clicks on the cell capture cell number and column number start (x,y), this will happen on the mouseDown event
Then the user starts moving the mouse, in that case capture the cell number and the row number end (x,y) respectively.
Now the div draw logic comes where the condition would highlight the cell if the below condition is true.
i = cellNumber
i >= Math.min(start,end) && i <= Math.max(start,end) && i%4 <= Math.max(startY, endY)
https://codesandbox.io/s/still-field-0q760y?file=/src/App.js