转载自:http://blog.youkuaiyun.com/xllily_11/article/details/51444311
前端如何呼风唤雨
起初我创造了canvas 。
我说,要有雨,就有了雨;
我说,要有雪,就有了雪。
而对于前端来说,canvas即是天地
在canvas这个天地上,前端可以呼风唤雨,无所不能。
------------------------------------华丽的分割线-------------------------------------------------
文章起因
其实就是最近在做一个需求,需要有下雨下雪的动画特效, 故在这里做了一个drop的组件,来展现这种canvas常见的下落物体的效果。那么,=。= ,就让我们先看看效果吧。
[github地址] 之后贴出来哈。。。。
效果展示
调用代码
<code class="hljs html" style="display: block; padding: 0px; color: rgb(248, 248, 242); margin: 0px; border: 0px; vertical-align: baseline; overflow-x: auto; font-size: 12px; font-family: 'Source Code Pro', Consolas, Monaco, Menlo, Consolas, monospace; background: 0px 50%;"><span class="hljs-doctype" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><!DOCTYPE html></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">html</span> <span class="hljs-attribute" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">lang</span>=<span class="hljs-value" style="color: rgb(166, 226, 46); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">"en"</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">head</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">meta</span> <span class="hljs-attribute" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">charset</span>=<span class="hljs-value" style="color: rgb(166, 226, 46); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">"UTF-8"</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">title</span>></span>Document<span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">title</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">style</span>></span><span class="css" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">
<span class="hljs-id" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">#canvas</span><span class="hljs-rules" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">{
<span class="hljs-rule" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span class="hljs-attribute" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(102, 217, 239);">width</span>:<span class="hljs-value" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">100%</span></span></span>;
<span class="hljs-rule" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><span class="hljs-attribute" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(102, 217, 239);">height</span>:<span class="hljs-value" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"> <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">100%</span></span></span>;
}</span>
</span><span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">style</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">head</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">body</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">canvas</span> <span class="hljs-attribute" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">id</span>=<span class="hljs-value" style="color: rgb(166, 226, 46); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">"canvas"</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">canvas</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">script</span> <span class="hljs-attribute" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">src</span>=<span class="hljs-value" style="color: rgb(166, 226, 46); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">"canvasDrop.js"</span>></span><span class="undefined" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></span><span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">script</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"><<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">script</span>></span><span class="actionscript" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">
canvasDrop.init({
type: <span class="hljs-string" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">"rain"</span>, <span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">// drop类型,有rain or snow</span>
speed : [<span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0.4</span>,<span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">2.5</span>], <span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//速度范围</span>
size_range: [<span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0.5</span>,<span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">1.5</span>],<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//大小半径范围</span>
hasBounce: <span class="hljs-literal" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">true</span>, <span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//是否有反弹效果or false,</span>
wind_direction: -<span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">105</span> <span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//角度</span>
hasGravity: <span class="hljs-literal" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">true</span> <span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//是否有重力考虑</span>
});
</span><span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">script</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">body</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></<span class="hljs-title" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">html</span>></span>
</code>
下雨 下雪
看起来效果还是不错的,相对于使用创建dom元素来制作多物体位移动画, 使用canvas会更加容易快捷,以及性能会更好
源码讲解
好了,接下来讲解一下简单的实现原理 首先,先定义一些我们会用到的全局变量,如风向角度,几率,对象数据等
定义全局变量
<code class="hljs javascript" style="display: block; padding: 0px; color: rgb(248, 248, 242); margin: 0px; border: 0px; vertical-align: baseline; overflow-x: auto; font-size: 12px; font-family: 'Source Code Pro', Consolas, Monaco, Menlo, Consolas, monospace; background: 0px 50%;">
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//定义两个对象数据</span>
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//分别是drops下落物体对象</span>
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//和反弹物体bounces对象</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> drops = [], bounces = [];
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//这里设定重力加速度为0.2/一帧</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> gravity = <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0.2</span>;
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> speed_x_x, <span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//横向加速度</span>
speed_x_y, <span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//纵向加速度</span>
wind_anger; <span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//风向</span>
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//画布的像素宽高</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> canvasWidth,
canvasHeight;
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//创建drop的几率</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> drop_chance;
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//配置对象</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> OPTS;
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//判断是否有requestAnimationFrame方法,如果有则使用,没有则大约一秒30帧</span>
<span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">window</span>.requestAnimFrame =
<span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">window</span>.requestAnimationFrame ||
<span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">window</span>.webkitRequestAnimationFrame ||
<span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">window</span>.mozRequestAnimationFrame ||
<span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">window</span>.oRequestAnimationFrame ||
<span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">window</span>.msRequestAnimationFrame ||
<span class="hljs-function" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(249, 38, 114);"><span class="hljs-keyword" style="color: rgb(102, 217, 239); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">function</span>(<span class="hljs-params" style="color: rgb(248, 248, 242); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">callback</span>) </span>{
<span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">window</span>.setTimeout(callback, <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">1000</span> / <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">30</span>);
};
</code>
定义核心对象
接下来我们需要定义几个重要的对象 该组织所需定义的对象也比较少,总共才三个 在整个drop组件中共定义了`三个核心对象,分别是如下:
- Vector 速度对象,带有横向x,和纵向y的速度大小 单位为:V = 位移像素/帧
对于Vector对象的理解也十分简单粗暴,就是记录下落对象drop的速度/V
<code class="hljs javascript" style="display: block; padding: 0px; color: rgb(248, 248, 242); margin: 0px; border: 0px; vertical-align: baseline; overflow-x: auto; font-size: 12px; font-family: 'Source Code Pro', Consolas, Monaco, Menlo, Consolas, monospace; background: 0px 50%;">
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> Vector = <span class="hljs-function" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(249, 38, 114);"><span class="hljs-keyword" style="color: rgb(102, 217, 239); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">function</span>(<span class="hljs-params" style="color: rgb(248, 248, 242); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">x, y</span>) </span>{
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//私有属性 横向速度x ,纵向速度y</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.x = x || <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0</span>;
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.y = y || <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0</span>;
};
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//公有方法- add : 速度改变函数,根据参数对速度进行增加</span>
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//由于业务需求,考虑的都是下落加速的情况,故没有减速的,后期可拓展</span>
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">/*
* @param v object || string
*/</span>
Vector.prototype.add = <span class="hljs-function" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(249, 38, 114);"><span class="hljs-keyword" style="color: rgb(102, 217, 239); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">function</span>(<span class="hljs-params" style="color: rgb(248, 248, 242); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">v</span>) </span>{
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">if</span> (v.x != <span class="hljs-literal" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">null</span> && v.y != <span class="hljs-literal" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">null</span>) {
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.x += v.x;
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.y += v.y;
} <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">else</span> {
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.x += v;
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.y += v;
}
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">return</span> <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>;
};
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//公有方法- copy : 复制一个vector,来用作保存之前速度节点的记录</span>
Vector.prototype.copy = <span class="hljs-function" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(249, 38, 114);"><span class="hljs-keyword" style="color: rgb(102, 217, 239); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">function</span>(<span class="hljs-params" style="color: rgb(248, 248, 242); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></span>) </span>{
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//返回一个同等速度属性的Vector实例</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">return</span> <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">new</span> Vector(<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.x, <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.y);
};
</code>
- Drop 下落物体对象, 即上面效果中的雨滴和雪, 在后面你也可自己拓展为陨石或者炮弹
对于Drop对象其基本定义如下
<code class="hljs javascript" style="display: block; padding: 0px; color: rgb(248, 248, 242); margin: 0px; border: 0px; vertical-align: baseline; overflow-x: auto; font-size: 12px; font-family: 'Source Code Pro', Consolas, Monaco, Menlo, Consolas, monospace; background: 0px 50%;"><span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//构造函数</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> Drop = <span class="hljs-function" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(249, 38, 114);"><span class="hljs-keyword" style="color: rgb(102, 217, 239); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">function</span>(<span class="hljs-params" style="color: rgb(248, 248, 242); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></span>) </span>{
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">/* .... */</span>
};
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//公有方法-update </span>
Drop.prototype.update = <span class="hljs-function" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(249, 38, 114);"><span class="hljs-keyword" style="color: rgb(102, 217, 239); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">function</span>(<span class="hljs-params" style="color: rgb(248, 248, 242); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></span>) </span>{
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">/* .... */</span>
};
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//公有方法-draw</span>
Drop.prototype.draw = <span class="hljs-function" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(249, 38, 114);"><span class="hljs-keyword" style="color: rgb(102, 217, 239); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">function</span>(<span class="hljs-params" style="color: rgb(248, 248, 242); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></span>) </span>{
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">/* .... */</span>
};
</code>
看了上面的三个方法,是否都猜到他们的作用呢,接下来让我们了解这三个方法做了些什么
构造函数
构造函数主要负责定义drop对象的初始信息,如速度,初始坐标,大小,加速度等
<code class="hljs javascript" style="display: block; padding: 0px; color: rgb(248, 248, 242); margin: 0px; border: 0px; vertical-align: baseline; overflow-x: auto; font-size: 12px; font-family: 'Source Code Pro', Consolas, Monaco, Menlo, Consolas, monospace; background: 0px 50%;"><span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//构造函数 Drop</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> Drop = <span class="hljs-function" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(249, 38, 114);"><span class="hljs-keyword" style="color: rgb(102, 217, 239); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">function</span>(<span class="hljs-params" style="color: rgb(248, 248, 242); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></span>) </span>{
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//随机设置drop的初始坐标 </span>
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//首先随机选择下落对象是从从哪一边</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> randomEdge = <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.random()*<span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">2</span>;
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">if</span>(randomEdge > <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">1</span>){
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos = <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">new</span> Vector(<span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">50</span> + <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.random() * canvas.width, -<span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">80</span>);
}<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">else</span>{
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos = <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">new</span> Vector(canvas.width, <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.random() * canvas.height);
}
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//设置下落元素的大小</span>
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//通过调用的OPTS函数的半径范围进行随机取值</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.radius = (OPTS.size_range[<span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0</span>] + <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.random() * OPTS.size_range[<span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">1</span>]) *DPR;
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//获得drop初始速度</span>
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//通过调用的OPTS函数的速度范围进行随机取值</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.speed = (OPTS.speed[<span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0</span>] + <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.random() * OPTS.speed[<span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">1</span>]) *DPR;
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.prev = <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos;
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//将角度乘以 0.017453293 (2PI/360)即可转换为弧度。</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> eachAnger = <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0.017453293</span>;
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//获得风向的角度</span>
wind_anger = OPTS.wind_direction * eachAnger;
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//获得横向加速度 </span>
speed_x = <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.speed * <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.cos(wind_anger);
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//获得纵向加速度</span>
speed_y = - <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.speed * <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.sin(wind_anger);
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//绑定一个速度实例</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.vel = <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">new</span> Vector(wind_x, wind_y);
};
</code>
Drop对象的update方法
update方法负责,每一帧drop实例的属性的改变 如位移的改变
<code class="hljs javascript" style="display: block; padding: 0px; color: rgb(248, 248, 242); margin: 0px; border: 0px; vertical-align: baseline; overflow-x: auto; font-size: 12px; font-family: 'Source Code Pro', Consolas, Monaco, Menlo, Consolas, monospace; background: 0px 50%;">Drop.prototype.update = <span class="hljs-function" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(249, 38, 114);"><span class="hljs-keyword" style="color: rgb(102, 217, 239); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">function</span>(<span class="hljs-params" style="color: rgb(248, 248, 242); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></span>) </span>{
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.prev = <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos.copy();
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//如果是有重力的情况,则纵向速度进行增加</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">if</span> (OPTS.hasGravity) {
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.vel.y += gravity;
}
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos.add(<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.vel);
};
</code>
Drop对象的draw方法
draw方法负责,每一帧drop实例的绘画
<code class="hljs javascript" style="display: block; padding: 0px; color: rgb(248, 248, 242); margin: 0px; border: 0px; vertical-align: baseline; overflow-x: auto; font-size: 12px; font-family: 'Source Code Pro', Consolas, Monaco, Menlo, Consolas, monospace; background: 0px 50%;">Drop.prototype.draw = <span class="hljs-function" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(249, 38, 114);"><span class="hljs-keyword" style="color: rgb(102, 217, 239); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">function</span>(<span class="hljs-params" style="color: rgb(248, 248, 242); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></span>) </span>{
ctx.beginPath();
ctx.moveTo(<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos.x, <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos.y);
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//目前只分为两种情况,一种是rain 即贝塞尔曲线</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">if</span>(OPTS.type ==<span class="hljs-string" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">"rain"</span>){
ctx.moveTo(<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.prev.x, <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.prev.y);
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> ax = <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.abs(<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.radius * <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.cos(wind_anger));
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> ay = <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.abs(<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.radius * <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.sin(wind_anger));
ctx.bezierCurveTo(<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos.x + ax, <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos.y + ay, <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.prev.x + ax , <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.prev.y + ay, <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos.x, <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos.y);
ctx.stroke();
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//另一种是snow--即圆形 </span>
}<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">else</span>{
ctx.moveTo(<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos.x, <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos.y);
ctx.arc(<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos.x, <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos.y, <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.radius, <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0</span>, <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.PI*<span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">2</span>);
ctx.fill();
}
};
</code>
- bounce 下落落地反弹对象, 即上面雨水反弹的水滴, 你也可后期拓展为反弹的碎石片或者烟尘
定义的十分简单,这里就不做详细说明
<code class="hljs javascript" style="display: block; padding: 0px; color: rgb(248, 248, 242); margin: 0px; border: 0px; vertical-align: baseline; overflow-x: auto; font-size: 12px; font-family: 'Source Code Pro', Consolas, Monaco, Menlo, Consolas, monospace; background: 0px 50%;"><span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> Bounce = <span class="hljs-function" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(249, 38, 114);"><span class="hljs-keyword" style="color: rgb(102, 217, 239); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">function</span>(<span class="hljs-params" style="color: rgb(248, 248, 242); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">x, y</span>) </span>{
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> dist = <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.random() * <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">7</span>;
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> angle = <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.PI + <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.random() * <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.PI;
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos = <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">new</span> Vector(x, y);
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.radius = <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0.2</span>+ <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.random()*<span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0.8</span>;
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.vel = <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">new</span> Vector(
<span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.cos(angle) * dist,
<span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.sin(angle) * dist
);
};
Bounce.prototype.update = <span class="hljs-function" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(249, 38, 114);"><span class="hljs-keyword" style="color: rgb(102, 217, 239); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">function</span>(<span class="hljs-params" style="color: rgb(248, 248, 242); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></span>) </span>{
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.vel.y += gravity;
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.vel.x *= <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0.95</span>;
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.vel.y *= <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0.95</span>;
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos.add(<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.vel);
};
Bounce.prototype.draw = <span class="hljs-function" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(249, 38, 114);"><span class="hljs-keyword" style="color: rgb(102, 217, 239); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">function</span>(<span class="hljs-params" style="color: rgb(248, 248, 242); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></span>) </span>{
ctx.beginPath();
ctx.arc(<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos.x, <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.pos.y, <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">this</span>.radius*DPR, <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0</span>, <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.PI * <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">2</span>);
ctx.fill();
};
</code>
对外接口
update
即相当于整个canvas动画的开始函数
<code class="hljs javascript" style="display: block; padding: 0px; color: rgb(248, 248, 242); margin: 0px; border: 0px; vertical-align: baseline; overflow-x: auto; font-size: 12px; font-family: 'Source Code Pro', Consolas, Monaco, Menlo, Consolas, monospace; background: 0px 50%;"><span class="hljs-function" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(249, 38, 114);"><span class="hljs-keyword" style="color: rgb(102, 217, 239); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">function</span> <span class="hljs-title" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(166, 226, 46);">update</span>(<span class="hljs-params" style="color: rgb(248, 248, 242); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></span>) </span>{
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> d = <span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">new</span> <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Date</span>;
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//清理画图</span>
ctx.clearRect(<span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0</span>, <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0</span>, canvas.width, canvas.height);
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> i = drops.length;
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">while</span> (i--) {
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> drop = drops[i];
drop.update();
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//如果drop实例下降到底部,则需要在drops数组中清楚该实例对象</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">if</span> (drop.pos.y >= canvas.height) {
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//如果需要回弹,则在bouncess数组中加入bounce实例</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">if</span>(OPTS.hasBounce){
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> n = <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.round(<span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">4</span> + <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.random() * <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">4</span>);
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">while</span> (n--)
bounces.push(<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">new</span> Bounce(drop.pos.x, canvas.height));
}
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//如果drop实例下降到底部,则需要在drops数组中清楚该实例对象</span>
drops.splice(i, <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">1</span>);
}
drop.draw();
}
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//如果需要回弹</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">if</span>(OPTS.hasBounce){
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> i = bounces.length;
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">while</span> (i--) {
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> bounce = bounces[i];
bounce.update();
bounce.draw();
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">if</span> (bounce.pos.y > canvas.height) bounces.splice(i, <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">1</span>);
}
}
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//每次产生的数量</span>
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">if</span>(drops.length < OPTS.maxNum){
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">if</span> (<span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">Math</span>.random() < drop_chance) {
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">var</span> i = <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0</span>,
len = OPTS.numLevel;
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">for</span>(; i<len; i++){
drops.push(<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">new</span> Drop());
}
}
}
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//不断循环update</span>
requestAnimFrame(update);
}
</code>
init
init接口,初始化整个canvas画布的一切基础属性 如获得屏幕的像素比,和设置画布的像素大小,和样式的设置
<code class="hljs javascript" style="display: block; padding: 0px; color: rgb(248, 248, 242); margin: 0px; border: 0px; vertical-align: baseline; overflow-x: auto; font-size: 12px; font-family: 'Source Code Pro', Consolas, Monaco, Menlo, Consolas, monospace; background: 0px 50%;"><span class="hljs-function" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(249, 38, 114);"><span class="hljs-keyword" style="color: rgb(102, 217, 239); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">function</span> <span class="hljs-title" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(166, 226, 46);">init</span>(<span class="hljs-params" style="color: rgb(248, 248, 242); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">opts</span>) </span>{
OPTS = opts;
canvas = <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">document</span>.getElementById(opts.id);
ctx = canvas.getContext(<span class="hljs-string" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">"2d"</span>);
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">兼容高清屏幕,canvas画布像素也要相应改变</span>
DPR = <span class="hljs-built_in" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">window</span>.devicePixelRatio;
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//canvas画板像素大小, 需兼容高清屏幕,故画板canvas长宽应该乘于DPR</span>
canvasWidth = canvas.clientWidth * DPR;
canvasHeight =canvas.clientHeight * DPR;
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//设置画板宽高</span>
canvas.width = canvasWidth;
canvas.height = canvasHeight;
drop_chance = <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">0.4</span>;
<span class="hljs-comment" style="color: rgb(117, 113, 94); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">//设置样式</span>
setStyle();
}
<span class="hljs-function" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(249, 38, 114);"><span class="hljs-keyword" style="color: rgb(102, 217, 239); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">function</span> <span class="hljs-title" style="margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; color: rgb(166, 226, 46);">setStyle</span>(<span class="hljs-params" style="color: rgb(248, 248, 242); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;"></span>)</span>{
<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">if</span>(OPTS.type ==<span class="hljs-string" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">"rain"</span>){
ctx.lineWidth = <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">1</span> * DPR;
ctx.strokeStyle = <span class="hljs-string" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">'rgba(223,223,223,0.6)'</span>;
ctx.fillStyle = <span class="hljs-string" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">'rgba(223,223,223,0.6)'</span>;
}<span class="hljs-keyword" style="color: rgb(249, 38, 114); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">else</span>{
ctx.lineWidth = <span class="hljs-number" style="color: rgb(174, 129, 255); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">2</span> * DPR;
ctx.strokeStyle = <span class="hljs-string" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">'rgba(254,254,254,0.8)'</span>;
ctx.fillStyle = <span class="hljs-string" style="color: rgb(230, 219, 116); margin: 0px; padding: 0px; border: 0px; vertical-align: baseline;">'rgba(254,254,254,0.8)'</span>;
}
}
</code>
结束语
好了,一个简单的drop组件已经完成了,当然其存在着许多地方不够完善,经过本次drop组件的编写,对于canvas的动画实现,我相信在H5的场景中拥有着许多可发掘的地方。
最后说下不足的地方和后期的工作哈:
- 0、该组件目前对外接口不够多,可调节的范围并不是很多,抽象不是很彻底
- 1、 setStyle 设置 基本样式
- 2、 Drop 和Bounce 对象的 update 和 draw 方法的自定义,让用户可以设立更多下落的 速度和大小改变的形式和样式效果
- 3、 应增加对动画的pause,加速和减速等操作的接口