使用JavaScript和Canvas打造真实的雨滴效果

简介: 使用JavaScript和Canvas打造真实的雨滴效果 寸志 · 1 年前 我最近搞了一个有趣的项目——rainyday.js  。我认为这个项目并不怎么样,而且,事实上这是我第一次尝试接触一些比弹窗更复杂的JavaScript。

使用JavaScript和Canvas打造真实的雨滴效果

我最近搞了一个有趣的项目——rainyday.js  。我认为这个项目并不怎么样,而且,事实上这是我第一次尝试接触一些比弹窗更复杂的JavaScript。幸好,你们觉得它还有点意思。
rainyday.js想创建一个轻量的JavaScript类库,利用HTML5的canvas,来实现雨滴在玻璃上滑落的效果。很简单,不过有时候还是很有挑战的,尤其是在我们既要尽力避免动画区别于通常JavaScript的动画,又要保证动画流畅运行的时候。
在本文中,我将对整个方案进行介绍,也会介绍一些细枝末节,请原谅我。不过首先你可能需要先看看下面我准备好的示例,让你自己对我说的有一个真正的概念(点击图片,打开放在JSBin上的示例)。

Canvas图层

为了实现有层次的效果,动画使用了三个canvas,如下图所示。


最下面一层放置原始的图片,使用API将其缩放到需要的大小。图片直接被绘制在canvas上,然后做了模糊处理,看上去像失焦的效果,目前采用的是Mario Klingemann的Stack Blur Algorithm
中间这一层本质上是看不到的。它并不在DOM树中,但是我们可以用它来辅助绘制雨滴的反射效果。图片进行了相应的转置,这可以简化之后的绘制过程。
最后,顶层(玻璃),直接盖在第一层的上面,我们在这一层绘制滑落的雨滴。
整个想法很简单,也很容易理解。相对于一个canvas,分成三层让脚本更加简单,提高了代码的可读性和性能。

深入了解一下雨滴的绘制

对雨滴的渲染是rainday.js最重要的部分。小雨滴想对比较简单,但是对于大雨滴就有好几个因素需要考虑,必须保证雨滴的形状完全是随机的。
为了实现这个目标,rainday.js采用了某种算法使用折线来模拟一个圆形出来(参看Dan Gries的这篇文章Imperfect Circles )。因此,脚本渲染出来的雨滴形状就像下面这样:
算法输出是一系列点的链表,这些点的轨迹就是一个圆。画一个雨滴很简单,把这些点连接起来就行,画的时候,在半径上稍微做点随机就行。然后对我们选作反射的上做剪切就形成了最终的形状。

运行动画

最后的难题就是动画“引擎”。这个动画引擎由三个模块组成。后面的模块依赖于前一个。输出就是你在本文开头demo中看到的效果。这三个模块分别为:
1. rain模块——当调用rain()方法后,就是开启JavaScript的时间定时器。根据用户时间间隔的设置,这个模块会随机的将雨滴放在canvas上。雨滴的大小决定与预设值,因此用户可以控制动画中雨滴的大小和数量。使用demo中的一个作为例子,像下面这样调用rain(),就会每过100ms就在canvas放一个新的水滴。这些水滴大小的分布如下:88%的水滴在3到6之间(最小值3+一个在0到3之间的随机值);2%(0.9 - 0.88)的水滴是5,剩下的10%(1 - 0.9)是6到8之间。

engine.rain([

    engine.preset(3, 3, 0.88), engine.preset(5, 5, 0.9), engine.preset(6, 2, 1), ], 100); 

2. gravity模块——每当水滴加入到动画中后,就会有一个新的定时器出来控制雨滴在canvas上的运动,通过修改它位置的Y坐标来实现(当需要模拟雨滴以一定的角度下落时,使用同样的方法修改其X坐标)。目前rainday.js实现了两种不用的重力函数:GRAVITY_LINEAR(加速度一定的简单重力)和GRAVITY_NON_LINEAR(雨滴的移动看起来更随机一点)。设置重力函数只需要运行如下简单的代码:

engine.gravity = engine.GRAVITY_NON_LINEAR; 

3. trail模块——每次雨滴降落时都会运行这个函数,目的是为了绘制雨滴后面的尾巴。TRAIL_DROPS函数实现了由小雨滴组成的尾巴,而TRAIL_NONE则会取消尾巴。如下调用选择雨滴尾巴的效果:

engine.trail = engine.TRAIL_DROPS;

下一步

可以在githubmaroslaw/rainyday.js上找到rainday.js的源码,如果你喜欢,可以去看看。下一个版本(本文是根据0.1.1写的)我会实现雨滴间的碰撞检测,还包括一些我所想到的小的改进。欢迎留言、建议和任何形式的反馈。

原文:Creating a Realistic Rain Effect with Canvas and JavaScript

目录
相关文章
|
3月前
|
前端开发 JavaScript
验证码(原生js加canvas绘图)
验证码(原生js加canvas绘图)
20 0
|
3月前
|
前端开发 JavaScript
纯样式或使用JS的canvas实现图片旋转
纯样式或使用JS的canvas实现图片旋转
31 0
|
3月前
|
前端开发 JavaScript
验证码(原生js加canvas绘图)
验证码(原生js加canvas绘图)
15 0
|
4月前
|
JavaScript 前端开发
将base64格式的图片画到canvas上(js和vue两种)
将base64格式的图片画到canvas上(js和vue两种)
128 1
|
1月前
|
前端开发 JavaScript 容器
编程笔记 html5&css&js 032 HTML Canvas
编程笔记 html5&css&js 032 HTML Canvas
|
2月前
|
前端开发 JavaScript 开发者
Canvas库 fabric.js可以实现哪些功能? 动图介绍
fabric.js是一个canvas库,今天整理了一下fabric.js可以实现的功能,用动图的形式分享给大家,方便快速了解fabric.js。
Canvas库 fabric.js可以实现哪些功能? 动图介绍
|
7月前
|
前端开发 开发者
|
8月前
|
移动开发 前端开发 JavaScript
js实现canvas验证码功能
js实现canvas验证码功能
|
9月前
html+js+canvas实现雪花效果背景
话不多说先看图:
85 0
|
9月前
|
前端开发 JavaScript
验证码(原生js加canvas绘图)
验证码(原生js加canvas绘图)
50 0