大概就是觉得网上这类的文章很多,而且有点乱,就总结了一波
结果图如下(用QQ录制然后ps转gif就成这样了):
读前须知
- 在观看文章之前大家最好有一些canvas的知识,不过没有也没有关系,这里用到的知识点并不多,看到不懂的再去查一下好了,在这里的代码还是很容易理解的
- 文章会涉及到部分es6相关内容,但是不影响阅读,文章后面会给出类写法的代码,也算是总结一波思路,希望大家在我的文章里学到的是思路,而不是代码
- 希望大家学习文章的过程中代码更多的是自己动手敲,而不是一味的复制
- 另外,在学习过程中重点在于展示思路,所以效果可能与文章图片不同,但文章最后给出的类形式的代码则是和真正效果一样的(除了一点点因为ps转换所导致的效果)
一、实现思路
要实现雪花飘落效果,实际上关键之处只需要小小的两步,其一就是需要将雪花随机遍布屏幕的位置,其二就是要更新雪花的位置。
二、实现步骤
1.基本设置
这里是基本的代码格式,这里直接copy就可以了:
index.html文件中:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Make it Snow</title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<div class="container">
<canvas id="canvas"></canvas>
<section class="section">
<div class="text">
<p>Make it Snow.</p>
</div>
</section>
</div>
</body>
<script type="text/javascript" src="./index.js"></script>
</html>
index.css文件中:(图片自己找一个,合适的背景就可)
html {
/* background-image: url('');这里加背景图片 */
background-size: cover;
}
html {
background-color: #000;
}
canvas {
z-index: 2;
}
.text {
text-align: center;
color: #ffffff6b;
font-size: 28px;
width: 100%;
top: 130px;
position: absolute;
margin: 0 auto;
display: block;
}
index.js文件:
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let w, h;//canvas的长宽
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;
//返回min和max中的随机数
function random(min, max) {
return min + Math.random() * (max - min + 1);
};
function clientResize() {
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;
};
window.addEventListener("resize", clientResize);
3.雪花生成
首先,我们需要定义变量particlesOnScreen,是要显示在屏幕上的雪花的数量,然后定义一个数组particlesArray用来设定这些雪花的参数,在这里,我们需要设置雪花的坐标,以及对应的圆的半径,以及雪花下落和左右移动的速度
let particlesOnScreen = 245;//设置雪花的数量
let particlesArray = [];//雪花参数数组
// 设置每个雪花的参数
function createSnowFlakes() {
for (let i = 0; i < particlesOnScreen; i++) {
particlesArray.push({
x: Math.random() * w,
y: Math.random() * h,
speedX: random(-11, 11),
speedY: random(7, 15),
radius: random(0.5, 4.2),
})
}
};
createSnowFlakes();
4.雪花呈现在画布上
这里就是调用canvas相关的方法根据参数画出圆:
// 画出雪花的位置
function drawSnowFlakes() {
for (let i = 0; i < particlesArray.length; i++) {
ctx.beginPath();
//画圆弧
ctx.arc(particlesArray[i].x, particlesArray[i].y, particlesArray[i].radius, 0,Math.PI * 2,false);
//使用白色填充
ctx.fillStyle = "#fff";
ctx.fill();
}
};
5.雪花位置更新
根据横纵方向速度移动雪花位置,如果已经超过了画布范围,就回到最上面:
// 移动雪花的位置
function moveSnowFlakes() {
for (let i = 0; i < particlesArray.length; i++) {
particlesArray[i].x += particlesArray[i].speedX;
particlesArray[i].y += particlesArray[i].speedY;
//如果超过画布大小
if (particlesArray[i].y > h) {
particlesArray[i].x = Math.random() * w * 1.5;
particlesArray[i].y = -50;
}
}
};
6.刷新画布
不断重绘画布实现效果:
// 更新画布
function updateSnowFall() {
//清空画布
ctx.clearRect(0, 0, w, h);
drawSnowFlakes();
moveSnowFlakes();
};
setInterval(updateSnowFall, 50);
至此我们就可以得到(不加背景图):
7.放一下完整代码
index.js文件
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let w, h;//canvas的长宽
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;
function random(min, max) {
return min + Math.random() * (max - min + 1);
};
function clientResize(ev) {
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;
};
window.addEventListener("resize", clientResize);
let particlesOnScreen = 245;//设置雪花的数量
let particlesArray = [];//雪花参数数组
// 设置每个雪花的参数
function createSnowFlakes() {
for (let i = 0; i < particlesOnScreen; i++) {
particlesArray.push({
x: Math.random() * w,
y: Math.random() * h,
opacity: Math.random(),
speedX: random(-11, 11),
speedY: random(7, 15),
radius: random(0.5, 4.2),
})
}
};
createSnowFlakes();
// 画出雪花的位置
function drawSnowFlakes() {
for (let i = 0; i < particlesArray.length; i++) {
ctx.beginPath();
//画圆弧
ctx.arc(particlesArray[i].x, particlesArray[i].y, particlesArray[i].radius, 0,Math.PI * 2,false);
//使用白色填充
ctx.fillStyle = "#fff";
ctx.fill();
}
};
// 移动雪花的位置
function moveSnowFlakes() {
for (var i = 0; i < particlesArray.length; i++) {
particlesArray[i].x += particlesArray[i].speedX;
particlesArray[i].y += particlesArray[i].speedY;
if (particlesArray[i].y > h) {
particlesArray[i].x = Math.random() * w * 1.5;
particlesArray[i].y = -50;
}
}
};
// 更新画布
function updateSnowFall() {
ctx.clearRect(0, 0, w, h);
drawSnowFlakes();
moveSnowFlakes();
};
setInterval(updateSnowFall, 50);
三、类方法实现
这里再用类方法实现一下以上效果,其中为了达到更好的效果,会有一些代码改动,有问题请到评论区或私信。
类方法的实现:
let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let w, h;//canvas的长宽
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;
function random(min, max) {
return min + Math.random() * (max - min + 1);
};
function clientResize() {
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;
};
window.addEventListener("resize", clientResize);
class RainFall {
constructor(particlesOnScreen) {
this.particlesOnScreen = particlesOnScreen;
this.particlesArray = [];
this.#createSnowFlakes();
}
update() {
this.particlesArray.forEach(e => {
e.x += e.speedX;
e.y += e.speedY;
if (e.y > h) {
e.x = Math.random() * w * 1.5;
e.y = -50;
}
})
}
draw() {
this.particlesArray.forEach(item => {
let gradient = ctx.createRadialGradient(item.x, item.y, 0, item.x, item.y, item.radius);
gradient.addColorStop(0, "rgba(255, 255, 255," + item.opacity + ")"); // 白色
gradient.addColorStop(.8, "rgba(210, 236, 242," + item.opacity + ")"); // 带蓝
gradient.addColorStop(1, "rgba(237, 247, 249," + item.opacity + ")"); // 浅蓝
ctx.beginPath();
ctx.arc(item.x,item.y,item.radius, 0,Math.PI * 2, false);
ctx.fillStyle = gradient;
ctx.fill();
})
}
// 设置每个雪花的参数
//每个雪花包括雪花的坐标,雪花的透明度,雪花的左右,下落速度,半径
#createSnowFlakes() {
for (let i = 0; i < this.particlesOnScreen; i++) {
this.particlesArray.push({
x: Math.random() * w,
y: Math.random() * h,
opacity: Math.random(),
speedX: random(-11, 11),
speedY: random(7, 15),
radius: random(0.5, 4.2),
})
}
};
}
let rainFall = new RainFall(100);
// 更新画布
function drawCanvas() {
ctx.clearRect(0, 0, w, h);
rainFall.update();
rainFall.draw();
requestAnimationFrame(drawCanvas);
};
drawCanvas();
总结
所谓总结,当然最好能够起到举一反三的作用了
那么,当我们再实现类似的效果时,我们的重心便是物体的绘制、以及形状的运动,实现了这些,其他的基本上就是copy了。
如果文章对你有帮助的话,请留下你的赞哦,这对我非常重要,谢谢!!!