给大家分享一下如何用js和canvas实现炫酷的雨滴特效
思路
先准备好开发工具,我用的是HBuilderX,当然也可以用Notepad等其它代码编辑器。还要了解一下canvas标签,其实就是一张画布,而js可以做到在上面画画并且实现动态效果
新建一张画布,铺满页面
canvas新建画布
<canvas class="rain"></canvas>
设置样式
<style>
body{
margin: 0;
}
canvas{
display: block;
background: black;
}
</style>
js代码让画布铺满页面
//获取canvas元素,浏览器窗口宽高
var canvas = document.querySelector(".rain");
var aRain=[];//存放雨滴
var w,h;//画布宽度高度
//立即执行方法
(function setSize(){
window.onresize = arguments.callee;
w = window.innerWidth;
h = window.innerHeight;
canvas.width = w;
canvas.height = h;
})();
通过上面的准备已经得到一张画布,接下来就是核心部分,用js在画布上作画,实现想要的效果
画雨滴
实现雨滴效果,首先你得有雨滴对吧,而这里的雨滴其实是一段细长的矩形,
所以考虑怎么画出这样的矩形,核心操作如下
//获取能操作画布的对象,可以说是画笔
var canCon = canvas.getContext("2d");
//开始一条路径,可以说是下笔
canCon.beginPath();
//设置颜色
canCon.fillStyle = "aqua";
//四个参数分别是矩形x,y坐标和宽度高度
canCon.fillRect(x,y,4,10);
雨滴下降
现在考虑怎么让雨滴有下降效果,其实就是用一个定时器来不断改变y的大小,但这样其实就会造成是从上往下画一条长线的效果,这时候就要考虑蒙版的使用,每次y的改变,就把上面的雨滴遮掉,思路就是画一个矩形去覆盖,利用rgba改变透明度
//加蒙版
canCon.fillStyle="rgba(0,0,0,0.05)";
canCon.fillRect(0,0,w,h);
制作源源不断的雨滴
我们的目的是画出源源不断的雨滴,所以得考虑每个雨滴的特性,包括生成的位置(总不能在同一个位置生成吧),雨滴下降以及每秒下降的距离等等,这时候就可以用面向对象的思想去表示雨滴,包括雨滴的一些初始属性,怎么去画雨滴,怎么让雨滴下降,将这些属性和方法封装成一个类
实现雨滴生成位置随机,写一个随机函数
//返回最小值到最大值之间的值
function random(min,max){
return Math.random()*(max-min)+min;
}
写一个雨滴类,实现初始属性以及函数,可以进一步考虑雨滴落到某个位置时产生绽放效果,主要是画半径不断变化的空心圆来实现
//构造函数
function Rain(){
}
//相当于一个雨滴类
Rain.prototype = {
//初始化雨滴
init:function(){
//生成雨滴位置
this.x = random(0,w);//从0到w
this.y = 0;
this.vY = random(4,5);//每秒下降的距离
this.h = random(0.8*h,0.9*h);//地板高度
this.r =1;//雨滴绽放的初始半径
this.vr = 1;//雨滴半径扩大的速度
},
//画出雨滴
draw:function(){
//让雨滴
if(this.y<this.h){
//开始一条路径,可以说是下笔
canCon.beginPath();
//设置颜色
canCon.fillStyle = "aqua";
//四个参数分别是矩形x,y坐标和宽度高度
canCon.fillRect(this.x,this.y,4,10);
}
else{
//画空心圆
canCon.beginPath();
canCon.strokeStyle = "aqua";
//参数分别是x,y坐标,半径,0-360度
canCon.arc(this.x,this.y,this.r,0,Math.PI*2);
canCon.stroke();
}
},
//雨滴下降
move:function(){
if(this.y<this.h){
this.y+= this.vY;//雨滴每秒下降4-5
}
else{
if(this.r<80){
this.r+=this.vr;
}
else{
this.init();
}
}
this.draw();//画移动雨滴
}
}
写一个函数不断创造雨滴,这里现在前面声明一个数组用来储存雨滴对象,还要考虑到for循环的速度贼快,生成雨滴时要给它一个递增的延时效果
function createRain(num){
for(var i =0;i<num;i++){
setTimeout(function(){
var rain = new Rain();
rain.init();
rain.draw();
aRain.push(rain);
},200*i);
}
}
createRain(66);
接下来就是写定时器让雨滴下落,把前面的蒙版部分也加进来写在一个计时器
setInterval(function(){
//加蒙版
canCon.fillStyle="rgba(0,0,0,0.05)";
canCon.fillRect(0,0,w,h);
//item指数组的每一个变量
for(var item of aRain){
item.move();
}
},1000/60);
整个代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>雨滴效果</title>
<style>
body{
margin: 0;
}
canvas{
display: block;
background: black;
}
</style>
</head>
<body>
<canvas class="rain"></canvas>
<script>
//获取canvas元素,浏览器窗口宽高
var canvas = document.querySelector(".rain");
var aRain=[];//存放雨滴
var w,h;
//立即执行方法
(function setSize(){
window.onresize = arguments.callee;
w = window.innerWidth;
h = window.innerHeight;
canvas.width = w;
canvas.height = h;
})();
//获取能操作画布的对象,可以说是画笔
var canCon = canvas.getContext("2d");
canCon.fillStyle = "aqua"//设置画笔颜色
//返回最小值到最大值之间的值
function random(min,max){
return Math.random()*(max-min)+min;
}
//构造函数
function Rain(){
}
//相当于一个雨滴类
Rain.prototype = {
//初始化雨滴
init:function(){
//生成雨滴位置
this.x = random(0,w);//从0到w
this.y = 0;
this.vY = random(4,5);//每秒下降的距离
this.h = random(0.8*h,0.9*h);//地板高度
this.r =1;//雨滴绽放的初始半径
this.vr = 1;//雨滴半径扩大的速度
},
//画出雨滴
draw:function(){
//让雨滴
if(this.y<this.h){
//开始一条路径,可以说是下笔
canCon.beginPath();
//设置颜色
canCon.fillStyle = "aqua";
//四个参数分别是矩形x,y坐标和宽度高度
canCon.fillRect(this.x,this.y,4,10);
}
else{
canCon.beginPath();
canCon.strokeStyle = "aqua";
canCon.arc(this.x,this.y,this.r,0,Math.PI*2);
canCon.stroke();
}
},
move:function(){
if(this.y<this.h){
this.y+= this.vY;//雨滴每秒下降4-5
}
else{
if(this.r<80){
this.r+=this.vr;
}
else{
this.init();
}
}
this.draw();//画移动雨滴
}
}
function createRain(num){
for(var i =0;i<num;i++){
setTimeout(function(){
var rain = new Rain();
rain.init();
rain.draw();
aRain.push(rain);
},200*i);
}
}
createRain(66);
setInterval(function(){
//加蒙版
canCon.fillStyle="rgba(0,0,0,0.05)";
canCon.fillRect(0,0,w,h);
//item指数组的每一个变量
for(var item of aRain){
item.move();
}
},1000/60);
</script>
</body>
</html>
最终效果图
如果光看文章还是有疑问,可以点击链接
看视频,讲的贼详细,希望对各位有帮助,有空的时候做点特效打发打发时间