1

我试图使用 HTML 5 画布创建一个示例绘画应用程序。然后我添加了一个按钮来重绘用户之前绘制的内容。我不确定我做错了什么,或者可能完全错了。当我多次单击重绘按钮时,它会通过绘制线条来生成一些神奇的动画。即使我每次都记录绘制图像的起点。

Demo: http://jsfiddle.net/BW57H/6/

重现步骤:

通过单击鼠标并将其拖动到矩形框上来绘制一些圆形或矩形或其他东西。然后单击 reset and redraw ,然后单击 redraw 几次,然后查看结果。

我不确定我做了什么。我没有读过很多关于 Canvas 的文章。但我很想知道这里发生了什么。谢谢。

html

<body>
    <canvas id="paint" width="600px" height="300px"></canvas>


    <div id="controls">
        <button name="reset" id="reset">Reset</button>
        &nbsp;<button name="redraw" id="redraw">Re-Draw</button>
    </div>
</body>

css

#paint{
    border: solid;
}

js

$(document).ready(function(){


    var x, y, context, painter;

    var xCounter = 0 , yCounter = 0;
    var xarray = [];
    var yarray = [];

    function init(){
        while(document.getElementById("paint") === undefined){
            //do nothing
        }

        console.log("Loaded document now registering events for canvas");
        var canvas = document.getElementById("paint");

        context = canvas.getContext('2d'); 
        painter = new Painter();

        canvas.addEventListener('mousedown', capture, false);
        canvas.addEventListener('mouseup', capture, false);
        canvas.addEventListener('mousemove', capture, false);

        document.getElementById("reset").addEventListener("click",function(){ clearCanvas(canvas);}, false);

            document.getElementById("redraw").addEventListener("click",             function(){
                autoDraw();
            }, false);
    }

    function clearCanvas(canvas){
    context.save();

    // Use the identity matrix while clearing the canvas
    context.setTransform(1, 0, 0, 1, 0, 0);
    context.clearRect(0, 0, canvas.width, canvas.height);

    // Restore the transform
    context.restore();

    };

    function capture(event){

        if(event.which !== 1){
            return;
        }   

        x = event.layerX;
        y = event.layerY;

        switch(event.type){
            case 'mousedown':
                painter.startPaint(event);
                break;
            case 'mouseup':
                painter.endPaint(event);
                break;
            case 'mousemove':
                painter.paint(event);
                break;
        }


    };


    var Painter = function(){

        var self = this;
        self.paintStarted = false;

        self.startPaint  = function(event){
                self.resetRecordingParams();
                self.paintStarted = true;
                context.beginPath();
                context.moveTo(x,y);
                self.record(); 
        }

        self.endPaint = function(event){
                self.paintStarted = false;
                self.record();
                self.paint(event)
        }

        self.paint  = function(event){
            if(self.paintStarted){
                context.lineTo(x,y); 
                context.stroke(); 
                self.record();
            }
        }

        self.record = function(){
            xarray[xCounter++] = x;
            yarray[yCounter++] = y;
        }

        self.resetRecordingParams = function(){
            xarray = [];
            yarray = [];
            xCounter = 0;
            yCounter= 0;
        }

    return self;

    }


    function autoDraw(){
        context.beginPath();

        console.log('starting at: '+xarray[0]+','+yarray[0]);
        context.moveTo(xarray[0],yarray[0]);

        for (var i = 0; i < xarray.length; i++) {
            setTimeout(drawLineSlowly, 1000+(i*20), i); 
        }; 

    }

    function drawLineSlowly(i)
    {
        context.lineTo(xarray[i],yarray[i]); 
        context.stroke(); 

    }

    init();
});
4

2 回答 2

0

您没有任何形式的检查来查看您是否已经在绘图,所以这里是您的代码,其中注释了这些更改,以及实际像素位置修复(http://jsfiddle.net/upgradellc/ htJXy/1/ ):

$(document).ready(function(){
    var x, y, context, painter, canvas;

    var xCounter = 0 , yCounter = 0;
    var xarray = [];
    var yarray = [];

    function init(){
        while(document.getElementById("paint") === undefined){
            //do nothing
        }

        console.log("Loaded document now registering events for canvas");
        canvas = document.getElementById("paint");

        context = canvas.getContext('2d'); 
        painter = new Painter();

        canvas.addEventListener('mousedown', capture, false);
        canvas.addEventListener('mouseup', capture, false);
        canvas.addEventListener('mousemove', capture, false);

        document.getElementById("reset").addEventListener("click",function(){ clearCanvas(canvas);}, false);

            document.getElementById("redraw").addEventListener("click", function(){
                autoDraw();
            }, false);
    }

    function clearCanvas(canvas){
    context.save();

    // Use the identity matrix while clearing the canvas
    context.setTransform(1, 0, 0, 1, 0, 0);
    context.clearRect(0, 0, canvas.width, canvas.height);

    // Restore the transform
    context.restore();

    };

    function capture(event){  
        if(event.which !== 1){
            return;
        }   

        tempPos = getMousePos(canvas, event);
        x = tempPos.x;
        y = tempPos.y;

        switch(event.type){
            case 'mousedown':
                painter.startPaint(event);
                break;
            case 'mouseup':
                painter.endPaint(event);
                break;
            case 'mousemove':
                painter.paint(event);
                break;
        }

    };


    var Painter = function(){
        var self = this;
        self.paintStarted = false;
        //this keeps track of whether or not we are currently auto drawing
        self.currentlyAutoDrawing = false;

        self.startPaint  = function(event){
                self.resetRecordingParams();
                self.paintStarted = true;
                context.beginPath();
                context.moveTo(x,y);
                self.record(); 
        }

        self.endPaint = function(event){
                self.paintStarted = false;
                self.record();
                self.paint(event);
        }

        self.paint  = function(event){
            if(self.paintStarted){
                context.lineTo(x,y); 
                context.stroke(); 
                self.record();
            }
        }

        self.record = function(){
            xarray[xCounter++] = x;
            yarray[yCounter++] = y;
        }

        self.resetRecordingParams = function(){
            xarray = [];
            yarray = [];
            xCounter = 0;
            yCounter= 0;
        }

    return self;

    }


    function autoDraw(){
        context.beginPath();
        //If we are already auto-drawing, then we should just return instead of starting another drawing loop cycle
        if(painter.currentlyAutoDrawing){
            console.log("painter is already auto drawing");
            return;
        }
        painter.currentlyAutoDrawing = true;
        console.log('starting at: '+xarray[0]+','+yarray[0]);
        context.moveTo(xarray[0],yarray[0]);

        for (var i = 0; i < xarray.length; i++) {
            setTimeout(drawLineSlowly, 1000+(i*20), i); 
        }; 

    }

    function drawLineSlowly(i)
    {
        //when we reach the last element in the array, update painter with the fact that autodrawing is now complete
        if(xarray.length == i+1){
            painter.currentlyAutoDrawing=false;
        }
        console.log(xarray.length+" "+i);
        context.lineTo(xarray[i],yarray[i]); 
        context.stroke(); 

    }

    function getMousePos(canv, evt) {
        var rect = canv.getBoundingClientRect();
        return {
          x: evt.clientX - rect.left,
          y: evt.clientY - rect.top
        };
    }

    init();
});
于 2013-06-18T03:40:01.390 回答
0

显然,在开始新的...

使用 setInterval 而不是 setTimeout,并在下一次推送时清除Interval。所以我认为问题不在于画布,而在于您的重绘动画。顺便说一句,这很奇怪,因为重画和原始画之间存在一些差异......

var drawInterval = null;

function autoDraw(){
    if (drawInterval) {
        //here your can reset the previous - still running - redraw
        clearInterval(drawInterval);
    }

    context.beginPath();

    console.log('starting at: '+xarray[0]+','+yarray[0]);
    context.moveTo(xarray[0],yarray[0]);

    var i=0;
    setInterval(function (){
        ++i;
        if (i<xarray.length)
            drawLineSlowly(i);
        else
            clearInterval(drawInterval);
    },20);

}

注意:重绘仍然存在错误,但至少它不会杀死浏览器...顺便说一句,奇怪的“动画”是因为您没有通过重绘检查当前是否正在绘制,所以您开始绘制并重绘在一起,他们干涉......当你开始绘图时,你必须停止重绘。

于 2013-06-18T03:28:57.903 回答