0
votes

I am drawing rectangles on a canvas using mouse. However, I want to activate the mouse action to draw the rectangles only when key d is pressed on the key board.

If I use

if (event.ctrlKey) {
 //draw rectangles
} 

I am able to draw by holding the ctrlKey on the keyboard. However, if I use

if (e.which == 88) {
 //draw rectangles
}

it doesn't work. I am not able to bind the keyboard keypress events to mouse events on a canvas. I understand canvas element does not have onKeyPress event and as suggested in some of the blogs, I tried the following code, which doesn't work. Can someone help to get me started?

I have many events for which I have to bind the keyboard press event on the canvas.

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <title>parallelogram</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>

<body>
    <canvas id="canvas" width="800" height="600" style="border:solid 1px;margin:0;padding:0;;z-index:1"></canvas>
</body>

</html>

<script type="text/javascript">
var canvas, context;
var dragging = false;
var startLocation;
var dragStartLocation;
var dragStopLocation;
var dragThirdLocation;
var snapshot;
var coords = [];
var pointsNum = 0;
var d = {
    x: 0,
    y: 0
};

//Get mouse click coordinates
function getCanvasCoordinates(event)
{
    var x = event.clientX - canvas.getBoundingClientRect().left;
    var y = event.clientY - canvas.getBoundingClientRect().top;
    return {
        x: x,
        y: y
    };
}

//save the canvas original state
function takeSnapShot()
{
    snapshot = context.getImageData(0, 0, canvas.width, canvas.height);
}

//restore the canvas original state
function restoreSnapShot()
{
    context.putImageData(snapshot, 0, 0);
}

//draw a point on mouse click
function drawPoint(position)
{
    context.beginPath();
    context.arc(position.x, position.y, 5.5, 0, Math.PI * 2, false);
    context.stroke();
}

//draw a line on mouse move
function drawLine(start, end)
{
    context.beginPath();
    context.moveTo(start.x, start.y);
    context.lineTo(end.x, end.y);
    context.stroke();
}

//start the event with first mouse click
function dragStart(event)
{
    dragging = true;
    dragStartLocation = getCanvasCoordinates(event);
    coords['imageClicked'] = localStorage.getItem('clickedImage');
    console.log(coords);
    var brandNode = localStorage.getItem('brandNode');
    var locationNode = localStorage.getItem('locationNode');
    drawPoint(dragStartLocation);
    pointsNum++;
    takeSnapShot();
    if (pointsNum == 1) startLocation = dragStartLocation;
}

//draw a line along with the mouse move from the first click
function drag(event)
{
    var position;
    if (snapshot && pointsNum && pointsNum < 3)
    {
        restoreSnapShot();
        position = getCanvasCoordinates(event);
        drawLine(dragStartLocation, position);
        drawPoint(position);
        if (pointsNum == 2) drawFourthCoord(position)

    }
}

//stop the mouse movement and drawing line.
function dragStop(event)
{
    dragging = false;
    restoreSnapShot();
    var position = getCanvasCoordinates(event);
    dragStopLocation = position;
    drawPoint(dragStopLocation);
    pointsNum++;
    drawLine(dragStartLocation, dragStopLocation);
    takeSnapShot();
    d = {
        x: dragStartLocation.x - dragStopLocation.x,
        y: dragStartLocation.y - dragStopLocation.y
    };

    dragStartLocation = position;
    console.log(dragStartLocation);
    if (pointsNum > 3) pointsNum = 0;
}

//draw the fourth coordinate
function drawFourthCoord(position)
{
    var p = {
        x: position.x + d.x,
        y: position.y + d.y
    };
    drawLine(position, p);
    drawPoint(p);
    drawLine(startLocation, p);
}

/*
  This code works...but does not have binding to keyCode x
  function init() {
  canvas = document.getElementById('canvas');
  context = canvas.getContext('2d');
  context.lineCap = "round";
  context.lineWidth = 3;
  context.strokeStyle = '#f4d03f';
  canvas.addEventListener('mousedown', dragStart, false);
  canvas.addEventListener('mousemove', drag, false);
  canvas.addEventListener('mouseup', dragStop, false);  

}

window.addEventListener('load', init, false);
*/

var canvaskey = document.getElementById('canvas');
canvaskey.addEventListener('keydown', doKeyDown, true);

function doKeyDown(e)
{
    if (e.which == 88)
    {
        canvas = document.getElementById('canvas');
        context = canvas.getContext('2d');
        context.lineCap = "round";
        context.lineWidth = 3;
        context.strokeStyle = '#f4d03f';
        canvas.addEventListener('mousedown', dragStart, false);
        canvas.addEventListener('mousemove', drag, false);
        canvas.addEventListener('mouseup', dragStop, false);
    }
}
</script>
1

1 Answers

1
votes

Simply hold a semaphor variable in the scope your drawing functions have access to.

On keydown of required key, set it to true, on keyup to false.
In the draw function, check the semaphor is set to true, otherwise, return promptly.

// our keydown semaphor
var d_down = false;

function doKeyDown(e)
{
    if (e.key == "d")
    {
      d_down = true;
    }
}
function doKeyUp(e)
{
    if (e.key == "d")
    {
      d_down = false;
    }
}


var canvas, context;
var dragging = false;
var startLocation;
var dragStartLocation;
var dragStopLocation;
var dragThirdLocation;
var snapshot;
var coords = [];
var pointsNum = 0;
var d = {
    x: 0,
    y: 0
};

//Get mouse click coordinates
function getCanvasCoordinates(event)
{
    var x = event.clientX - canvas.getBoundingClientRect().left;
    var y = event.clientY - canvas.getBoundingClientRect().top;
    return {
        x: x,
        y: y
    };
}

//save the canvas original state
function takeSnapShot()
{
    snapshot = context.getImageData(0, 0, canvas.width, canvas.height);
}

//restore the canvas original state
function restoreSnapShot()
{
    context.putImageData(snapshot, 0, 0);
}

//draw a point on mouse click
function drawPoint(position)
{
    context.beginPath();
    context.arc(position.x, position.y, 5.5, 0, Math.PI * 2, false);
    context.stroke();
}

//draw a line on mouse move
function drawLine(start, end)
{
    context.beginPath();
    context.moveTo(start.x, start.y);
    context.lineTo(end.x, end.y);
    context.stroke();
}

//start the event with first mouse click
function dragStart(event)
{
  // check our semaphor
  if(!d_down)
    return; // we're not allowed to go farther
    
    dragging = true;
    dragStartLocation = getCanvasCoordinates(event);
/*    coords['imageClicked'] = localStorage.getItem('clickedImage');
    console.log(coords);
    var brandNode = localStorage.getItem('brandNode');
    var locationNode = localStorage.getItem('locationNode');*/
    drawPoint(dragStartLocation);
    pointsNum++;
    takeSnapShot();
    if (pointsNum == 1) startLocation = dragStartLocation;
}

//draw a line along with the mouse move from the first click
function drag(event)
{
  // check our semaphor
  if(!d_down)
    return; // we're not allowed to go farther
    var position;
    if (snapshot && pointsNum && pointsNum < 3)
    {
        restoreSnapShot();
        position = getCanvasCoordinates(event);
        drawLine(dragStartLocation, position);
        drawPoint(position);
        if (pointsNum == 2) drawFourthCoord(position)

    }
}

//stop the mouse movement and drawing line.
function dragStop(event)
{
    dragging = false;
  // check our semaphor
  if(!d_down)
    return; // we're not allowed to go farther
    restoreSnapShot();
    var position = getCanvasCoordinates(event);
    dragStopLocation = position;
    drawPoint(dragStopLocation);
    pointsNum++;
    drawLine(dragStartLocation, dragStopLocation);
    takeSnapShot();
    d = {
        x: dragStartLocation.x - dragStopLocation.x,
        y: dragStartLocation.y - dragStopLocation.y
    };

    dragStartLocation = position;
//    console.log(dragStartLocation);
    if (pointsNum > 3) pointsNum = 0;
}

//draw the fourth coordinate
function drawFourthCoord(position)
{
    var p = {
        x: position.x + d.x,
        y: position.y + d.y
    };
    drawLine(position, p);
    drawPoint(p);
    drawLine(startLocation, p);
}

  function init() {
  canvas = document.getElementById('canvas');
  context = canvas.getContext('2d');
  context.lineCap = "round";
  context.lineWidth = 3;
  context.strokeStyle = '#f4d03f';
  canvas.addEventListener('mousedown', dragStart, false);
  canvas.addEventListener('mousemove', drag, false);
  canvas.addEventListener('mouseup', dragStop, false); 
  snapshot = context.createImageData(1,1)

}

window.addEventListener('load', init, false);

var canvaskey = document.getElementById('canvas');
canvaskey.addEventListener('keydown', doKeyDown);
canvaskey.addEventListener('keyup', doKeyUp);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<canvas id="canvas" width="800" height="600" style="border:solid 1px;margin:0;padding:0;;z-index:1" tabindex="1"></canvas>