I've been trying to draw smooth lines on my canvas but I've had no luck. I've tried setting the lineCap to round, using quadratic instead of lineTo, but nothing worked.
While the mouse moves, it records the position of the mouse into an array and then runs through the array to draw the lines.
**JavaScript**
// GLOBAL VARIABLES - CONTAINER/CANVAS
var wContainer = document.getElementById('Whiteboard_Container');
var layerGrid = document.getElementById('LayerGrid');
var lgctx = layerGrid.getContext('2d');
var layer1 = document.getElementById('Layer1');
var l1ctx = layer1.getContext('2d');
// GLOBAL VARIABLES - MOUSE/TOUCH
var cursorPos = { top: 0, left: 0, x: 0, y: 0 };
var cursorType = 'mouse'; // USED TO CONTROL MOUSE/TOUCH
var dragging = false; // SETS/STOPS DRAGGING CANVAS
var dragLock = false; // USED TO PREVENT ACCIDENTAL DRAGGING (esp. touch)
// GLOBAL VARIABLES - DRAWING
var layer = 'LAYER1';
var vectors = [];
// MOUSE EVENT LISTENERS
layer1.addEventListener('mousedown', mouseDown);
layer1.addEventListener('mouseup', mouseUp);
// TOUCH EVENT LISTENERS
layer1.addEventListener('touchstart', touchDown);
layer1.addEventListener('touchend', touchUp);
// INITIALISER
function init()
{
resize();
// SET PEN STYLE
lgctx.strokeStyle = 'rgba(230, 230, 230, 1)';
lgctx.lineWidth = 1;
lgctx.lineCap = 'round';
lgctx.lineJoin = 'round';
// SET PEN STYLE
l1ctx.strokeStyle = 'rgba(0, 0, 0, 1)';
l1ctx.lineWidth = 10;
l1ctx.lineCap = 'round';
l1ctx.lineJoin = 'round';
}
init();
// AUTO SIZE THE CANVAS
function resize()
{
// SET THE CANVAS SIZE
layerGrid.width = window.innerWidth * 4;
layerGrid.height = window.innerHeight * 4;
layer1.height = window.innerHeight * 4;
layer1.width = window.innerWidth * 4;
layer1.height = window.innerHeight * 4;
}
// MOUSE DOWN
function mouseDown(e)
{
// Set cursor type
cursorType = 'mouse';
// EMPTY CURRENT VECTOR LIST
vectors = [];
vectors.length = 0;
if(e.button == 0) // LEFT MOUSE CLICK
{
layer1.addEventListener('mousemove', setVectors);
}
else if(e.button == 2 && dragLock == false) // RIGHT MOUSE CLICK
{
dragging = true;
layer1.addEventListener('mousemove', canvasDrag);
// SET START SCROLL POSITION
cursorPos.top = wContainer.scrollTop;
cursorPos.left = wContainer.scrollLeft;
// SET CURSOR POSITION
cursorPos.x = e.clientX;
cursorPos.y = e.clientY;
}
}
// MOUSE UP
function mouseUp(e)
{
// PREVENT DRAGGING & REMOVE GRID
dragging = false;
layer1.removeEventListener('mousemove', canvasDrag);
layer1.removeEventListener('mousemove', setVectors);
removeGrid();
}
// TOUCH DOWN
function touchDown(e)
{
e.preventDefault();
// Set cursor type
cursorType = 'touch';
// EMPTY CURRENT VECTOR LIST
vectors = [];
vectors.length = 0;
if(e.touches.length == 1) // SINGLE TOUCH
{
layer1.addEventListener('touchmove', setVectors);
}
else if(e.touches.length > 1 && dragLock == false) // MULTI-TOUCH
{
dragging = true;
layer1.addEventListener('touchmove', canvasDrag);
// SET START SCROLL POSITION
cursorPos.top = wContainer.scrollTop;
cursorPos.left = wContainer.scrollLeft;
// SET CURSOR POSITION
cursorPos.x = e.touches[0].clientX;
cursorPos.y = e.touches[0].clientY;
}
}
// TOUCH UP
function touchUp(e)
{
// PREVENT DRAGGING & REMOVE GRID
dragging = false;
layer1.removeEventListener('mousemove', canvasDrag);
layer1.removeEventListener('touchmove', setVectors);
removeGrid();
}
// HANDLE MOVEMENT
function canvasDrag(e)
{
if(dragging == true && cursorType == 'mouse') // MOUSE DRAG
{
// DRAW GRID AS GUIDANCE
drawGrid();
const dx = e.clientX - cursorPos.x;
const dy = e.clientY - cursorPos.y;
wContainer.scrollTop = cursorPos.top - dy;
wContainer.scrollLeft = cursorPos.left - dx;
}
else if(dragging == true && cursorType == 'touch' && e.touches.length > 1) // TOUCH DRAG
{
// DRAW GRID AS GUIDANCE
drawGrid();
const dx = e.touches[0].clientX - cursorPos.x;
const dy = e.touches[0].clientY - cursorPos.y;
wContainer.scrollTop = cursorPos.top - dy;
wContainer.scrollLeft = cursorPos.left - dx;
}
}
// SET VECTORS
function setVectors(e)
{
if(cursorType == 'mouse') // MOUSE DRAW
{
// Set the drawing vectors
vectors.push({x:e.clientX + wContainer.scrollLeft, y:e.clientY + wContainer.scrollTop});
}
else if(cursorType == 'touch' && e.touches.length == 1) // ONLY ALLOW IF SINGLE TOUCH
{
// Set the drawing vectors
vectors.push({x:e.touches[0].clientX + wContainer.scrollLeft, y:e.touches[0].clientY + wContainer.scrollTop});
}
// Draw the path, based on the vectors array
drawVectors();
}
// DRAW VECTORS
function drawVectors()
{
l1ctx.beginPath();
//l1ctx.clearRect(0, 0, layer1.width, layer1.height);
for(var i = 0; i < vectors.length - 2; i++)
{
var xc = (vectors[i].x + vectors[i + 1].x) / 2;
var yc = (vectors[i].y + vectors[i + 1].y) / 2;
l1ctx.quadraticCurveTo(vectors[i].x, vectors[i].y, xc, yc);
//l1ctx.lineTo(vectors[i].x, vectors[i].y);
}
l1ctx.stroke();
}
// DRAW GRID
function drawGrid()
{
lgctx.beginPath();
for(var i = 0; i < layer1.width; i = i + 100)
{
lgctx.moveTo(i, 0);
lgctx.lineTo(i, layer1.height);
}
lgctx.moveTo(0, 0);
for(var i = 0; i < layer1.height; i = i + 100)
{
lgctx.moveTo(0, i);
lgctx.lineTo(layer1.width, i);
}
lgctx.stroke();
lgctx.closePath();
}
// REMOVE GRID
function removeGrid()
{
lgctx.clearRect(0, 0, layerGrid.width, layerGrid.height);
}
The first line is how its drawn, the second is how I'm trying to get it to appear: Line comparison
You never clear your l1ctx
context.
So you are always drawing new lines over the previous ones and killing the antialiasing.
Simply add a clearRect
call at the beginning of drawVectors
.