Reputation: 475
I'm trying to let users draw rectangles on a canvas using the mouse and i've been able to get it to work to some extent.The users can draw the rectangles using the mouse but it only shows after the mouseup event but i also want the users to also see the rectangles while drawing it on mousemove event. How can i achieve this and at the same time let users draw multiple rectangles which currently works but i want them to see it while drawing the rectangles.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
#container {
/*background-color: lime;*/
width: 150px;
height: 150px;
cursor: pointer;
}
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
#heatmapContainer {
border: 1px solid red;
}
</style>
</head>
<body>
<div class="heatmapWrapper">
<div id="heatmapContainer" style="height: 4205px; width: 1278px">
<div id="heatmap1" class="heatmapTile" style="height: 4205px; position: relative">
<canvas id="myCanvas" class="heatmap-canvas" width="1278" height="4205" style="position: absolute; left: 0px; top: 0px"></canvas>
</div>
</div>
</div>
<script>
var canvas = document.getElementById('myCanvas'),
elemLeft = canvas.offsetLeft,
elemTop = canvas.offsetTop,
context = canvas.getContext('2d');
let start = {};
var mouseDown = false;
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect(),
scaleX = canvas.width / rect.width,
scaleY = canvas.height / rect.height;
return {
x: (evt.clientX - rect.left) * scaleX,
y: (evt.clientY - rect.top) * scaleY,
};
}
function startRect(e) {
start = getMousePos(canvas, e);
mouseDown = true;
}
window.addEventListener('mousedown', startRect);
function endRect(e) {
let {
x,
y
} = getMousePos(canvas, e);
context.strokeStyle = 'blue';
context.strokeRect(start.x, start.y, x - start.x, y - start.y);
mouseDown = false;
}
function drawSquare(e) {
if (!mouseDown) return;
// creating a square
var width = Math.abs(start.x - canvas.getBoundingClientRect().offsetLeft);
var height = Math.abs(start.y - canvas.getBoundingClientRect().offsetLeft);
context.beginPath();
context.rect(start.x, start.y, width, height);
context.strokeStyle = 'blue';
context.stroke();
}
window.addEventListener('mouseup', endRect);
window.addEventListener('mousemove', drawSquare);
/**End Drawing a rectangle on the canvas **/
</script>
</body>
</html>
Upvotes: 2
Views: 1385
Reputation: 17584
We need to make something different, instead of drawing on the fly we need to add the rectangles to an array, then clean the canvas and draw them on demand, that way we can also draw additional elements, on the sample below I draw a red rectangle while moving and blue ones once we release the mouse
var canvas = document.getElementById('myCanvas')
var context = canvas.getContext('2d')
let start = {}
let rects = [{x: 9, y: 9, width: 50, height: 30}]
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect()
return {
x: (evt.clientX - rect.left) * canvas.width / rect.width,
y: (evt.clientY - rect.top) * canvas.height / rect.height,
};
}
function startRect(e) {
start = getMousePos(canvas, e);
}
function endRect(e) {
let { x, y } = getMousePos(canvas, e)
rects.push({x: start.x, y: start.y, width: x - start.x, height: y - start.y})
start = {}
draw()
}
function draw() {
context.clearRect(0, 0, canvas.width, canvas.height)
rects.forEach(rect => {
context.beginPath();
context.rect(rect.x, rect.y, rect.width, rect.height);
context.strokeStyle = 'blue';
context.stroke();
});
}
function drawMove(e) {
if (start.x) {
draw()
let { x, y } = getMousePos(canvas, e)
context.beginPath();
context.rect(start.x, start.y, x - start.x, y - start.y);
context.strokeStyle = 'red';
context.stroke();
context.beginPath();
context.arc(start.x, start.y, 5, 0, 2 * Math.PI);
context.fill();
context.beginPath();
context.arc(x, y, 5, 0, 2 * Math.PI);
context.fill();
}
}
draw()
window.addEventListener('mouseup', endRect)
window.addEventListener('mousedown', startRect)
window.addEventListener('mousemove', drawMove)
canvas { border: solid }
<canvas id="myCanvas" width="400" height="400"></canvas>
Upvotes: 5