[英]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.