簡體   English   中英

html 5 canvas javascript rain動畫(如何高效,輕松地實現!)

[英]html 5 canvas javascript rain animation(how to implement efficiently and easily!)

我在畫布上嘗試了這兩個並沒有顯示,我也懷疑它是否有效:/。 我試圖讓屏幕上的雨下雨。想知道這樣做最有效的方法是什么。 我是動畫的初學者,非常感謝幫助。

我懷疑創建一個下雨對象會是最好的,每個都有從屏幕上下來的質量然后到達頂部然后是一個帶有它們的數組...可能有隨機x值,畫布寬度和y值為0但我不知道如何實現。 請幫忙!

                xofRain = 20;
        startY = 0;
        ctx.beginPath();
        ctx.moveTo(xofRain, startY);
        ctx.lineTo(xofRain, startY + 20);
        ctx.closePath();
        ctx.fillStyle = "black"; 
        ctx.fill();


     function rain(xofRain){

        startY = canvas.height();

        ctx.moveTo(xofRain, startY);
        ctx.beginPath();
        ctx.lineTo(xofRain, startY + 3);
        ctx.closePath();
        ctx.fillStyle = "blue"; 
        ctx.fill();
    }

您的回答是,這場雪雨是使用純HTML5 Canvas創建的,用於實現此動畫的技術稱為“雙緩沖動畫”。 首先,了解什么是雙緩沖動畫技術是很好的。

雙緩沖技術:這是一種先進的技術,可以使動畫清晰,閃爍更少。 在此技術中使用2 Canvas,一個顯示在網頁上以顯示結果,第二個用於在后備過程中創建動畫屏幕。

這將有多大幫助,假設我們必須創建一個具有非常高移動次數的動畫,就像在我們的Snow Fall示例中,有許多Flakes正在以自己的速度移動,所以讓它們保持移動,我們必須改變位置每個片狀並在畫布上更新它,這是一個非常繁重的處理過程。

所以現在不是直接在我們的頁面畫布上更新每個Flake,我們將創建一個緩沖區Canvas,所有這些更改都會發生,我們只需在30ms后從Buffer畫布捕獲一個Picture並將其顯示在我們的真實畫布上。

這樣我們的動畫就會清晰,沒有閃爍。 所以這是一個實例。

http://aspspider.info/erishaan8/html5rain/

這是它的代碼:

  <!DOCTYPE html> <html> <head> <meta charset=utf-8 /> <title>HTML5 Rain</title> <!--[if IE]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <style> article, aside, figure, footer, header, hgroup, menu, nav, section { display: block; } </style> <script type="text/javascript"> var canvas = null; var context = null; var bufferCanvas = null; var bufferCanvasCtx = null; var flakeArray = []; var flakeTimer = null; var maxFlakes = 200; // Here you may set max flackes to be created function init() { //Canvas on Page canvas = document.getElementById('canvasRain'); context = canvas.getContext("2d"); //Buffer Canvas bufferCanvas = document.createElement("canvas"); bufferCanvasCtx = bufferCanvas.getContext("2d"); bufferCanvasCtx.canvas.width = context.canvas.width; bufferCanvasCtx.canvas.height = context.canvas.height; flakeTimer = setInterval(addFlake, 200); Draw(); setInterval(animate, 30); } function animate() { Update(); Draw(); } function addFlake() { flakeArray[flakeArray.length] = new Flake(); if (flakeArray.length == maxFlakes) clearInterval(flakeTimer); } function blank() { bufferCanvasCtx.fillStyle = "rgba(0,0,0,0.8)"; bufferCanvasCtx.fillRect(0, 0, bufferCanvasCtx.canvas.width, bufferCanvasCtx.canvas.height); } function Update() { for (var i = 0; i < flakeArray.length; i++) { if (flakeArray[i].y < context.canvas.height) { flakeArray[i].y += flakeArray[i].speed; if (flakeArray[i].y > context.canvas.height) flakeArray[i].y = -5; flakeArray[i].x += flakeArray[i].drift; if (flakeArray[i].x > context.canvas.width) flakeArray[i].x = 0; } } } function Flake() { this.x = Math.round(Math.random() * context.canvas.width); this.y = -10; this.drift = Math.random(); this.speed = Math.round(Math.random() * 5) + 1; this.width = (Math.random() * 3) + 2; this.height = this.width; } function Draw() { context.save(); blank(); for (var i = 0; i < flakeArray.length; i++) { bufferCanvasCtx.fillStyle = "white"; bufferCanvasCtx.fillRect(flakeArray[i].x, flakeArray[i].y, flakeArray[i].width, flakeArray[i].height); } context.drawImage(bufferCanvas, 0, 0, bufferCanvas.width, bufferCanvas.height); context.restore(); } </script> </head> <body onload="init()"> <canvas id="canvasRain" width="800px" height="800px">Canvas Not Supported</canvas> </body> </html> 

此外,如果您發現此幫助已滿,請接受答案並進行補救。 O_O

干杯!!!

我不確定“效率最高”是什么。 如果是我,我會在WebGL中做到這一點,但是對我來說效率是否有效。

在任何一種情況下,我都會嘗試使用無狀態公式。 為每個雨滴創建和更新狀態可能會很慢。

 const ctx = document.querySelector("canvas").getContext("2d"); const numRain = 200; function render(time) { time *= 0.001; // convert to seconds resizeCanvasToDisplaySize(ctx.canvas); const width = ctx.canvas.width; const height = ctx.canvas.height; ctx.fillStyle = "black"; ctx.fillRect(0, 0, width, height); resetPseudoRandom(); const speed = time * 500; ctx.fillStyle = "#68F"; for (let i = 0; i < numRain; ++i) { const x = pseudoRandomInt(width); const y = (pseudoRandomInt(height) + speed) % height; ctx.fillRect(x, y, 3, 8); } requestAnimationFrame(render); } requestAnimationFrame(render); let randomSeed_ = 0; const RANDOM_RANGE_ = Math.pow(2, 32); function pseudoRandom() { return (randomSeed_ = (134775813 * randomSeed_ + 1) % RANDOM_RANGE_) / RANDOM_RANGE_; }; function resetPseudoRandom() { randomSeed_ = 0; }; function pseudoRandomInt(n) { return pseudoRandom() * n | 0; } function resizeCanvasToDisplaySize(canvas) { const width = canvas.clientWidth; const height = canvas.clientHeight; if (canvas.width !== width || canvas.height !== height) { canvas.width = width; canvas.height = height; } } 
 body { margin: 0; } canvas { width: 100vw; height: 100vh; display: block; } 
 <canvas></canvas> 

請注意,我可以使用ctx.moveTo(x, y); ctx.lineTo(x, y + 8); ctx.moveTo(x, y); ctx.lineTo(x, y + 8); 對於每一行,然后在循環的末尾稱為ctx.stroke() 我沒有這樣做,因為我認為它的效率低於使用ctx.fillRect 為了使畫布繪制線條,它實際上必須分配一個動態路徑(你調用ctx.beginPath )。 然后它必須記錄您添加的所有行。 然后它必須將這些線擴展為各種頂點以光柵化線。 你基本上可以看到它在這里使用的各種算法 相反, ctx.fillRect不會發生這種情況。 沒有分配必須發生(不是說他們沒有發生,只是說他們沒有必要)。 畫布可以使用單個預先分配的四邊形,並通過傳遞正確的矩陣在GPU上繪制它來繪制您要求的任何矩形。 當然,他們調用ctx.fillRect 200次而不是ctx.moveToctx.lineTo 200s + ctx.stroke可能會更多,但實際上這取決於瀏覽器。

上面的雨可能會或可能不會有足夠好的降雨效果。 這不是我真正發布的觀點。 關鍵是效率。 幾乎所有具有某種降雨效果的游戲都會為他們的下雨做一些無狀態的公式。 不同的公式會產生不同或更少重復的降雨。 關鍵是它是無國籍的。

暫無
暫無

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

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