簡體   English   中英

如何修復帆布上的球的斑點?

[英]how to fix the bliking of the balls in the canvas?

使用新的構造函數ball(color)創建ball的對象類型。 它的屬性包括將其繪制在畫布上並使他沿隨機方向移動的所有條件。 當創建一個球orangeBall = new ball('orange')時,它將很好地顯示出來,包括其在畫布上的運動。 但是,當添加另一個時,它們都開始閃爍。 如何解決呢? 謝謝。

    <!DOCTYPE html>
    <html lang="he">
    <head>
        <meta charset="utf-8" />
        <title>
        כדורים קופצים רנדומלית בצבעים שונים
        </title>
        <style>
            html,body {
                margin: 0;
                padding: 0;
                background: black;
            }
            .container { width:900px; margin:0 auto; }
            #canvas { background:#8613eb; border:1px solid #cbcbcb; }
        </style>
        <script>
var ctx;
var H = 800;
var W = 800;

window.onload = function () {

    ctx = canvas.getContext("2d");
    canvas.width=W;
    canvas.height=H;

    function ball(color) {
        //life - the amount of time to show the ball in the screen
        this.life = 60*1000, //1 minute
    this.color = arguments.length==1 ? color: 'white';
    this.x= Math.round(Math.random()*W);
    this.y= Math.round(Math.random()*H);
    this.radius= 10 + Math.round(Math.random()*50);// between 10-60
    this.dx=1+ Math.round(Math.random()*5); //between 1-6
    this.dy= 2+ Math.round(Math.random()*4); //between 2-6
    this.startAngel= 0;
    this.endAngel= 2*Math.PI; //360deg 
    this.speed= 3+Math.round(Math.random()*50) //3-50msec
    this.show = function() {
        //first clear the previous ball 
        ctx.clearRect(0,0,canvas.width,canvas.height);
        var xClear = (this.x-this.radius) <=0 ? 0:(this.x - this.radius);
        var yClear = (this.y-2*this.radius) <=0 ? 0:(this.y - 2*this.radius);
        ctx.clearRect(xClear,yClear,canvas.width,canvas.height);
        //lets stroke the ball
        ctx.beginPath();
        ctx.fillStyle = this.color;
        this.x+=this.dx;
        this.y+=this.dy;
        if (this.x<0 || this.x>W) {
            this.dx=-this.dx;
            }
        if (this.y<0 || this.y>H) {
            this.dy=-this.dy;
            }
        ctx.arc(this.x,this.y,this.radius,this.startAngel,this.endAngel);
        ctx.closePath();
        ctx.fill();
        this.life-=this.speed;
        var _this = this;
        //  creating new property in the ball 'timePointer'
        this.timePointer = this.life<=0 ? 
            clearInterval(this.timePointer): 
            setTimeout(function() {
            _this.show();
            },this.speed);      
    }
    this.show();
    };

    orangeBall = new ball('orange');
    blackBall = new ball('black');
//  whiteBall = new ball('white');
//  yellowgeBall = new ball('yellow');
//  pinkBall = new ball('pink');
//  blueBall = new ball('blue');
//  greenBall = new ball('green');

};
        </script>
    </head>
    <body>
        <div class="container">
            <canvas id="canvas">Your browser doesn't support this game.</canvas>
        </div>
    </body>
</html>

每個球通過其show功能繪制自身之后,您正在清理整個畫布。 不必讓球離開畫布,而是要有一個間隔,該間隔將調用一個函數,該函數將清除畫布一次,然后迭代所有球並繪制它們。

動畫分為幀。 一幀大約是1/60秒,並且在那一刻繪制了所有動畫。

為了幫助制作動畫,瀏覽器提供了一個函數,您可以使用該函數來調用渲染幀的函數。 requestAnimationFrame(yourfunction)

requestAnimationFrame會告訴瀏覽器您正在對動畫進行更改。 這將停止將畫布呈現給顯示器,直到刷新下一個垂直顯示器為止。

使用setIntervalsetTimeout

function animateSomething(){
    // draw something    

} // as soon as this exits the content of the canvas is moved to the display
  // there is no way to know where the display hardware is writing pixels to 
  // display, could be halfway through drawing a ball
setInterval(animateSomething,1000 / 60);

如果每次退出時對許多對象執行此操作,則像素將移至顯示器,而與顯示器硬件的工作無關。 這導致閃爍,剪切和其他問題。

使用requestAnimationFrame

function animateSomething(){
    // draw something 
    requestAnimationFrame(animateSomething)   

} // The content of the canvas does not move to the display until the
  // display hardware is getting ready to scan the next display refresh
requestAnimationFrame(animateSomething);

處理動畫的最佳方法是從一個功能進行所有渲染。

下面我修改了您的代碼以使用requestAnimationFrame消除閃爍,我添加了一個mainLoop函數來繪制所有球。 我讓瀏覽器處理時間。

 var ctx; var H = 800; var W = 800; window.onload = function() { ctx = canvas.getContext("2d"); canvas.width = W; canvas.height = H; function ball(color) { //life - the amount of time to show the ball in the screen this.life = 60 * 1000; //1 minute this.color = arguments.length == 1 ? color : 'white'; this.x = Math.round(Math.random() * W); this.y = Math.round(Math.random() * H); this.radius = 10 + Math.round(Math.random() * 50); // between 10-60 this.dx = 1 + Math.round(Math.random() * 5); //between 1-6 this.dy = 2 + Math.round(Math.random() * 4); //between 2-6 this.startAngel = 0; this.endAngel = 2 * Math.PI; //360deg this.speed = 3 + Math.round(Math.random() * 50) //3-50msec this.show = function() { //first clear the previous ball ctx.beginPath(); ctx.fillStyle = this.color; this.x += this.dx; this.y += this.dy; if (this.x < 0 || this.x > W) { this.dx = -this.dx; } if (this.y < 0 || this.y > H) { this.dy = -this.dy; } ctx.arc(this.x, this.y, this.radius, this.startAngel, this.endAngel); ctx.closePath(); ctx.fill(); this.life -= this.speed; } }; orangeBall = new ball('orange'); blackBall = new ball('black'); whiteBall = new ball('white'); yellowgeBall = new ball('yellow'); pinkBall = new ball('pink'); blueBall = new ball('blue'); greenBall = new ball('green'); var balls = [orangeBall, blackBall, whiteBall, yellowgeBall, pinkBall, blueBall, greenBall]; function mainLoop(){ ctx.clearRect(0, 0, canvas.width, canvas.height); for(var i = 0; i < balls.length; i++){ if(balls[i].life > 0){ balls[i].show(); } } requestAnimationFrame(mainLoop); } requestAnimationFrame(mainLoop); }; 
 html, body { margin: 0; padding: 0; background: black; } .container { width: 900px; margin: 0 auto; } #canvas { background: #8613eb; border: 1px solid #cbcbcb; } 
 <div class="container"> <canvas id="canvas">Your browser doesn't support this game.</canvas> </div> 

我更改了代碼以使用原型。 那個更好嗎 ? 此外,它還不夠平滑。 還添加了性能時間表以幫助您。

 var ctx; var H = window.innerHeight; var W = window.innerWidth; window.onload = function () { ctx = canvas.getContext("2d"); canvas.width=W; canvas.height=H; function ball(color) { //life - the amount of time to show the ball in the screen this.life = 60*10, //duration of 600 X 16ms(fram per sec) this.color = arguments.length==1 ? color: 'white'; this.x= Math.round(Math.random()*W); this.y= Math.round(Math.random()*H); this.radius= 10 + Math.round(Math.random()*50);// between 10-60 this.dx=1+ Math.round(Math.random()*5); //between 1-6 this.dy= 2+ Math.round(Math.random()*4); //between 2-6 this.startAngel= 0; this.endAngel= 2*Math.PI; //360deg this.start = null; }; ball.prototype.show = function() { //lets stroke the ball ctx.beginPath(); ctx.fillStyle = this.color; this.x+=this.dx; this.y+=this.dy; if (this.x<0 || this.x>W) { this.dx=-this.dx; } if (this.y<0 || this.y>H) { this.dy=-this.dy; } ctx.arc(this.x,this.y,this.radius,this.startAngel,this.endAngel); ctx.closePath(); ctx.fill(); this.life--; }; var arrBalls = [] ; arrBalls.push(new ball('orange')); arrBalls.push(new ball('black')); arrBalls.push(new ball('white')); arrBalls.push(new ball('pink')); arrBalls.push(new ball('blue')); arrBalls.push(new ball('green')); // This loop shell be less then 10ms inorder not to maintain // 60fps interval of screen hardware rendering var balldeth = 0; function paint() { //clear the canvas once in xframes ctx.clearRect(0,0,canvas.width,canvas.height); //paint balls in the canvas for (var i = 0; i < arrBalls.length; i++ ) { arrBalls[i].life >= 0 ? arrBalls[i].show() : ++balldeth; } (balldeth == arrBalls.length) ? console.log("game over"):window.requestAnimationFrame(paint); } window.requestAnimationFrame(paint); }; 
  html,body { margin: 0; padding: 0; background: black; } #canvas { background:#8613eb; border:1px solid #cbcbcb; } 
  <body> <canvas id="canvas">Your browser doesn't support this game.</canvas> </body> 

在此處輸入圖片說明

暫無
暫無

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

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