HTML 5 canvas JavaScript rain animation(如何高效轻松地实现!).
html 5 canvas javascript rain animation(how to implement efficiently and easily!)
我在画布上尝试了这两种方法,但没有任何显示,我也怀疑它甚至有效:/。我试图让雨从屏幕上下来。想知道最有效的方法是什么。我是动画初学者,非常感谢帮助。
我怀疑创建一个雨对象是最好的,每个都有从屏幕上下来然后到顶部的质量,然后有一个数组......也许在画布宽度和 y 值为 0 的随机 x 值中,但我不知道如何实现它。请帮忙!
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画布创建的,用于实现此动画的技术称为"双缓冲区动画"。首先,最好知道什么是双缓冲区动画技术。
双缓冲技术:这是一种高级技术,可以使动画清晰且闪烁更少。在这种技术中,使用2 Canvas,一个显示在网页上以显示结果,第二个用于在支持过程中创建动画屏幕。
这将如何帮助充分,假设我们必须创建一个具有非常高移动次数的动画,就像我们的 Snow Fall 示例中一样,有许多雪花以自己的速度移动,所以保持它们移动,我们必须改变每个雪花的位置并在画布上更新它,这是一个相当繁重的过程。
因此,现在我们将创建一个缓冲区画布,而不是直接在我们的页面画布上更新每个 Flake,所有这些更改都发生在那里,我们只需在 30 毫秒后从缓冲区画布捕获图片并将其显示在我们真实的画布上。
这样,我们的动画将清晰且没有闪烁。所以这里有一个活生生的例子。
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.stroke()
的循环末尾使用 .我没有这样做,因为我认为它的效率会低于使用ctx.fillRect
。为了使画布绘制线条,它实际上必须分配一个动态路径(您调用ctx.beginPath
)。然后,它必须记录您添加的所有行。然后,它必须将这些线扩展为各种顶点以栅格化线。你基本上可以看到它使用的各种算法在这里。相反,这一切都不必发生在ctx.fillRect
身上。不必进行分配(不是说它们不会发生,只是说它们不必发生)。画布只能使用单个预分配的四边形,并通过传递正确的矩阵在 GPU 上绘制它来绘制您要求它的任何矩形。当然,他们可能会更多地调用ctx.fillRect
200 次而不是 ctx.moveTo
次,ctx.lineTo
200 秒 + ctx.stroke
一次,但实际上这取决于浏览器。
上面的雨可能是也可能不是足够好的雨效果。这不是我发帖的重点。关键是效率。几乎所有具有某种雨效果的游戏都会为它们的雨做某种无状态公式。不同的公式会产生不同或更少的重复雨。关键是它是无国籍的。
- 如何使用动画实现纸张推车
- 客户端服务器REST API captcha实现
- 如何实现此布局
- Meteor忘记了密码的实现
- 使用Native Sockets在Android中实现WebSockets
- 在样板文件中实现Ajax
- instanceof是如何在JavaScript中实现的
- 如何正确实现Jquery多选小部件
- 实现一个建立在google.com之上的自定义搜索引擎
- 多个组件是如何实现的
- window.location使用jquery mobile实现chrome跳转
- 如何在OpenERP中实现网络摄像头
- Node.js使用Series函数(模式?)实现流控制时出现意外结果
- javascript加密实现,包括可信否认
- 实现比较方法的最佳实践是什么;s的比较类型是在运行时选择的
- 如何让程序员在javascript中实现正确的回调
- 如何使用自定义辅助对象(handler)实现嵌套的每个循环
- AngularJS智能表全局配置实现
- Expressjs/AngularJS:实现req-flash后出错
- HTML 5 canvas JavaScript rain animation(如何高效轻松地实现!).