I am making a simple drag to draw script on canvas. The thing is that when I am drawing a line to connect the points of the mouse positions, the canvas draws extra lines from some random points, but always from the initial point.
Here's an example to see the problem: http://sktch.io/988111
I took the data captured in one such mouse move, and manually went through drawing each point, and i can confirm that the issue doesn't get solved. What makes me annoyed is that if I manually do moveTo and lineTo for some arbitrary points, the code works. It's got some issue with mouse drag points. As far as I can tell there isn't an issue with the points collected.
Any pointers are appreciated. I have already tried various modifications such as, beginPath, moveto, lineto, and stroke in each single loop iteration, or beginpath, and in the loop - moveto, lineto, and then stroke outside the loop. Same results.
The problematic code is included at the bottom.
var App = (function() {
var canvas, currentLayer, paint = false, context, socket, room, currentTool = 'line',
keysrt = function(key,desc) {
return function(a,b){
return desc ? ~~(a[key] < b[key]) : ~~(a[key] > b[key]);
}
},
reDraw = function() {
if (context) {
context.clearRect(0, 0, canvas.offsetWidth, canvas.offsetHeight);
Object.keys(layers).sort().forEach(function(key) {
let layer = layers[key];
switch(layer.getTool()) {
case 'line':
var data = layer.getData().sort(keysrt('time'));
if(data.length > 1) {
for(var i = 1; i < data.length; i++) {
context.beginPath();
context.moveTo(data[i-1]['value'][0], data[i-1]['value'][1]);
context.lineTo(data[i]['value'][0], data[i]['value'][1]);
context.stroke();
}
}
break;
case 'eraser':
var data = layer.getData().sort(keysrt('time'));
if(data.length > 0) {
for(var i = 0; i < data.length; i++) {
context.clearRect(data[i][0], data[i][1], 4, 4);
}
}
break;
case 'clear':
context.clearRect(0, 0, canvas.offsetWidth, canvas.offsetHeight);
break;
}
});
}
},
Layer = function() {
var data = [], tool, id = new Date().getTime();
return {
push: function(time, value) {
data.push({time: time, value: value})
},
toJSON: function() {
return {
data: data,
tool: tool,
id: id
}
},
setTool: function(t) {
tool = t;
},
getTool: function() {
return tool;
},
getData: function() {
return data;
},
getId: function() {
return id;
},
setId: function(i) {
id = i;
},
setData: function(d) {
data = d;
}
};
},
layers = {},
events = 0;
press = function (e) {
var mouseX = (e.changedTouches ? e.changedTouches[0].pageX : e.pageX) - this.offsetLeft, mouseY = (e.changedTouches ? e.changedTouches[0].pageY : e.pageY) - this.offsetTop;
// add a layer
paint = true;
currentLayer = Layer();
currentLayer.setTool(currentTool);
layers[currentLayer.getId()] = currentLayer;
events = 1;
},
drag = function (e) {
var mouseX = (e.changedTouches ? e.changedTouches[0].pageX : e.pageX) - this.offsetLeft, mouseY = (e.changedTouches ? e.changedTouches[0].pageY : e.pageY) - this.offsetTop;
if (paint) {
events = events + 1;
currentLayer.push(new Date().getTime() * 10 + events, [mouseX, mouseY]);
reDraw()
}
e.preventDefault();
},
release = function () {
paint = false;
if(currentLayer) {
events = 0;
reDraw();
}
currentLayer = null;
},
init = function(id, appendTo, width, height) {
room = id;
canvas = document.createElement('canvas');
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
canvas.setAttribute('id', 'canvas');
appendTo.appendChild(canvas);
context = canvas.getContext("2d");
canvas.addEventListener("mousedown", press, false);
canvas.addEventListener("mousemove", drag, false);
canvas.addEventListener("mouseup", release);
canvas.addEventListener("mouseout", release, false);
// Add touch event listeners to canvas element
canvas.addEventListener("touchstart", press, false);
canvas.addEventListener("touchmove", drag, false);
canvas.addEventListener("touchend", release, false);
canvas.addEventListener("touchcancel", release, false);
document.getElementById('clear').addEventListener("click", function() {
layer = Layer();
layer.setTool('clear');
layers[layer.getId()] = layer;
reDraw();
}, false);
}
return {
init: init
}
})();
context.clearRect(0,0,canvasWidth,canvasHeight);
– Rayon