Skip to content Skip to sidebar Skip to footer

Html5 Canvas Paint Redrawing Linejoin Not Rounded

Hello i make like a paint with undo function, i write all coordinates in array and then try undo just redrawing without last coordinates but problem while i redrawing my canvas par

Solution 1:

I think that you're looking for ctx.lineCap property. + I modified your redraw function to use a switchinstead of your confusing if statements :

function redraw() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.lineCap = "round";
        ctx.beginPath();

        for(var i=0; i < points.length; i++) {
            var pt = points[i];                
            switch(pt.mode){
                    case"begin" : ctx.moveTo(pt.x, pt.y); 
                    case"draw" : ctx.lineTo(pt.x, pt.y);
                    case"end" : ctx.stroke();
            }
        }
}

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var points = [];
var size = 10;
var prevX = 0;
var prevY = 0;
var isCanDraw = false;
var rect = canvas.getBoundingClientRect();

$("#canvas").on("mousedown", function(e) {
  isCanDraw = true;

  prevX = e.clientX;
  prevY = e.clientY;
  
  points.push({
    x: prevX,
    y: prevY,
    size: size,
    mode: "begin"
  });
  ctx.beginPath();
  ctx.arc(prevX, prevY, size/2, 0, Math.PI*2);
  ctx.fill();
});

$("#canvas").on("mousemove", function(e) {
  if (isCanDraw) {
    stroke(e.clientX - rect.left, e.clientY - rect.top);
    points.push({
      x: prevX,
      y: prevY,
      size: size,
      mode: "draw"
    });
  }
});

$("#canvas").on("mouseup", function(e) {
  isCanDraw = false;
  points.push({
    x: prevX,
    y: prevY,
    size: size,
    mode: "end"
  });
});

$("#canvas").on("mouseleave", function(e) {
  isCanDraw = false;
});

$("#undo").on("click", function(e) {
  deleteLast();
  redraw();
});

functiondeleteLast() {
  if (points.length != 0) {
    var i = points.length - 1;
    while (points[i].mode != "begin") {
      i--;
      points.pop();
    }
    points.pop();
  }
}

functionredraw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.lineCap = "round";
  ctx.beginPath();

  for (var i = 0; i < points.length; i++) {
    var pt = points[i];
    switch (pt.mode) {
      case"begin":
        ctx.moveTo(pt.x, pt.y);
      case"draw":
        ctx.lineTo(pt.x, pt.y);
      case"end":
        ctx.stroke();
    }
  }
}


functionstroke(x, y) {
  ctx.lineWidth = size;
  ctx.lineJoin = "round";

  ctx.beginPath();
  ctx.moveTo(prevX, prevY);
  ctx.lineTo(x, y);
  ctx.closePath();
  ctx.stroke();
  prevX = x;
  prevY = y;
}
// debounce our rect update funcvar scrolling = false;
functionscrollHandler(){
  rect = canvas.getBoundingClientRect();
  scrolling = false;
  }
$(window).on('scroll resize', function(e){
  if(!scrolling){
    requestAnimationFrame(scrollHandler);
    }
 });
#canvas {
  border: 1px solid #000;
}
<scriptsrc="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script><canvasid="canvas"width="500"height="300"></canvas><inputtype="button"id="undo"value="undo">

Solution 2:

@Kaiido answers correctly that applying lineCap='round' will round the ends of your redrawn line.

Two further thoughts:

  1. You should account for your canvas's offset position from the top-left corner of the document. Otherwise your prevX & prevY positions will be slightly off if the canvas is not on the top-left of the document.

  2. You will have a more crisp line (less "bulgy") if you allow only the beginning and ending linecaps to be rounded and all the interim linecaps to be butted. Leave the linejoins as the default of mitered.

Here's example code and a Demo:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;

var points = []; 
var size = 10;
var prevX = 0;
var prevY = 0;
var isCanDraw = false;

$("#canvas").on("mousedown", function(e) {
  isCanDraw = true;

  prevX = e.clientX-offsetX;
  prevY = e.clientY-offsetY;
  points.push({x: prevX, y: prevY, size: size, mode: "begin"});
});

$("#canvas").on("mousemove", function(e) {
  if(isCanDraw) {
    stroke(e.clientX-offsetX, e.clientY-offsetY);
    points.push({x: prevX, y: prevY, size: size, mode: "draw"});
  }     
});

$("#canvas").on("mouseup", function(e) {
  isCanDraw = false;  
  points.push({x: prevX, y: prevY, size: size, mode: "end"});
});

$("#canvas").on("mouseleave", function(e) {
  isCanDraw = false; 
});

$("#undo").on("click", function(e) {
  deleteLast();
  redraw();
});

functiondeleteLast() {
  if(points.length != 0) {
    var i = points.length - 1;
    while(points[i].mode !== "begin") {
      i--; 
      points.pop();
    }
    points.pop();
  }
}


functionredraw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);

  var savedFillStyle=ctx.fillStyle;
  ctx.fillStyle=ctx.strokeStyle;

  var i=0;
  while(i<points.length){

    var p=points[i];

    // draw "begin" as circle instead of line
    ctx.beginPath();
    ctx.arc(p.x,p.y,p.size/2,0,Math.PI*2);
    ctx.closePath();
    ctx.fill();

    // draw "draw"
    ctx.lineWidth=p.size;
    ctx.beginPath();
    ctx.moveTo(p.x,p.y);
    i++;
    while(i<points.length && points[i].mode!='end'){
      var p=points[i];
      ctx.lineTo(p.x,p.y);
      i++;
    }
    ctx.stroke();

    // draw "end" as circle instead of linevar p=points[i];
    ctx.beginPath();
    ctx.arc(p.x,p.y,p.size/2,0,Math.PI*2);
    ctx.closePath();
    ctx.fill();

    i++;
  }

  ctx.fillStyle=savedFillStyle;

}

functionstroke(x,y) {
  ctx.lineWidth = size;
  ctx.lineJoin = "round";

  ctx.beginPath();
  ctx.moveTo(prevX, prevY);
  ctx.lineTo(x, y);
  ctx.closePath();
  ctx.stroke();
  prevX = x;
  prevY = y;
}
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
<scriptsrc="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script><canvasid="canvas"width="500"height="300"></canvas><inputtype="button"id="undo"value="undo"></body>

Post a Comment for "Html5 Canvas Paint Redrawing Linejoin Not Rounded"