I’m trying to make a very simple paint in JS but I have a problem when I increase the line width it create weird shape at the end of shape but not when I use a lineWidth = 1 and I don’t know where the problem come from furthermore it create space between lines while with a lineWidth=1 I don’t have that problem
this is my code :
JavaScript
x
106
106
1
class Board{
2
constructor(canvas) {
3
this.canvas = canvas;
4
this.ctx = this.canvas.getContext("2d");
5
this.isDrawing = false;
6
this.mousePosition = {
7
x: 0,
8
y: 0
9
};
10
this.color = "black";
11
this.rect = this.canvas.getBoundingClientRect();
12
this.lineWidth = 15;
13
this.height = 0;
14
this.width = 0;
15
16
this.initBoard();
17
// this.test();
18
// this.checkIfFill = this.checkIfFill.bind(this)
19
}
20
21
initBoard() {
22
this.renderCanvas();
23
24
window.addEventListener("resize", () => {
25
this.renderCanvas();
26
});
27
28
this.canvas.addEventListener("mousedown", (e) => {
29
this.mousePosition = {
30
x: e.clientX - this.rect.left,
31
y: e.clientY - this.rect.top
32
};
33
34
this.isDrawing = true;
35
});
36
37
this.canvas.addEventListener("mousemove", (e) => {
38
if (this.isDrawing) {
39
this.draw((e.clientX - this.rect.left), (e.clientY - this.rect.top));
40
this.mousePosition = {
41
x: e.clientX - this.rect.left,
42
y: e.clientY - this.rect.top
43
};
44
}
45
});
46
47
this.canvas.addEventListener("mouseup", () => {
48
this.isDrawing = false;
49
});
50
}
51
52
renderCanvas() {
53
const drawingTools = document.querySelector(".drawing-tools");
54
const dpr = window.devicePixelRatio;
55
this.height = document.body.offsetHeight - drawingTools.offsetHeight;
56
this.width = document.body.offsetWidth;
57
58
this.canvas.style.height = this.height + "px";
59
this.canvas.style.width = this.width + "px";
60
this.canvas.setAttribute("width", (this.width*dpr) + "px");
61
this.canvas.setAttribute("height", (this.height*dpr) + "px");
62
63
this.ctx.scale(dpr, dpr);
64
}
65
66
draw(x, y) {
67
this.ctx.strokeStyle = this.color;
68
this.ctx.lineWidth = this.lineWidth;
69
this.ctx.beginPath();
70
this.ctx.moveTo(this.mousePosition.x, this.mousePosition.y);
71
this.ctx.lineTo(x, y);
72
this.ctx.stroke()
73
// this.ctx.closePath();
74
}
75
76
setColor(color) {
77
this.color = color;
78
}
79
80
setLineWidth(width) {
81
this.lineWidth = width;
82
}
83
84
reset() {
85
this.ctx.clearRect(0,0, this.canvas.width, this.canvas.height)
86
}
87
88
test() {
89
this.ctx.strokeStyle = this.color;
90
this.ctx.lineWidth = this.lineWidth;
91
this.ctx.beginPath();
92
this.ctx.moveTo(100, 100);
93
this.ctx.lineTo(150, 100);
94
this.ctx.stroke()
95
}
96
97
checkIfFill() {
98
99
this.canvas.addEventListener("mousemove", (e) => {
100
const x = e.clientX - this.rect.left;
101
const y = e.clientY - this.rect.top;
102
103
console.log(this.ctx.getImageData(x, y, 1, 1).data)
104
})
105
}
106
}
Advertisement
Answer
This happens because of two things:
- Inside your
draw()
function you’re setting the starting point and the end point with every call. Usually you determine the start as soon as the user pushes the mousebutton – once. - even with #1 fixed, the line end might still look a bit ‘fuzzy’. This can be fixed by setting the context’s lineCap style to
round
instead of it’s defaultbutt
– which squares of line endpoints.
Here’s an example based on your code (just click ‘Run code snippet’):
JavaScript
1
106
106
1
class Board {
2
constructor(canvas) {
3
this.canvas = canvas;
4
this.ctx = this.canvas.getContext("2d");
5
this.isDrawing = false;
6
this.mousePosition = {
7
x: 0,
8
y: 0
9
};
10
this.color = "black";
11
this.rect = this.canvas.getBoundingClientRect();
12
this.lineWidth = 16;
13
this.height = 0;
14
this.width = 0;
15
16
this.initBoard();
17
// this.test();
18
// this.checkIfFill = this.checkIfFill.bind(this)
19
}
20
21
initBoard() {
22
this.renderCanvas();
23
24
window.addEventListener("resize", () => {
25
this.renderCanvas();
26
});
27
28
this.canvas.addEventListener("mousedown", (e) => {
29
this.mousePosition = {
30
x: e.clientX - this.rect.left,
31
y: e.clientY - this.rect.top
32
};
33
this.ctx.beginPath();
34
this.ctx.moveTo(this.mousePosition.x, this.mousePosition.y);
35
this.isDrawing = true;
36
});
37
38
this.canvas.addEventListener("mousemove", (e) => {
39
if (this.isDrawing) {
40
this.draw((e.clientX - this.rect.left), (e.clientY - this.rect.top));
41
this.mousePosition = {
42
x: e.clientX - this.rect.left,
43
y: e.clientY - this.rect.top
44
};
45
}
46
});
47
48
this.canvas.addEventListener("mouseup", () => {
49
this.isDrawing = false;
50
});
51
}
52
53
renderCanvas() {
54
// const drawingTools = document.querySelector(".drawing-tools");
55
const dpr = window.devicePixelRatio;
56
this.height = document.body.offsetHeight;
57
this.width = document.body.offsetWidth;
58
59
this.canvas.style.height = this.height + "px";
60
this.canvas.style.width = this.width + "px";
61
this.canvas.setAttribute("width", (this.width * dpr) + "px");
62
this.canvas.setAttribute("height", (this.height * dpr) + "px");
63
64
this.ctx.scale(dpr, dpr);
65
}
66
67
draw(x, y) {
68
this.ctx.strokeStyle = this.color;
69
this.ctx.lineWidth = this.lineWidth;
70
this.ctx.lineCap = 'round';
71
72
this.ctx.lineTo(x, y);
73
this.ctx.stroke()
74
75
}
76
77
setColor(color) {
78
this.color = color;
79
}
80
81
setLineWidth(width) {
82
this.lineWidth = width;
83
}
84
85
reset() {
86
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
87
}
88
89
test() {
90
this.ctx.strokeStyle = this.color;
91
this.ctx.lineWidth = this.lineWidth;
92
this.ctx.beginPath();
93
this.ctx.moveTo(100, 100);
94
this.ctx.lineTo(150, 100);
95
this.ctx.stroke()
96
}
97
98
checkIfFill() {
99
100
this.canvas.addEventListener("mousemove", (e) => {
101
const x = e.clientX - this.rect.left;
102
const y = e.clientY - this.rect.top;
103
});
104
}
105
}
106
var b = new Board(document.getElementById("canvas"));
JavaScript
1
1
1
<canvas id="canvas" width=400 height=300></canvas>