Android : EaselJs, CreateJs Undo canvas drawing is too slow on mobile

on Wednesday, March 25, 2015


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 :




  1. 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.




  2. Then i am storing(pushing) each continuous line information in allPoints array on mouseup event.




  3. 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?


0 comments:

Post a Comment