Deepak S Rautela
Deepak S Rautela

Reputation: 77

Draw polygons of fixed sides with mouse on canvas

I am trying to draw polygons(lets say 4 sided) on a canvas using mouse click and move events.

  1. Click on canvas the moveTo(this point).
  2. Now move the cursor a lineTo(the current point) but not intermediate point. Line should keep moving with mousemove and should be draw to the canvas only once clicked.
  3. After fourth click(or any x) the polygon should closepath();

    var pressed = false;

    function myfunc1(e){
        context.beginPath();
        context.arc(e.clientX, e.clientY, radius, 0, Math.PI*2);
        context.fill();
        context.beginPath();
        context.moveTo(e.clientX,e.clientY);
        pressed = true; 
    }
    
    function myfunc2(e){    
        if(pressed ===true){    
        context.lineTo(e.clientX,e.clientY);
        context.stroke();    
        }
    }    
    canvas.addEventListener('click',myfunc1);
    canvas.addEventListener('mousemove',myfunc2);
    

I wrote this, but i don't want the intermediate lines

Upvotes: 0

Views: 2319

Answers (3)

Deepak S Rautela
Deepak S Rautela

Reputation: 77

I created an array(cords[]) which holds the coordinates of the polygon i am drawing and push them to another array (polygons[]) if the current polygon is completed. Then i can clear the canvas when required and redraw the polygons from polygon[]

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = document.getElementById("myimg");
ctx.drawImage(img, 0, 0);
var canvasOffset = $("#canvas").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var polygons = [];
var cords = [];
var start = false;
var control = false;
var clicks = 0;

ctx.strokeStyle = "orange";
ctx.lineWidth = 1;

$("#canvas").mousedown(function(e) {
  handleMouseDown(e);
});
$("#canvas").mousemove(function(e) {
  handleMouseMove(e);
});


function handleMouseDown(e) {
  start = false;
  clicks = clicks + 1;

  var mouseX = parseInt(e.clientX - offsetX);
  var mouseY = parseInt(e.clientY - offsetY);

  cords.push([mouseX, mouseY]);
  console.log(cords);
  clearanddraw();

  if (clicks % 4 === 0) {
    return;
  }
  
  start = true;
}

function handleMouseMove(e) {
  if (!start) {
    return;
  }

  canvasclear();

  var mouseX = parseInt(e.clientX - offsetX);
  var mouseY = parseInt(e.clientY - offsetY);

  ctx.beginPath();
  ctx.moveTo(cords[clicks - 1][0], cords[clicks - 1][1]);
  ctx.lineTo(mouseX, mouseY);
  ctx.stroke();
}

function canvasclear() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(myimg, 0, 0);
  drawOtherPol();
  ctx.beginPath();
  ctx.moveTo(cords[0][0], cords[0][1]);

  for (var i = 0; i < clicks - 1; i++) {
    ctx.lineTo(cords[i + 1][0], cords[i + 1][1]);
    //alert("redrwan");
  }
  ctx.stroke();
  return;

}

function clearanddraw() {
  if (clicks > 1) {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.drawImage(myimg, 0, 0);
    drawOtherPol();
    ctx.beginPath();
    ctx.moveTo(cords[0][0], cords[0][1]);
    
    for (var i = 0; i < clicks - 1; i++) {
      ctx.lineTo(cords[i + 1][0], cords[i + 1][1]);
    }
    
    if (clicks < 4) {
      ctx.stroke();
    }
    if (clicks === 4) {
      ctx.closePath();
      ctx.stroke();
      savepolygon();
      cords = [];
      clicks = 0;
      return;
    }
  }
  start = true;
}

function savepolygon() {
  polygons.push(cords);
  console.log(polygons);
  return
}

function drawOtherPol() {
  if (polygons.length === 0) {
    return;
  } else {
    for (var i = 0; i < polygons.length; i++) {
      ctx.beginPath();
      ctx.moveTo(polygons[i][0][0], polygons[i][0][1]);
      ctx.lineTo(polygons[i][1][0], polygons[i][1][1]);
      ctx.lineTo(polygons[i][2][0], polygons[i][2][1]);
      ctx.lineTo(polygons[i][3][0], polygons[i][3][1]);
      ctx.closePath();
      ctx.stroke();
    }
    return;
  }
}

Upvotes: 0

Kevin Martin Jose
Kevin Martin Jose

Reputation: 640

What you need is a stack. Don't think of drawing lines. Think of storing all your points of click in an array. And when you have clicked 4 times, draw the polygon (assuming that is what you want). Something like this:

var stack = [];

myfunc1(e){

    stack.push(e.clientX, e.clientY);

    if(stack.length == 4)
        actuallyDraw();
}

var actuallyDraw(){
    //take the 4 points in stack and draw the polygon

    //clearing the stack for the next polygon
    stack.length = 0; 
}

canvas.addEventListener('click', myfunc1);

Upvotes: 1

user5346455
user5346455

Reputation:

Use below code it will help you to solve your problem.

Click to assign polygon vertices point

<button id=done>Click when done assigning points</button>
<canvas id="canvas" width=450 height=450></canvas>

var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
  var BB=canvas.getBoundingClientRect();
  offsetX=BB.left;
  offsetY=BB.top;        
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }

context.lineWidth=2;
context.strokeStyle='blue';

var coordinates = [];
var isDone=false;

$('#done').click(function(){
  isDone=true;
});

$("#canvas").mousedown(function(e){handleMouseDown(e);});

function handleMouseDown(e){
  if(isDone || coordinates.length>10){return;}

  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();

  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);
  coordinates.push({x:mouseX,y:mouseY});
  drawPolygon();
}

function drawPolygon(){
  context.clearRect(0,0,cw,ch);
  context.beginPath();
  context.moveTo(coordinates[0].x, coordinates[0].y);
  for(index=1; index<coordinates.length;index++) {
    context.lineTo(coordinates[index].x, coordinates[index].y);
  }
  context.closePath();
  context.stroke();
}

Upvotes: 0

Related Questions