Reputation: 369
Hi guys I have been comparing drawing lines on canvases between two different functions. I realise the lines drawn between the two functions are different but the code logic of the two functions seems to be exactly the same(to me).
The code:
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var radius = 10;
var dragging = false;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
context.lineWidth = radius*2;
var putPoint = function(e){
if(dragging){
context.lineTo(e.clientX, e.clientY);
context.stroke();
}
}
var engage = function(e){
dragging = true;
putPoint(e);
}
var disengage = function(){
dragging = false;
context.beginPath();
}
canvas.addEventListener('mousedown', engage);
canvas.addEventListener('mousemove', putPoint);
canvas.addEventListener('mouseup', disengage);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Canvas</title>
</head>
<body style="margin:0">
<canvas style="display:block;" id="canvas">
sorry this browser does not support HTML 5 Canvas!
</canvas>
<script src="main.js"></script>
</body>
</html>
The line drawn from the above function:
If I modify the above function putPoint()
to the following:
var putPoint = function(e){
if(dragging){
context.lineTo(e.clientX, e.clientY);
context.stroke();
context.beginPath();
context.moveTo(e.clientX, e.clientY);
}
}
The line changes to this:
I don't understand why the two lines in any way should differ(even though it does).
var putPoint = function(e){
if(dragging){
context.lineTo(e.clientX, e.clientY);
context.stroke();
}
}
This function draws a much smoother line than the later as every time the function is called a line will be drawn from (x,y) of the previous function's coordinates to the (x,y) of the next functions's coordinates when it is called.
var putPoint = function(e){
if(dragging){
context.lineTo(e.clientX, e.clientY);
context.stroke();
context.beginPath();
context.moveTo(e.clientX, e.clientY);
}
}
This function appears to be the same to me as moveTo(x,y)
would store the latest (x,y) coordinates. When lineTo(x,y)
is called a line between the coordinates of moveTo(x,y)
and lineTo(x,y)
will be drawn. This seems to be exactly the same to me as the the first function although different lines are drawn.
Please explain?
Upvotes: 1
Views: 719
Reputation: 54128
It is because in the second example the lines are not joined. The rending API has special code to fill in the gaps that are created when rendering thick curvy lines, by cheating lots od small paths you do not allow this code to do its thing.
Controlling stroke rendering.
You can control the line joining with the property ctx.lineJoin
which can be round
, miter
, and 'bevel' if you use miter (pointy corners) you can control how far the mitering sticks out on sharp corners by setting the value of ctx.miterLimit
to the number of pixels that it should not go past.
You can also control the line ends with ctx.lineCap
property which can have on of butt
,round
, and square
Butt has a flat end that stops at the coordinates of the start and end of the line. square add half the line width to the start and end of the line.
Fixing the gaps
To fix your line problem set the ctx.lineCap = "round"
which adds a half circle to the start and end of each path segment. The circle is the same diameter as the line width. This will fill in the gaps you are seeing in the second line example.
Upvotes: 1