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

寸志 · 1 年前

我最近搞了一个有趣的项目——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

使用JavaScript和Canvas打造真实的雨滴效果的更多相关文章

  1. Rainyday.js – 使用 JavaScript 实现雨滴效果

    Rainyday.js 背后的想法是创建一个 JavaScript 库,利用 HTML5 Canvas 渲染一个雨滴落在玻璃表面的动画.Rainyday.js 有功能可扩展的 API,例如碰撞检测和易 ...

  2. 使用 JavaScript 和 canvas 做精确的像素碰撞检测

    原文地址:Pixel accurate collision detection with Javascript and Canvas 译者:nzbin 我正在开发一个需要再次使用碰撞检测的游戏.我通常 ...

  3. javascript的canvas绘图的基本用法

    <canvas>是HTML里面非常强大的元素,利用它结合js可以实现很多动画效果,大大增强交互性.下面,我想用图文并茂的方式阐述一下canvas的绘图机制的基础内容,话不多说,先上代码: ...

  4. 使用javascript和canvas画月半弯

    使用javascript和canvas画月半弯,月半弯好浪漫!浏览器须支持html5 查看效果:http://keleyi.com/a/bjad/8xqdm0r2.htm 以下是代码: <!do ...

  5. JavaScript之canvas

    num.push(x,y); 动画草图(举个栗子,我们把数字“2”给画出来): <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transit ...

  6. 每天一个JavaScript实例-canvas绘图

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  7. JavaScript修改Canvas图片

    用JavaScript修改Canvas图片的分辨率(DPI)   应用场景: 仓库每次发货需要打印标签, Canvas根据从数据库读取的产品信息可以生成标签JPG, 但是这个JPG图片的默认分辨率(D ...

  8. html加javascript和canvas类似超级玛丽游戏

    html加javascript和canvas制作 代码来源于网上 复制可用 <!doctype html><html lang="en"> <head ...

  9. JavaScript+html5 canvas实现本地截图教程

    这篇文章主要介绍了JavaScript+html5 canvas实现本地截图教程,对截图功能感兴趣的小伙伴们可以参考一下 最近有时间了解了下html5的各API,发现新浪微博的头像设置是使用canva ...

随机推荐

  1. Promise解决回调地狱(多层调用问题)

    Promise # Promise 是异步编程的一种解决方案:从语法上讲,promise是一个对象,从它可以获取异步操作的消息:从本意上讲,它是承诺,承诺它过一段时间会给你一个结果.promise有三 ...

  2. 安装pytorch

    安装cpu版本的 conda install pytorch-cpu torchvision-cpu -c pytorch 安装gpu版本的 conda install pytorch torchvi ...

  3. C++判断txt文件编码格式

    转载:https://blog.csdn.net/kikityan/article/details/89923808 记事本打开txt文件,然后另存,有四种编码格式可供选择,分别是:ANSI     ...

  4. 「Luogu P5368 [PKUSC2018]真实排名」

    PKUSC签到题 题目大意 给出一个长度为 \(N\) 的序列,序列中有 \(K\) 个数会乘二,对于每个数计算在乘二后大于等于这个数的个数与乘二前没有发生变化的方案数. 分析 思路很清晰,可以将答案 ...

  5. StaticLinkList(静态链表)

    写这个写了几次,然后都没写完就关掉了,所以也不想多码字了,直接上代码吧(本来还认真自制了一张图片来理解静态链表的cursor与sub之间的关系)但其实也就那么回事:通过游标来找下标通过下标找到对应的数 ...

  6. 浅谈Java三大特性之继承

    前言 简单用伪代码去介绍一些 父类与子类的构造函数问题 others 前言 类的继承性是面向对象语言的基本特性,多态性前提是继承性.Java 支持继承性和多态性.——Java从小白到大牛 继承:三大特 ...

  7. PB specified database is invalid

    拷贝资料库到其他机器,可以重新配置ODBC ,如果还是报错,建议删除log .

  8. centos7.4安装gitlab

    1. 安装依赖软件 yum -y install policycoreutils openssh-server openssh-clients postfix 2.下载gitlab安装包,然后安装 c ...

  9. Spring Boot 项目本地运行无异常,部署到 Linux 服务器运行报错:java.lang.ClassNotFoundException

    一 背景 最近在用 Springboot 开发项目 A,引了小伙伴开发的模块 B,本地起服务,运行的好好的,等部署到服务器上,一运行就报错:Caused by: java.lang.ClassNotF ...

  10. 从零构建以太坊(Ethereum)智能合约到项目实战——第24章 IPFS + 区块链

    P93 .1-IPFS环境配置P94 .2-IPFS+P .IPNS+P .个人博客搭建 - 如何在IPFS新增一个文件P95 .3-IPFS+P .IPNS+P .个人博客搭建 - 通过ipfs创建 ...