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 switch
instead 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:
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.
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"