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>
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?
How it appears for me:
Share Improve this question edited Sep 11, 2023 at 13:35 Lee Taylor 7,98416 gold badges37 silver badges53 bronze badges asked Oct 9, 2016 at 12:40 tctc91tctc91 1,3632 gold badges21 silver badges41 bronze badges 5- Works fine for me in Chrome imgur./a/515dZ – tctc91 Commented Oct 9, 2016 at 12:48
- yes sorry working in chrome may be not in fx – Madhawa Priyashantha Commented Oct 9, 2016 at 12:48
-
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 the letter. That means the canvas is being stretched and the blur is due to the bilinear filtering. Either you are zoomed on the tab or you have a retina display. Set the
canvas.width
& height to twice what it is, set thecanvas.style.width
& height to DOM pixels. Remove thectx.translate
and addctx.scale(2,2)
and all things will be clear. – Blindman67 Commented Oct 9, 2016 at 15:14 - Thanks, that solved it. Make that an answer and I'll accept :) – tctc91 Commented Oct 9, 2016 at 15:56
- @Blindman67. ... and from the image only(!) -- bravo! – markE Commented Oct 9, 2016 at 22:37
1 Answer
Reset to default 8Retina & HiDPI devices
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