Canvas制作的下雨动画

简介

在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制作的下雨动画

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/370325.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在Eclipse中有效使用JUnit

最近&#xff0c;我被卷入了讨论1和一些受感染的同伴2&#xff0c;他们关于我们如何在Eclipse IDE中使用JUnit 。 令人惊讶的是&#xff0c;对话带来了并非所有人都知道的一些“技巧”。 这使我有了写这篇文章的想法&#xff0c;总结了我们的演讲。 谁知道–也许有人也有新事物…

jquery文件上传控件 Uploadify

基于jquery的文件上传控件&#xff0c;支持ajax无刷新上传&#xff0c;多个文件同时上传&#xff0c;上传进行进度显示&#xff0c;删除已上传文件。 要求使用jquery1.4或以上版本&#xff0c;flash player 9.0.24以上。 有两个版本&#xff0c;一个用flash,一个是html5。html5…

php实现第三方邮箱登录_PHP实现用户异地登录提醒功能的方法

有时候你的网站账号被盗或你在别处登录操作后台时&#xff0c;右下角会弹出提示信息&#xff0c;提醒你的账号异地登录&#xff0c;或者会被强制下线。对于这种安全性要求比较高的web网站&#xff0c;很多后台管理都会做这种功能提醒。甄别自己的账号是否被盗或者是否有另一个人…

课时47.datalist标签(了解)

1.datalist标签 作用&#xff1a;给输入框绑定待选项 2.datalist格式&#xff1a; <datalist> <option>待选项内容</option> </datalist> 3.如何给输入框绑定待选列表&#xff1f; 搞一个输入框搞一个datalist列表给datalist列表标签添加一个id给…

postgis安装_从零开始,构建电子地图网站:0_2_数据处理postgis

软件安装完&#xff0c;开始数据处理。从China Historical GIS下载一份数据。一、数据下载数据来源&#xff1a;China Historical GIS&#xff1a;https://sites.fas.harvard.edu/~chgis/data/chgis/v6/先下载一份时间序列数据&#xff1a;Download CHGIS V6 TIME SERIES Datah…

sar图像去噪matlab,一种基于总曲率的SAR图像变分去噪方法与流程

本发明属于数字图像处理技术领域&#xff0c;具体涉及一种基于总曲率的SAR图像变分去噪方法。背景技术&#xff1a;&#xff1a;相干斑噪声是合成孔径雷达(Synthetic Aperture Radar&#xff0c;简称SAR)图像的重要特征&#xff0c;严重影响SAR图像的可解译性。相干斑噪声通常作…

课时2.浏览器和服务器(了解)

1.什么是浏览器&#xff1f; 浏览器就是由安装在我们电脑上的一款软件&#xff0c;QQ&#xff0c;百度影音等一样&#xff0c;都是安装在电脑上的一款软件 那这些软件之间由什么区别呢&#xff1f; 它们的区别就是它们的功能不太一样&#xff0c;QQ是用来聊天的&#xff0c;…

python 定义变量_用python解决动态的定义变量名(并给其赋值方法:大数据处理)...

前言&#xff1a;今天为大家带来的内容是&#xff1a;用python解决动态的定义变量名(并给其赋值方法&#xff1a;大数据处理)具有很好的参考价值&#xff0c;希望对大家有所帮助。喜欢本文内容的记得点赞转发收藏不迷路哦&#xff01;&#xff01;&#xff01;最近消费kafka数据…

课时39.细线表格(理解)

请你设计出以下图片里的这个样式的表格 步骤&#xff1a; 我先来制作一个两行两列的表格 2.将table里的cellspacing设置成0 外边距是不见了&#xff0c;但是和我们想要完成的图片有一定的差距&#xff0c;我们发现这样做出来的图片好像是两条线合并到了一起一样&#xff0c;实…

matlab拼碎纸片过程,碎纸片拼接复原模型

1. 引言破碎文件的拼接在司法物证复原、历史文献修复以及军事情报获取等领域都有着重要的应用。企事业、机关、院校和军队基于保密的需要&#xff0c;使用碎纸机对重要文件&#xff0c;单据以及材料进行销毁。一些重要的文件随着时间流逝&#xff0c;残破不全&#xff0c;因此&…

VC++编译MPIR 2.7.0

目录 第1章编译 2 1.1 简介 2 1.2 下载 3 1.3 解决方案 4 1.4 创建项目 5 1.5 复制文件树 6 1.6 不使用预编译头文件 8 1.7 包含目录 9 1.8 定义宏 10 1.9 编译前事件 11 1.10 修改 obj 的位置 13 1.11 编译yasm 14 1.12 编译汇编代码 …

导弹拦截

链接 分析&#xff1a;经典DP题&#xff0c;最长不下降子序列的变种&#xff0c;同时需要记录路径&#xff0c;用pre[]数组记录当前结点的前一个结点的方法很妙 1 #include "iostream"2 #include "cstdio"3 #include "cstring"4 #include "…

Spring中的@Cacheable开销

Spring 3.1引入了很棒的缓存抽象层 。 最后&#xff0c;我们可以放弃所有本地化的方面&#xff0c;装饰器和污染我们与缓存相关的业务逻辑的代码。 从那时起&#xff0c;我们可以简单地注释重量级方法&#xff0c;并让Spring和AOP机械完成工作&#xff1a; Cacheable("bo…

电工接线模拟仿真软件_VERICUT数控加工仿真软件,最强的数控加工模拟软件,你知道么?...

VERICUT数控加工仿真软件,最强的数控加工模拟软件VERICUT软件及功能简介1、VERICUT软件简介VERICUT是美国CGTech公司开发一款专业的数控加工仿真软件&#xff0c;是当前全球数控加工程序验证、机床模拟、工艺程序优化软件领域的领导者。该软件自1988年开始推向市场以来&#xf…

php数据库创建文件失败怎么回事,安装zblogPHP提示“创建c_option.php失败”解决方法...

有zblog用户反应在安装zblog的最后一步时提示“创建c_option.php失败”&#xff0c;如下图&#xff1a;本文来说明下这个问题的原因和解决办法。问题产生的原因&#xff1a;c_option.php是zblog的数据库配置文件&#xff0c;当安装完成的时候程序会自动创建这个文件。如果你的主…

CSS Variables

CSS原生变量(CSS自定义属性) 示例地址&#xff1a;https://github.com/ccyinghua/Css-Variables 一、css原生变量的基础用法 变量声明使用两根连词线"--"表示变量&#xff0c;"$color"是属于Sass的语法&#xff0c;"color"是属于Less的语法&a…

【基础中的基础】引用类型和值类型,以及引用传递和值传递

一直在博客园怼人&#xff0c;非常惭愧。所以郑重决定&#xff1a; 好好写一篇干货&#xff0c;然后再接着怼人。 这是一起帮上陈百万同学的求助&#xff0c;讲了一会之后&#xff0c;我觉得很有些普世价值&#xff0c;干脆就发到园子来。面向小白&#xff0c;高手轻拍。 我们从…

Java 7:使用NIO.2进行文件过滤–第3部分

大家好。 这是使用NIO.2系列进行文件过滤的第3部分。 对于那些尚未阅读第1 部分或第2部分的人 &#xff0c;这里有个回顾。 NIO.2是自Java 7起JDK中包含的用于I / O操作的新API。使用此新API&#xff0c;您可以执行与java.io相同的操作&#xff0c;以及许多出色的功能&#xf…

Hadoop Serialization -- hadoop序列化具体解释 (2)【Text,BytesWritable,NullWritable】

回想&#xff1a;回想序列化&#xff0c;事实上原书的结构非常清晰&#xff0c;我截图给出书中的章节结构&#xff1a;序列化最基本的&#xff0c;最底层的是实现writable接口&#xff0c;wiritable规定读和写的游戏规则 &#xff08;void write(DataOutput out) throws IOExce…

我需要多少个线程?

这取决于您的应用程序。 但是对于那些希望对如何从生产站点购买的所有昂贵内核中挤出更多资金的人来说&#xff0c;请多多包涵&#xff0c;我将阐明围绕多线程 Java应用程序的奥秘。 内容针对最典型的Java EE应用程序进行了“优化”&#xff0c;该应用程序具有Web前端&#xff…