简介

在codepen上看到一个Canvas做的下雨效果动画,感觉蛮有意思的。就研究了下,这里来分享下,实现技巧。效果可以见下面的链接。

霓虹雨: http://codepen.io/natewiley/full/NNgqVJ/

效果截图:

Canvas动画基础

大家都知道,Canvas其实只是一个画板。我们可以应用canvas的api在上面绘制各种图形。
Canvas 2D 的API:
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D

那么Canvas绘制动画的步骤就是:

  1. 绘制第一帧图形(利用API绘图)
  2. 清空画板(应用clearRect()或fillRect())
  3. 绘制下一帧动画

用什么来控制动画每一帧的绘制时间呢?大家很容易想到 window.setInterval()和window.setTimeout()。没错用这两个也可以。除此之外,后来又出现一个新的方法:window.requestAnimationFrame(callback)。

requestAnimationFrame会告诉浏览器你要绘制一个动画。让浏览器要重绘时调用你指定的方法(callback)来绘制你的动画。
使用方法如下:

function anim() {
ctx.fillStyle = clearColor;
ctx.fillRect(0,0,w,h);
for(var i in drops){
drops[i].draw();
}
requestAnimationFrame(anim);
}

一般情况下优先使用requestAnimationFrame能保持动画绘制的频率和浏览器重绘的频率一致。不幸的是requestAnimationFrame的兼容性还不是很好。IE9以下和addroid 4.3以下好像不支持这个属性。不支持的浏览器要用setInterval或setTimeout做兼容。

雨滴下落效果

首先来讲讲雨滴下落的效果如何制作。雨滴其实是一个长方形,然后加残影。残影的绘制可以说是雨滴下落的关键。残影是通过在前进的方向每一帧都绘制一个半透明的背景和一个长方形,然后前面绘制的图形叠加产生的效果。由于前进方向的图形最后绘制,所以显得明亮,后面的图形叠加的比较多,所以视觉上减弱。整体看起来后面的就像残影。这里绘制具有透明度背景是关键,否则产生不了叠加效果。

那么来绘制个雨滴看看。首先准备一个画板:
html代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>霓虹雨</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<style type="text/css">
.bg {background: #000;
overflow: hidden;
}
</style>
</head>
<body class="bg">
<canvas id="canvas-club"></canvas>
<script type="text/javascript" src="raindrop.js"></script>
</body>
</html>

我在js文件里绘制动画(raindrop.js),代码如下:

var c = document.getElementById("canvas-club");
var ctx = c.getContext("2d");//获取canvas上下文
var w = c.width = window.innerWidth;
var h = c.height = window.innerHeight;//设置canvas宽、高
var clearColor = 'rgba(0, 0, 0, .1)';//画板背景,注意最后的透明度0.1 这是产生叠加效果的基础
function random(min, max) {
return Math.random() * (max - min)   min;
}
function RainDrop(){}
//雨滴对象 这是绘制雨滴动画的关键
RainDrop.prototype = {
init:function(){
this.x =  random(0, w);//雨滴的位置x
this.y = 0;//雨滴的位置y
this.color = 'hsl(180, 100%, 50%)';//雨滴颜色 长方形的填充色
this.vy = random(4, 5);//雨滴下落速度
this.hit = random(h * .8, h * .9);//下落的最大值
this.size = 2;//长方形宽度
    },
draw:function(){
if (this.y < this.hit) {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.size, this.size * 5);//绘制长方形,通过多次叠加长方形,形成雨滴下落效果
        }
this.update();//更新位置
    },
update:function(){
if(this.y < this.hit){
this.y  = this.vy;//未达到底部,增加雨滴y坐标
}else{
this.init();
}
}
};
function resize(){
w = c.width = window.innerWidth;
h = c.height = window.innerHeight;
}
//初始化一个雨滴
var r = new RainDrop();
r.init();
function anim() {
ctx.fillStyle = clearColor;//每一帧都填充背景色
ctx.fillRect(0,0,w,h);//填充背景色,注意不要用clearRect,否则会清空前面的雨滴,导致不能产生叠加的效果
r.draw();//绘制雨滴
requestAnimationFrame(anim);//控制动画帧
}
window.addEventListener("resize", resize);
//启动动画
anim();

涟漪效果

接着来绘制涟漪效果。与绘制雨滴的方式类似,也是通过具有透明度的背景来叠加前面的图像产生内阴影的效果。

代码如下(rippling.js):

var c = document.getElementById("canvas-club");
var ctx = c.getContext("2d");//获取canvas上下文
var w = c.width = window.innerWidth;
var h = c.height = window.innerHeight;//设置canvas宽、高
var clearColor = 'rgba(0, 0, 0, .1)';//画板背景,注意最后的透明度0.1 这是产生叠加效果的基础
function random(min, max) {
return Math.random() * (max - min)   min;
}
function Rippling(){}
//涟漪对象 这是涟漪动画的主要部分
Rippling.prototype = {
init:function(){
this.x = random(0,w);//涟漪x坐标
this.y = random(h * .8, h * .9);//涟漪y坐标
this.w = 2;//椭圆形涟漪宽
this.h = 1;//椭圆涟漪高
this.vw = 3;//宽度增长速度
this.vh = 1;//高度增长速度
this.a = 1;//透明度
this.va = .96;//涟漪消失的渐变速度
    },
draw:function(){
ctx.beginPath();
ctx.moveTo(this.x, this.y - this.h / 2);
//绘制右弧线
        ctx.bezierCurveTo(
this.x   this.w / 2, this.y - this.h / 2,
this.x   this.w / 2, this.y   this.h / 2,
this.x, this.y   this.h / 2);
//绘制左弧线
        ctx.bezierCurveTo(
this.x - this.w / 2, this.y   this.h / 2,
this.x - this.w / 2, this.y - this.h / 2,
this.x, this.y - this.h / 2);
ctx.strokeStyle = 'hsla(180, 100%, 50%, ' this.a ')';
ctx.stroke();
ctx.closePath();
this.update();//更新坐标
    },
update:function(){
if(this.a > .03){
this.w  = this.vw;//宽度增长
this.h  = this.vh;//高度增长
if(this.w > 100){
this.a *= this.va;//当宽度超过100,涟漪逐渐变淡消失
this.vw *= .98;//宽度增长变缓慢
this.vh *= .98;//高度增长变缓慢
            }
} else {
this.init();
}
}
};
function resize(){
w = c.width = window.innerWidth;
h = c.height = window.innerHeight;
}
//初始化一个涟漪
var r = new Rippling();
r.init();
function anim() {
ctx.fillStyle = clearColor;
ctx.fillRect(0,0,w,h);
r.draw();
requestAnimationFrame(anim);
}
window.addEventListener("resize", resize);
//启动动画
anim();

总结

这样大家对整个下雨效果的制作方法,应该有一定的了解了。Canvas用来绘制动画的效果确实能让人眼前一亮,让web的视觉效果提升一大截。发动自己的智慧,相信能做出更多奇妙的动画。这是我越来越喜欢web的原因之一吧 O(∩_∩)O~~。

转载出处:Web前端开发 » Canvas制作的下雨动画

本文转载于:猿2048➭https://www.mk2048.com/blog/blog.php?id=ckbahaa&title=Canvas制作的下雨动画

Canvas制作的下雨动画相关推荐

  1. html怎么做下雨效果,Canvas制作的下雨动画的示例

    简介 在codepen上看到一个Canvas做的下雨效果动画,感觉蛮有意思的.就研究了下,这里来分享下,实现技巧. 效果截图: Canvas动画基础 大家都知道,Canvas其实只是一个画板.我们可以 ...

  2. 如何用html5 canvas制作子画面动画,如何用HTML5 Canvas制作子画面动画

    用户提问 为了用DOM做2D游戏,你基本上要动态地调整元素风格,以便在页面上移动它.虽然有些时候DOM修改是很好的,但这一次我将重点介绍使用HTML5 Canvas来制作图像,因为对于现代浏览器,它是 ...

  3. 带你使用canvas制作马赛克canvas飞鸟动画小球动画

    文章目录 canvas制作马赛克&飞鸟动画&小球拖拽动画 一.了解单像素操作 1.在canvas中的像素操作 2.得到场景像素数据 3.ImageData对象 4.在场景中写入像素数据 ...

  4. php 3d animation,如何用HTML5的Canvas制作3D动画效果

    HTML5的诞生给web前端界带来了不小轰动,像什么动画旋转.图片滑块.图片轮播等等这些3D特效,也引发了不少朋友想要学习HTML5的好奇心.最近我一直在做canvas动画效果,发现canvas这个东 ...

  5. html5在线制作教程,HTML5 Canvas 制作动画

    HTML5 Canvas 制作动画 在HTML5 canvas中绘制图像动画效果,你需要绘制出每一帧的图像,然后在一个极短的时间内从一帧过渡到下一帧,形成动画效果. 在线示例 要在HTML5画布上绘制 ...

  6. canvas 制作动画(上)

    canvas 制作动画(上) canvas 制作动画(上) 1. 画布中的动画 2. 创建动画循环 2.1 循环 2.2 更新.清除.绘制 3. 记忆要绘制的形状 3.1 错误的方法 3.2 正确的方 ...

  7. 在线html5制作场景,html5 canvas超逼真3d动画场景

    这是一个使用Html5 canvas制作的相当真实的3d动画场景效果.canvas由js在运行时动态生成. HTML Look around by dragging and holding the m ...

  8. html制作的动态粒子图像,一种基于AnimateCC+Canvas的随机粒子动画效果设计

    潘博 摘要:粒子动画是一种应用广泛的动画效果,也有不同的制作方法.Animate CC是Flash的延续和发展,在动画制作方面功能强大,而Canvas是HTML5在网页中绘制图形.制作动画的核心元素. ...

  9. 用离屏canvas制作仿Prezi页面转场动画特效

    用离屏canvas制作网站页面特效.仿Prezi转场特效 首屏效果 页面切换转场效果 · 首屏圆形循环扩散效果 首屏效果的难点在于圆形循环扩散动画和贝塞尔曲线的绘制.圆形逐渐扩大的动画并不难,关键在于 ...

最新文章

  1. 《Nature》挑战进化DNA突变理论!
  2. 2009下半年网络管理员试题及答案
  3. Spring-解决请求中文乱码问题
  4. 21%转化率,海淘用户都在买什么?
  5. oracle每天自增长,oracle的自增长
  6. pythonopencv的配置_python配置与使用OpenCV
  7. python异常值处理实例_python-异常值:(“ 08001”,“ [08001] [unixODBC]...
  8. 设置只能开启一个程序实例
  9. 【网络营销】CPA、CPS、CPM、CPT、CPC 是什么
  10. Binarized Neural Network : BNN二值神经网络代码实例
  11. 从伊朗虚假新闻活动案例来看国外造谣及传谣模式
  12. 遗传算法的基本原理和方法(转)
  13. js封装QQ音乐api
  14. 天猫精灵,还缺点啥?
  15. UPS不间断电源系统安全使用要领
  16. UiPath官网认证培训
  17. umeditor 专题
  18. PHP利用CURL_MULTI实现多线程爆破
  19. DameWare remote control工具远程时“找不到网络路径”错误提示67
  20. MQTT通信架构 搭建MQTT服务器

热门文章

  1. cordic ip核 vivado_Xilinx Vivado CORDIC IP求解atan 反正切
  2. react组件卸载调用的方法_好程序员web前端培训分享React学习笔记(三)
  3. 如何有效开展小组教学_高效课堂 有效教学 | 教育部专家到徐州市第三中学开展教研活动...
  4. BZOJ 2957 楼房重建-线段树
  5. MongoDB系列之——安装和启动
  6. [python] 列表解析式的高效与简洁
  7. DHCP服务(dhcpd)
  8. Java----前端验证之验证码额实现
  9. linux下如何安装配置redis及主从配置
  10. windbg script ---- 禁用IsDebuggerPresent