Reputation: 1363
Reading related articles, I've tried forcing the canvas size in pixels, specifying half pixels for the paths and also context.translate(0.5) but my canvas lines are still blurry.
const boxContainer = document.querySelector('.boxes');
const canvas = document.getElementById("canvas");
canvas.width = boxContainer.offsetWidth * 2;
canvas.height = boxContainer.offsetHeight * 2;
canvas.style.width = boxContainer.offsetWidth + 'px';
canvas.style.height = boxContainer.offsetHeight + 'px';
const ctx = canvas.getContext("2d");
ctx.scale(2, 2);
/* Function to draw HTML5 canvas line */
const drawPath = (startX, startY, endX, endY) => {
ctx.beginPath();
ctx.lineWidth = "1";
ctx.strokeStyle = "red";
ctx.moveTo(startX, startY);
ctx.lineTo(endX, endY);
ctx.stroke();
};
/* Return coords for different points of element */
const getCoords = (elem, corner) => {
let coords = {};
switch (corner) {
case 'bottomRight':
coords.x = elem.offsetLeft + elem.offsetWidth;
coords.y = elem.offsetTop + elem.offsetHeight;
break;
case 'bottomLeft':
coords.x = elem.offsetLeft;
coords.y = elem.offsetTop + elem.offsetHeight;
break;
case 'topRight':
coords.x = elem.offsetLeft + elem.offsetWidth;
coords.y = elem.offsetTop;
break;
case 'topLeft':
coords.x = elem.offsetLeft;
coords.y = elem.offsetTop;
break;
}
return coords;
};
/* Get coords for all points */
let boxData = {};
let boxes = document.querySelectorAll('.box');
boxes.forEach((boxElem, index) => {
boxData['box' + parseInt(index + 1)] = {
x: getCoords(boxElem, boxElem.getAttribute('data-path-point')).x,
y: getCoords(boxElem, boxElem.getAttribute('data-path-point')).y
};
});
/* Start the drawing! */
drawPath(boxData.box1.x, boxData.box1.y,
boxData.box4.x, boxData.box4.y);
drawPath(boxData.box2.x, boxData.box2.y,
boxData.box3.x, boxData.box3.y);
.boxes {
max-width: 500px;
position: relative;
}
.box {
display: inline-block;
width: 120px;
margin-left: 10%;
margin-bottom: 10%;
padding: 20px;
border: 1px solid red;
}
#canvas {
position: absolute;
top: 0;
left: 0;
pointer-events: none;
}
<div class="boxes">
<canvas id="canvas"></canvas>
<div data-path-point="bottomRight" id="box1" class="box box-pair1">a<br>b<br>x<br>y<br>z<br></div>
<div data-path-point="bottomLeft" id="box2" class="box box-pair2">x<br>y<br>z<br></div>
<div data-path-point="topRight" id="box3" class="box box-pair2">x<br>y<br>z<br></div>
<div data-path-point="topLeft" id="box4" class="box box-pair1">x<br>y<br>z<br></div>
</div>
Where am I going wrong and how can I make my lines crisp like the border around the boxes in the demo?
Upvotes: 4
Views: 3947
Reputation: 54069
Looking at the image you supplied. The canvas is half the resolution of the display. Zoom in and look at the pixels on the "X", The DOM line is 1px yet still twice a wide as the pixels on that letter. That means the canvas is being stretched and the blur is due to the bilinear filtering. Either you are zoomed out on the tab or you have a retina or HiDPI display. Set the canvas.width
& canvas.height
to twice what it is, set the canvas.style.width
& canvas.style.height
to DOM pixels. Remove the ctx.translate
and add ctx.scale(2,2)
and all things will be clear.
A zoom in on the image
Upvotes: 8