EaselJs,CreateJs撤消画布绘图在移动设备上太慢了

时间:2015-03-25 15:10:14

标签: android canvas easeljs undo createjs

我正在为画布绘图创建phonegap / cordova android应用程序。

我用https://github.com/ludei/webview-plus/ webview +替换了CordovaWebView(android股票浏览器webview),以提高Android平台上的绘图性能。更换webview后,在android上绘制速度非常快。

现在我使用下面的demo作为基础

创建撤消功能

http://www.createjs.com/Demos/EaselJS/CurveTo

撤消功能正在按预期工作,但撤消性能会随着画布上的更多绘图数据而逐渐降低。这种渐进的性能下降是绝对肯定的,因为我遵循撤消的方法。 在桌面浏览器上性能很好,但在Android手机和平板电脑上撤消需要很长时间。

我的撤消方法:

  1. 将每个绘制点存储(推)到点[]数组以及笔划宽度和颜色。这个points []数组存储了一条连续线的所有信息。

  2. 然后我在mouseup事件中将所有连续行信息存储(推送)到allPoints数组中。

  3. 然后单击撤消时,我从allPoints []数组中弹出(删除)最后一个连续行,然后通过重绘allPoints []数组中的所有点来更新阶段。

  4. 随着画布绘制笔划的增加,allPoints []数组大小增加,并且需要更多时间来重绘allPoints。

    我已经为我的撤销方法的演示设置了一个小提琴。

    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();
    

    我认为重绘allPoints比将画布绘制快照保存为撤消图像更好,因为它会占用大量内存,但现在重绘allPoints很慢,我的运气不好:(

    我在撤消功能方面做错了什么因为画布花了很长时间从allPoints []数组重绘绘图。在10行或更多行后,Android移动设备上的撤销速度很慢。

    有人可以用更好的方法帮助我使用厚帆布绘图进行撤消吗?

    注意:我的画布是A4页面尺寸,即高度为1123像素,宽度为794像素。

2 个答案:

答案 0 :(得分:1)

我还没有在移动设备上测试过大量的形状,但你可以将绘图画布变成一个Container,每行都有自己的Shape,然后在撤消的情况下,你不必重绘任何内容,只需从画布中删除最后一个形状。

答案 1 :(得分:0)

我设法通过画架快速绘制和快速撤消。

现在我已经为每个新行使用了基于对象(形状)的方法,而不是保存每个点。

快速撤消:刚从舞台上移除最后一个形状并调用stage.update()来重绘所有形状。

对于快速绘图:刚刚在我的tick()侦听器或handleMouseMove()中使用currentShape.draw(ctx)替换了stage.update()调用,它就像一个魅力。 currentShape.draw()只绘制调用它的形状,而stage.update()在每个tick()上重绘其所有子形状,使得绘图变慢。

快速撤消和快速绘制的工作小提琴http://jsfiddle.net/MkRCg/134/

var stage;
var isMouseDown;
var currentShape;
var oldMidX, oldMidY, oldX, oldY;
var canvas;
var ctx;

function init() {
    stage = new createjs.Stage('canvas');
    stage.autoClear = true;
    stage.addEventListener("stagemousedown", handleMouseDown);
    stage.addEventListener("stagemouseup", handleMouseUp);            
    createjs.Touch.enable(stage);
    stage.update();
    createjs.Ticker.addEventListener("tick", tick);

    //bind element with id 'undo-drawing' with undoDrawing function
    var undoEl = document.getElementById('undo-drawing');
    undoEl.addEventListener("click",undoDrawing);

    ctx = stage.canvas.getContext('2d');    
}

function stop() {
   createjs.Ticker.removeEventListener("tick", tick);          
}

function tick() {
    if (isMouseDown) {
        var pt = new createjs.Point(stage.mouseX, stage.mouseY);
        var midPoint = new createjs.Point(oldX + pt.x>>1, oldY+pt.y>>1);
        currentShape.graphics.moveTo(midPoint.x, midPoint.y);
        currentShape.graphics.curveTo(oldX, oldY, oldMidX, oldMidY);

        oldX = pt.x;
        oldY = pt.y;

        oldMidX = midPoint.x;
        oldMidY = midPoint.y;

        /* Costly redrawing all previous objects too */
        //stage.update();

        /* only draws currentShape, made drawing fast*/
        currentShape.draw(ctx);


    }
}

function handleMouseDown() {
    isMouseDown = true;

    var s = new createjs.Shape();
    oldX = stage.mouseX;
    oldY = stage.mouseY;
    oldMidX = stage.mouseX;
    oldMidY = stage.mouseY;
    var g = s.graphics;

    var stroke = 2;
    g.setStrokeStyle(stroke, 'round', 'round');

    var color = "#000000";

    g.beginStroke(color);
    stage.addChild(s);

    currentShape = s;
}

function handleMouseUp() {
  isMouseDown = false;

    //make drawing smooth on each mouse up
    stage.update();
   // alert();
}


function undoDrawing() {
  console.log('undo clicked');
  stage.removeChildAt(stage.children.length - 1);
  stage.update();
}


init();