画布雪动画不起作用

时间:2017-12-07 18:17:30

标签: javascript animation canvas

这是一个特定季节的问题。我做了一个基本的动画来模拟一些雪。问题是雪只会下降一次,之后屏幕会变黑。我已经按照一个教程将所有内容放在window.onload()中。这对我来说似乎不那么好,所以这就是我提出来的:

let sky, ctx;
let W, H;

const maxSnow = 250;
const snow = [];

function init(){
	sky = document.getElementById("sky");
	ctx = sky.getContext("2d");

	sky.width = W = window.innerWidth;
	sky.height = H = window.innerHeight;

	for(let i = 0; i < maxSnow; i++)
	{
		snow.push({
			x: Math.random()*W, //x-coordinate
			y: -50, //y-coordinate
			radius: Math.random()*4+1, //radius
			density: Math.random()*maxSnow //density
		})
	}
}

function draw()
{
	ctx.clearRect(0, 0, W, H);

	ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
	ctx.beginPath();
	for(let i = 0; i < maxSnow; i++)
	{
		var flake = snow[i];
		ctx.moveTo(flake.x, flake.y);
		ctx.arc(flake.x, flake.y, flake.radius, 0, Math.PI*2, true);
	}
	ctx.fill();
	update();
}

//Function to move the snowflakes
//angle will be an ongoing incremental flag. Sin and Cos functions will be applied to it to create vertical and horizontal movements of the flakes
var angle = 0;
function update()
{
	angle += 0.01;
	for(var i = 0; i < maxSnow; i++)
	{
		var p = snow[i];
		//Updating X and Y coordinates
		//We will add 1 to the cos function to prevent negative values which will lead flakes to move upwards
		//Every particle has its own density which can be used to make the downward movement different for each flake
		//Lets make it more random by adding in the radius
		p.y += Math.cos(angle+p.density) + 1 + p.radius/2;
		p.x += Math.sin(angle) * 2;

		//Sending flakes back from the top when it exits
		//Lets make it a bit more organic and let flakes enter from the left and right also.
		if(p.x > W+5 || p.x < -5 || p.y > H)
		{
			if(i%3 > 0) //66.67% of the flakes
			{
				snow[i] = {x: Math.random()*W, y: -10, r: p.radius, d: p.density};
			}
			else
			{
				//If the flake is exitting from the right
				if(Math.sin(angle) > 0)
				{
					//Enter from the left
					snow[i] = {x: -5, y: Math.random()*H, r: p.radius, d: p.density};
				}
				else
				{
					//Enter from the right
					snow[i] = {x: W+5, y: Math.random()*H, r: p.radius, d: p.density};
				}
			}
		}
	}
}

window.onload = function(){
	init();
	//animation loop
	setInterval(draw, 33);
}

window.addEventListener('resize', function(){
  sky.width = W = window.innerWidth;
  sky.height = H = window.innerHeight;
}, false);
* {
  margin: 0;
  padding: 0;
}

body {
  overflow: hidden;
  background-color: rgba(0, 0, 0, 1);
}
<html>
  <head>
    <link rel="stylesheet" href="style.css">
  </head>

  <body>
    <canvas id="sky"></canvas>
    <script src="snow.js"></script>
  </body>
</html>

有人看到问题是什么以及为什么粒子只落下一次? 谢谢。

1 个答案:

答案 0 :(得分:3)

这是因为当雪花离开屏幕时,您将它们重置为错误的物体。

原始对象(以及所有方法)期望xyradiusdensity

但是当您更新对象时,您需要创建xyrd

如果您将rd重命名为正确的名称,则可以使用。

let sky, ctx;
let W, H;

const maxSnow = 250;
const snow = [];

function init(){
	sky = document.getElementById("sky");
	ctx = sky.getContext("2d");

	sky.width = W = window.innerWidth;
	sky.height = H = window.innerHeight;

	for(let i = 0; i < maxSnow; i++)
	{
		snow.push({
			x: Math.random()*W, //x-coordinate
			y: -50, //y-coordinate
			radius: Math.random()*4+1, //radius
			density: Math.random()*maxSnow //density
		})
	}
}

function draw()
{
	ctx.clearRect(0, 0, W, H);

	ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
	ctx.beginPath();
	for(let i = 0; i < maxSnow; i++)
	{
		var flake = snow[i];
		ctx.moveTo(flake.x, flake.y);
		ctx.arc(flake.x, flake.y, flake.radius, 0, Math.PI*2, true);
	}
	ctx.fill();
	update();
}

//Function to move the snowflakes
//angle will be an ongoing incremental flag. Sin and Cos functions will be applied to it to create vertical and horizontal movements of the flakes
var angle = 0;
function update()
{
	angle += 0.01;
	for(var i = 0; i < maxSnow; i++)
	{
		var p = snow[i];
		//Updating X and Y coordinates
		//We will add 1 to the cos function to prevent negative values which will lead flakes to move upwards
		//Every particle has its own density which can be used to make the downward movement different for each flake
		//Lets make it more random by adding in the radius
		p.y += Math.cos(angle+p.density) + 1 + p.radius/2;
		p.x += Math.sin(angle) * 2;

		//Sending flakes back from the top when it exits
		//Lets make it a bit more organic and let flakes enter from the left and right also.
		if(p.x > W+5 || p.x < -5 || p.y > H)
		{
			if(i%3 > 0) //66.67% of the flakes
			{
				snow[i] = {x: Math.random()*W, y: -10, radius: p.radius, density: p.density};
			}
			else
			{
				//If the flake is exitting from the right
				if(Math.sin(angle) > 0)
				{
					//Enter from the left
					snow[i] = {x: -5, y: Math.random()*H, radius: p.radius, density: p.density};
				}
				else
				{
					//Enter from the right
					snow[i] = {x: W+5, y: Math.random()*H, radius: p.radius, density: p.density};
				}
			}
		}
	}
}

window.onload = function(){
	init();
	//animation loop
	setInterval(draw, 33);
}

window.addEventListener('resize', function(){
  sky.width = W = window.innerWidth;
  sky.height = H = window.innerHeight;
}, false);
* {
  margin: 0;
  padding: 0;
}

body {
  overflow: hidden;
  background-color: rgba(0, 0, 0, 1);
}
<html>
  <head>
    <link rel="stylesheet" href="style.css">
  </head>

  <body>
    <canvas id="sky"></canvas>
    <script src="snow.js"></script>
  </body>
</html>