Reputation: 1159
I am making an HTML drawing app with JavaScript, following a tutorial from this page. I've got up to the point at the end of the 'Demo Colours' section, just before the 'Add Sizes' section.
I have made the app for myself but after a reasonable amount of drawing, the app begins to lag. The pen begins to delay behind the mouse, but most of all, when the colour is changed, it takes a considerable amount of time for the pen's colour to actually change.
I'm calling console.log
when the button is pressed, telling me which button is pressed. These appear immediately when the button is pressed, but the colour still takes a while to change.
Here's the code:
<html>
<head></head>
<body>
<canvas id="lessonCanvas" width="800" height="500" style="border:1px solid black;"></canvas>
<button id="colorPurple">Purple</button>
<button id="colorGreen">Green</button>
<button id="colorYellow">Yellow</button>
<button id="colorBrown">Brown</button>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
//canvas drawing
context = document.getElementById('lessonCanvas').getContext("2d");
$('#lessonCanvas').mousedown(function(e){
var mouseX = e.pageX - this.offsetLeft;
var mouseY = e.pageY - this.offsetTop;
paint = true;
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);
redraw();
});
$('#lessonCanvas').mousemove(function(e){
if(paint){
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
redraw();
}
});
$('#lessonCanvas').mouseup(function(e){
paint = false;
});
$('#lessonCanvas').mouseleave(function(e){
paint = false;
});
var clickX = new Array();
var clickY = new Array();
var clickDrag = new Array();
var clickSize = new Array();
var curSize = "normal";
var clickTool = new Array();
var curTool = "crayon";
var paint;
function addClick(x, y, dragging) {
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
if(curTool == "eraser"){
clickColor.push("white");
}else{
clickColor.push(curColor);
}
clickColor.push(curColor);
clickSize.push(curSize);
}
function redraw() {
context.lineJoin = "round";
/* context.lineWidth = 5; */
for(var i=0; i < clickX.length; i++) {
context.beginPath();
if(clickDrag[i] && i) {
context.moveTo(clickX[i-1], clickY[i-1]);
} else {
context.moveTo(clickX[i]-1, clickY[i]);
}
context.lineTo(clickX[i], clickY[i]);
context.closePath();
context.strokeStyle = clickColor[i];
context.lineWidth = curSize;
context.stroke();
}
}
var colorPurple = "#cb3594";
var colorGreen = "#659b41";
var colorYellow = "#ffcf33";
var colorBrown = "#986928";
var curColor = colorPurple;
var clickColor = new Array();
document.getElementById("colorPurple").onclick = function() {
curColor = colorPurple;
console.log("Color changed to purple.");
}
document.getElementById("colorGreen").onclick = function() {
curColor = colorGreen;
console.log("Color changed to green.");
}
document.getElementById("colorYellow").onclick = function() {
curColor = colorYellow;
console.log("Color changed to yellow.");
}
document.getElementById("colorBrown").onclick = function() {
curColor = colorBrown;
console.log("Color changed to brown.");
}
</script>
</body>
</html>
There's a demo at this page, which uses the exact same code but for some reason doesn't lag. Is this because my canvas is bigger, or is there some other problem I haven't noticed? Any help will be appreciated!
Upvotes: 1
Views: 1138
Reputation: 1358
I also encountered this lag. I follow the tutorial here. After searching for solution I found this tutorial. After comparing, the reason why it is lagging it's because of this loop.
function redraw() {
context.lineJoin = "round";
/* context.lineWidth = 5; */
for(var i=0; i < clickX.length; i++) {
context.beginPath();
if(clickDrag[i] && i) {
context.moveTo(clickX[i-1], clickY[i-1]);
} else {
context.moveTo(clickX[i]-1, clickY[i]);
}
context.lineTo(clickX[i], clickY[i]);
context.closePath();
context.strokeStyle = clickColor[i];
context.lineWidth = curSize;
context.stroke();
}
}
The value saved in arrays does not reset and always looping every time the mouse move event occur. To solve this problem, Remove the addClick()
, don't save it in array and just save the last x, y and color. YOu should also save the last x and y on mouse down event. Here's an example.
saveX;
saveY;
function redraw(x, y){
ctx.beginPath();
ctx.moveTo(saveX, saveY);
ctx.lineTo(x, y);
ctx.closePath();
ctx.strokeStyle = selectedColor;
ctx.lineJoin = 'round';
ctx.lineWidth = curSize;
ctx.stroke();
saveX = x;
saveY = y;
}
Upvotes: 0
Reputation: 4870
It dose not lag. You have done a mistake.
Have a look below at addClick
There you are adding the same color twice and thats why you are getting this behavior.
I made smal change, read the comment at addClick
var colorPurple = "#cb3594";
var colorGreen = "#659b41";
var colorYellow = "#ffcf33";
var colorBrown = "#986928";
var curColor = colorPurple;
var clickColor = new Array();
//canvas drawing
context = document.getElementById('lessonCanvas').getContext("2d");
$('#lessonCanvas').mousedown(function(e){
var mouseX = e.pageX - this.offsetLeft;
var mouseY = e.pageY - this.offsetTop;
paint = true;
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);
redraw();
});
$('#lessonCanvas').mousemove(function(e){
if(paint){
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
redraw();
}
});
$('#lessonCanvas').mouseup(function(e){
paint = false;
});
$('#lessonCanvas').mouseleave(function(e){
paint = false;
});
var clickX = new Array();
var clickY = new Array();
var clickDrag = new Array();
var clickSize = new Array();
var curSize = "normal";
var clickTool = new Array();
var curTool = "crayon";
var paint;
function addClick(x, y, dragging) {
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
if(curTool == "eraser"){
clickColor.push("white");
}else{
clickColor.push(curColor);
}
// clickColor.push(curColor);//This should be removed
clickSize.push(curSize);
}
function redraw() {
context.lineJoin = "round";
/* context.lineWidth = 5; */
for(var i=0; i < clickX.length; i++) {
context.beginPath();
if(clickDrag[i] && i) {
context.moveTo(clickX[i-1], clickY[i-1]);
} else {
context.moveTo(clickX[i]-1, clickY[i]);
}
context.lineTo(clickX[i], clickY[i]);
context.closePath();
context.strokeStyle = clickColor[i];
context.lineWidth = curSize;
context.stroke();
}
}
document.getElementById("colorPurple").onclick = function() {
curColor = colorPurple;
console.log("Color changed to purple.");
}
document.getElementById("colorGreen").onclick = function() {
curColor = colorGreen;
console.log("Color changed to green.");
}
document.getElementById("colorYellow").onclick = function() {
curColor = colorYellow;
console.log("Color changed to yellow.");
}
document.getElementById("colorBrown").onclick = function() {
curColor = colorBrown;
console.log("Color changed to brown.");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="lessonCanvas" width="200" height="200" style="border:1px solid black;"></canvas>
<button id="colorPurple">Purple</button>
<button id="colorGreen">Green</button>
<button id="colorYellow">Yellow</button>
<button id="colorBrown">Brown</button>
Upvotes: 2