簡體   English   中英

畫布和動畫

[英]Canvas and animation

我試圖使用HTML 5 canvas創建一個示例繪畫應用程序。 然后,我添加了一個按鈕以重繪用戶之前繪制的內容。 我不確定自己在做什么錯或可能完全錯了。 當我多次單擊重繪按鈕時,它會通過在各處繪制線條來生成一些神奇的動畫。 即使我每次都記錄繪制圖像的起點相同。

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

重現步驟:

通過單擊鼠標並將其拖動到矩形框上來繪制一些圓形或矩形或其他形狀。 然后單擊“重置並重繪”,然后單擊“重繪”幾次,然后查看結果。

我不確定我做了什么。 我還沒有閱讀有關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();
});

顯然,在開始新的超時循環之前,您不會停止前一個超時循環。

使用setInterval代替setTimeout,並在下一次推送時清除clearInterval。 因此,我認為問題不在於畫布,而在於您的重繪動畫。 順便說一句,這很奇怪,因為重畫和原始畫之間有些區別...

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

}

注意:重繪中仍然存在錯誤,但是至少它不會殺死瀏覽器...奇怪的是,“動畫”是因為您不通過重繪來檢查當前是否正在繪制,因此開始繪制並重繪在一起,它們會相互干擾...開始繪制時必須停止重繪。

您無需進行任何檢查即可查看是否已在繪制圖形,因此這是注釋了這些更改的代碼以及實際像素位置修復程序( 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();
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM