最近瞎逛的时候发现了一个超炫的粒子进度效果,有多炫呢?请擦亮眼镜!
1)进度条的实现没什么好说的,简单的一个 fillRect(0,0,long,20),long和20是分别进度条的长宽。然后每帧动画调用前将画布清除clearRect(0,0,canvas.width,canvas.height)。做出来应该是这样的(点击启动/暂停动画):
2)进度条色彩的变化。这个也简单,颜色渐变嘛,fillStyle = createLinearGradient() 就行了吧。不对哦,是颜色随时间变化,每一帧内的进度条颜色一样的哦。理所当然就能搞出一句:fillStyle = rgba(f(t),f(t),f(t),1),f(t)是随时间变化的函数。然而,这些只知道rgba的哥们,发现怎么调也调不出这样的渐变效果,rgb变化哪一个都会造成颜色明暗变化,卡壳了吧,这里估计要卡掉5%的人。要保持亮度不发生变化,这里要用到hsla这种颜色格式,就是妹子们自拍修图时常用的色调/饱和度/亮度/透明度。对照进度条的效果,明显我们只要改色调就OK了。
ctx.fillStyle = 'hsla('+(hue++)+', 100%, 40%, 1)';
结果可能是这样的(点击启动/暂停动画):
3)接下来进入正题,要做粒子效果了。粒子很多,观察力不好或者没掌握方法的同学这里就要歇菜啦(此处应有博主爽朗的笑声,哈哈哈~)。对于元素数量巨大的效果,我们应该尽可能缩小观察范围,只观察一个或者一组元素,找出单体的规律。多看几次,就能发现单个粒子是先向上运动一阵子然后掉下去,单个粒子的x轴应该是不变的。对于粒子集合来说,每个粒子的x坐标递增,就能产生我们需要的效果了。这里推荐同学们去看一下MDN的例程,超好玩的ball(好玩、ball?嘿嘿~):https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Advanced_animations
这里我们每帧只添加一个粒子:
var raf = null, c = document.createElement('canvas'), parent = document.getElementById('canvas-wrapper-test3'); c.width = 400; c.height = 100; c.id = 'canvas-test3'; parent.appendChild(c); var ctx = c.getContext('2d'), hue = 0, //色调 vy = -2, //y轴速度 par = [], //粒子数组 x = 0, //进度条当前位置 draw = function () { var color; ctx.clearRect(0,0,c.width,c.height); x += 3; //进度条速度为每帧3个像素 hue = (x > 310) ? 0 : hue; //颜色渐变为每帧1色调 color = 'hsla('+(hue++)+', 100%, 40%, 1)' ; par.push({ //用数组模拟队列 px: x + 40, py: 50, pvy: vy, pcolor: 'hsla('+(hue+30)+', 100%, 70%, 1)', }); x = (x > 310) ? 0 : x; //进度条到右侧后返回 ctx.fillStyle = color; ctx.fillRect(45, 40, x, 20); var n = par.length; while(n--){ //切记要随机差异化粒子y轴速度,否则就变成一根抛物线了 par[n].pvy += (Math.random()+0.1)/5; par[n].py += par[n].pvy; if (par[n].py > c.height ) { par.splice(n, 1); //掉到画布之外了,清除该粒子 continue; } ctx.fillStyle = par[n].pcolor; ctx.fillRect(par[n].px, par[n].py, 5, 5); } raf = window.requestAnimationFrame(draw); }; raf = window.requestAnimationFrame(draw);
虽然简单,但效果还是出来了(点击启动/暂停动画):
至此,这个动画效果基本完成了,后续要做的就是优化了:
1)增加粒子数量,现在我们每帧要push多个粒子进去,这样数量上就上来了。
3)增加随机化效果。现在xy起始坐标都跟进度条紧密联系在一起。我们每次生成几个粒子的话,粒子初始坐标应该在一定范围浮动,另外粒子的大小、颜色也应该要在小范围内随机化。颜色相对进度条颜色有一定滞后的话,效果会更加自然。
4)上面说到x方向不动,但是如果x方向增加一点抖动效果的话会更自然生动。
5)画布颜色混合选项设置线性叠加:globalCompositeOperation = 'lighter',这样在粒子重叠的时候颜色会有叠加的效果。这个是在源码上看到的,大牛就是细节会做得比别人好的家伙!关于这个属性的具体解释可以看看这位"大白鲨"的实验,中文的!
总结一下:想要实现一个效果,首先我们要简化模型,可以分成色彩的变化、位置的变化、大小的变化等,还有就是将某个因子独立出来看,通过各种抽茧剥丝的手法去找到效果后面的数学模型,然后编程去实现它。艺术总是源于生活,所以在做时候应该好好考虑是否应该加入惯性、弹性、重力这些效果,这些物理特性反映到效果中的话,会更加自然逼真。
都总结了,那完事了?
NO!NO!NO!
接下来才是我想要说的重点!上面的代码效果优化之后,老大看到效果觉得还不错哦,加到新项目去吧。。。然后就是啪啦啪啦ctrlC ctrlV?好吧,你也猜到了我要说什么,对的,复用和封装。
先看人家的源码,貌似这哥们连停止动画都没写呢,就一个无限循环。。。