簡體   English   中英

平穩地停止畫布中的動畫雨

[英]Stopping animated rain in Canvas smmoothly

雨圖片瀏覽所以我的問題沒有停止其停止下雨的制作,因此已經呈現雨水完成其動畫關閉屏幕雨。

我在JS中嘗試過setInterval和setTimeout,但是它凍結了。

並使用JQuery刪除canvas標記可一次刪除所有拖放。

任何想法或方向都很好!

  var canvas = document.getElementById("rainCanvas"); var ctx = canvas.getContext("2d"); var canvasW = window.innerWidth; var canvasH = window.innerHeight; canvas.height = canvasH; canvas.width = canvasW; var mf = 70; var drops = []; for(var i = 0; i < mf; i++){ drops.push({ x: Math.random()*canvasW, y: Math.random()*canvasH, r: Math.random()*5+2, d: Math.random() + 1 }) } function fill() { ctx.fill(); } function drawRain(){ ctx.clearRect(0, 0, canvasW, canvasH); ctx.fillStyle = "rgba(255, 255, 255, .5)"; ctx.beginPath(); for(var i = 0; i < mf; i++){ var f = drops[i]; ctx.moveTo(fx-5, fy); ctx.lineTo(fx, fy-15); ctx.lineTo(f.x+5, fy); ctx.arc(fx, fy + fr*.7,5, 0, Math.PI, false); } fill(); moveRain(); } function moveRain(){ for(var i = 0; i < mf; i++){ var f = drops[i]; fy += Math.pow(fd, 2) + 1; if(fy > canvasH){ drops[i] = {x: Math.random()*canvasW, y: 0, r: fr, d: fd}; } } } var i = setInterval(drawRain, 20); setTimeout(function( ) { clearInterval(); }, 2000); 
 canvas{ background-color: black } 
 <canvas id="rainCanvas"></canvas> 

您要做的是設置一個標志,以防止雨水回滾到函數頂部以停止雨水:

var stopRain = false;

...

setTimeout(function( ) { stopRain = true; }, 2000);

現在在moveRain內部,當該變量為true時,而不是將其移回頂部,將其從數組中刪除。 一旦刪除所有滴,我們便可以清除不再需要的時間間隔:

function moveRain(){
    for(var i = 0; i < mf; i++){
        var f = drops[i];
        f.y += Math.pow(f.d, 2) + 1;

        if(f.y > canvasH){
            if(stopRain) {              // When we stop raining 
            drops.splice(i, 1);        // Remove drop from array
            mf--;                      // Make sure to update the "length"
            if(mf<1) clearInterval(i); // If there are not more drops clear the interval
          } else drops[i] = {x: Math.random()*canvasW, y: 0, r: f.r, d: f.d};
        }
    }
}

小提琴的例子

您也可以使用drops.length而不是mf ,這樣就不需要做mf--

在這里,我修復了一些代碼,並添加了rainDensity變量來控制新雨滴的計數。 原始代碼被設計為具有固定數量的雨滴,必須對其進行更改以實現所需的效果。

 window.onload = function(){ var canvas = document.getElementById("rainCanvas"); var ctx = canvas.getContext("2d"); var canvasW = window.innerWidth; var canvasH = window.innerHeight; canvas.height = canvasH; canvas.width = canvasW; var drops = []; function makeDrop() { drops.push({ x: Math.random()*canvasW, y: -10, r: Math.random()*4+1, d: Math.pow(Math.random() + 1, 2) + 1 }) } function drawRain(){ ctx.clearRect(0, 0, canvasW, canvasH); ctx.fillStyle = "rgba(128, 128, 255, .5)"; for(var f of drops){ ctx.beginPath(); ctx.moveTo(fx-5, fy); ctx.lineTo(fx, fy-15); ctx.lineTo(f.x+5, fy); ctx.arc(fx, fy + fr*.7,5, 0, Math.PI, false); ctx.fill(); } } function handleFrame() { drawRain(); updateRain(); } function updateRain() { moveRain(); makeNewDrops(); } var dropPerFrameCounter = 0; var startTime = Date.now(); function makeNewDrops() { var elapsedTime = (Date.now() - startTime) / 1000; // rainDensity: set it to 0 to stop rain var rainDensity = Math.max(0, Math.sin(elapsedTime / 3) + 0.5); dropPerFrameCounter += rainDensity; while (dropPerFrameCounter >= 1) { dropPerFrameCounter--; makeDrop(); } } function moveRain() { for(var f of drops){ fy += fd; } drops = drops.filter(d => dy < canvasH); } var intervalRender = setInterval(handleFrame, 20); } 
 <canvas id="rainCanvas"></canvas> 

必須添加答案,因為該示例都使用setInterval來制作看上去很糟糕的動畫。 使用requestAnimationFrame進行動畫處理。 還修復了代碼中的其他一些問題。

我添加了一個暫停,當您在畫布上單擊時可以暫停動畫。 再次單擊將繼續。

 var canvas = document.getElementById("rainCanvas"); var ctx = canvas.getContext("2d"); var canvasW = window.innerWidth; var canvasH = window.innerHeight; canvas.height = canvasH; canvas.width = canvasW; var mf = 70; var drops = []; var paused = false; for(var i = 0; i < mf; i++){ drops.push({ x: Math.random()*canvasW, y: Math.random()*canvasH, r: Math.random()*5+2, d: Math.random() + 1 }) } function drawRain(){ if(!paused){ ctx.clearRect(0, 0, canvasW, canvasH); ctx.fillStyle = "rgba(255, 255, 255, .5)"; ctx.beginPath(); for(var i = 0; i < mf; i++){ var f = drops[i]; ctx.moveTo(fx - 2.5 * fd, fy); ctx.lineTo(fx, fy - 7.5 * fd); ctx.lineTo(fx + 2.5 * fd, fy); ctx.arc(fx, fy + fr * 0.7, 2.5 * fd, 0, Math.PI, false); } ctx.fill(); for(var i = 0; i < mf; i++){ var f = drops[i]; fy += Math.pow(fd, 2) + 1; if(fy > canvasH + 15){ // make sure completely off the bottom // dont create a new drop reuse it will stop GC from // having to interrupt the code. fx = Math.random()*canvasW; fy = -6; // move off top } } } requestAnimationFrame(drawRain); } requestAnimationFrame(drawRain); canvas.addEventListener("click",()=>{paused = ! paused}); 
 canvas{ background-color: black; position : absolute; top : 0px; left : 0px; } 
 <canvas id="rainCanvas"></canvas> 

暫無
暫無

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

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