I am creating phonegap/cordova android app for canvas drawing.
I have replaced CordovaWebView(android stock browser webview) with https://github.com/ludei/webview-plus/ webview+ to improve the drawing performance on android platform. After replacing webview drawing is smooth as fast on android.
Now i am creating undo functionality using below demo as base
http://www.createjs.com/Demos/EaselJS/CurveTo
Undo functionality is working as expected, but undo performance is gradually decreasing with more drawing data on canvas. This gradual performance decrease is absolutely certain because of the approach i followed for undoing. On desktop browser performance is good but on android mobile and tablet undoing is taking long time.
My approach for undo :
Storing(pushing) each drawn point into a points[] array along with stroke width and color. This points[] array stores all information for one continuous line.
Then i am storing(pushing) each continuous line information in allPoints array on mouseup event.
Then on clicking undo, I popped(removed) last continuous line from allPoints[] array and then update stage by redrawing all points from allPoints[] array.
As canvas drawing strokes increasing, allPoints[] array size increase and it is taking more time to redraw allPoints.
I have setup a fiddle for demo of my undo approach.
http://jsfiddle.net/JTqvJ/188/
var canvas, stage;
var drawingCanvas;
var oldPt;
var oldMidPt;
var title;
var color;
var stroke;
var colors;
var index;
var allPoints = [];
var points = [];
function init() {
canvas = document.getElementById("canvas");
var undoEl = document.getElementById('undo');
undoEl.addEventListener("click",undoDrawing);
index = 0;
colors = ["#828b20"];
//check to see if we are running in a browser with touch support
stage = new createjs.Stage(canvas);
stage.autoClear = false;
stage.enableDOMEvents(true);
createjs.Touch.enable(stage);
createjs.Ticker.setFPS(24);
drawingCanvas = new createjs.Shape();
stage.addEventListener("stagemousedown", handleMouseDown);
stage.addEventListener("stagemouseup", handleMouseUp);
stage.addChild(drawingCanvas);
stage.update();
}
function stop() {
}
function handleMouseDown(event) {
color = colors[(index++) % colors.length];
stroke = 2;
oldPt = new createjs.Point(stage.mouseX, stage.mouseY);
oldMidPt = oldPt.clone();
stage.addEventListener("stagemousemove", handleMouseMove);
}
function handleMouseMove(event) {
var midPt = new createjs.Point(oldPt.x + stage.mouseX >> 1, oldPt.y + stage.mouseY >> 1);
// current point to draw
var point = {
midPt_x: midPt.x,
midPt_y: midPt.y,
oldPt_x: oldPt.x,
oldPt_y: oldPt.y,
oldMidPt_x:oldMidPt.x,
oldMidPt_y: oldMidPt.y,
s_stroke: stroke,
s_color: color,
}
//store this point in points array
points.push(point);
//draw this point
drawLine(point);
oldPt.x = stage.mouseX;
oldPt.y = stage.mouseY;
oldMidPt.x = midPt.x;
oldMidPt.y = midPt.y;
stage.update();
}
function handleMouseUp(event) {
stage.removeEventListener("stagemousemove", handleMouseMove);
allPoints.push(points);
//empty points array for saving new point objects
points = [];
console.log(allPoints);
}
function drawLine(point){
console.log("drawing");
drawingCanvas.graphics.clear().setStrokeStyle(point.s_stroke, 'round', 'round').beginStroke(point.s_color).moveTo(point.midPt_x, point.midPt_y).curveTo(point.oldPt_x, point.oldPt_y, point.oldMidPt_x, point.oldMidPt_y);
};
function reDrawAllLines(){
//clear whole canvas to refresh
stage.clear();
for (var index1 in allPoints) {
for(var index2 in allPoints[index1]){
drawLine(allPoints[index1][index2]);
stage.update();
//alert(allPoints[index1][index2]);
}
}
};
function undoDrawing(){
console.log('undo');
if(allPoints.length > 0){
console.log('pop last one');
//pop/remove last continuous line from allPoints
allPoints.pop();
allPoints.pop();
console.log(allPoints);
//redraw allPoints array to refresh canvas
reDrawAllLines();
}
}
init();
I thought redrawing allPoints will be a better approach than saving snapshot of canvas drawing as image for undoing as it will be a heavy memory consuming process, but now redrawing allPoints is slow, my bad luck :(
Am i doing something wrong in my undo functionality because of which canvas taking long time to redraw drawing from allPoints[] array. Undo is dead slow on android mobile after 10 or more lines.
Can someone help me with better approach for undoing with heavy canvas drawing?
Note: My canvas is A4 page size i.e height is 1123px and width is 794px .