那些年下过的大雨
2018-02-01 11:48
225 查看
想了解一下用纯CSS和JS怎么实现一段下雨的动画,于是去CodePen上面搜了一下,发现了很多很有意思的东西。有空可以常去上面逛逛,在对技术产生敬畏的同时也能学到好多好多东西。以下是自己理解的几个代码实现过程,所有源码均出自于CodePen。
代码:github
效果:http://rynxiao.com/The-heavy-rain-in-those-years/
PS: 所有效果均在代码中以注释形式给出,不再额外进行补充,如果想了解更多细节,麻烦参考源码
雨滴容器模仿的是下降的过程,在下降过程的同时,改变真正雨滴的透明度,模仿出雨滴划过的轨迹
源码:https://codepen.io/arickle/pen/XKjMZY
雨滴的下降过程中,高度逐渐变小,因此造成了一种下落的堕落感,这点和第一个动画略有不同。
所有过程都是中心对齐,然后像周围扩散,例如下面的水珠,模拟的其实就是从中心点的原点上跳过程。
源码:https://codepen.io/Yakudoo/pen/doObLw
源码:https://codepen.io/towc/pen/VYbYvQ
源码:https://codepen.io/K-T/pen/YVYvdW
源码:https://codepen.io/vennsoh/pen/DuLbo
代码:github
效果:http://rynxiao.com/The-heavy-rain-in-those-years/
PS: 所有效果均在代码中以注释形式给出,不再额外进行补充,如果想了解更多细节,麻烦参考源码
淅沥淅沥
像一阵细雨打湿你心田,那感觉如此甜蜜。/** * 雨滴容器 * 宽度为15px,高度为120px * 0.5秒内从屏幕上方移动到屏幕90%的高度 * 模仿雨滴的下降过程 */ .drop { position: absolute; bottom: 100%; width: 15px; height: 120px; pointer-events: none; animation: drop 0.5s linear infinite; } @keyframes drop { 0% { transform: translateY(0vh); } 75% { transform: translateY(90vh); } 100% { transform: translateY(90vh); } }
雨滴容器模仿的是下降的过程,在下降过程的同时,改变真正雨滴的透明度,模仿出雨滴划过的轨迹
/** * 雨滴 * 宽度为1px,高度为120 * 0.6 = 72px * 设置从上到下的渐变色,模仿雨滴划过的轨迹 * 0.5s内由不透明变为透明,模仿雨滴下落碰撞到物体之后消失的情景 */ .stem { width: 1px; height: 60%; margin-left: 7px; background: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.25)); animation: stem 0.5s linear infinite; } @keyframes stem { 0% { opacity: 1; } 65% { opacity: 1; } 75% { opacity: 0; } 100% { opacity: 0; } } /** * 水花 * 雨滴碰撞到地面会溅起水花 * 宽度为15px,高度为10px * 设置上边框为点状,加上设置圆角,模拟水花溅起时的弧形 * 设置动画,当雨滴下降到地面时,透明度设置为1,同时通过设置缩放 * 模拟水花放大的过程 */ .splat { width: 15px; height: 10px; border-top: 2px dotted rgba(255, 255, 255, 0.5); border-radius: 50%; opacity: 1; transform: scale(0); animation: splat 0.5s linear infinite; /*display: none;*/ } @keyframes splat { 0% { opacity: 1; transform: scale(0); } 80% { opacity: 1; transform: scale(0); } 90% { opacity: 0.5; transform: scale(1); } 100% { opacity: 0; transform: scale(1.5); } }
源码:https://codepen.io/arickle/pen/XKjMZY
是离愁
犹记当时杏花雨,晓幕晨钟去孤舟。说好不回头,止不住,是离愁。/** * 雨滴 * 下落过程透明度由0变为1 * 高度由40px变为5px */ .drop { position: absolute; background: #fff; width: 2px; height: 40px; opacity: 0; left: 150px; animation: fall 0.2s ease-in forwards; } @keyframes fall { 0% { top: -100px; opacity: 0; height: 100px; } 99% { opacity: 1; } 100% { top: 150px; opacity: 0; height: 5px; } }
雨滴的下降过程中,高度逐渐变小,因此造成了一种下落的堕落感,这点和第一个动画略有不同。
/** * 波纹 * 沿X轴旋转75度,造成椭圆效果 * 动画效果: * 中心定格,设置波纹延迟,波纹逐渐变大造成扩散效果 * 先上在下再上,造成波纹的跌宕效果 */ #ripples { position: absolute; width: 300px; height: 300px; transform: rotateX(75deg); } .ripple { position: absolute; /* ... */ border: 6px solid rgba(255, 255, 255, 0.2); animation: grow ease-in-out forwards 1; } .ripple:nth-child(1) { animation-delay: 0s; animation-duration: 2s; } /* ... */ @keyframes grow { 0% { width: 1px; height: 1px; opacity: 0; transform: translateY(20px); } 25% { opacity: 0.5; transform: translateY(-10px); } 50% { transform: translateY(10px); } 100% { width: 250px; height: 250px; opacity: 0; transform: translateY(0); } }
所有过程都是中心对齐,然后像周围扩散,例如下面的水珠,模拟的其实就是从中心点的原点上跳过程。
/** * 水珠 * 中心定位 * 通过控制水花垂直方向位移,造成溅起效果 * 通过控制水平方向便宜,造成运动效果 */ @keyframes bounce1 { /* 中心点 */ 0% { left: 150px; top: 150px; opacity: 0; } /* 透明度 */ 5% { opacity: 0.5; } /* 上升 */ 50% { top: 104px; } /* 下降,同时左偏 */ 100% { left: 125px; top: 150px; opacity: 0; } }
源码:https://codepen.io/Yakudoo/pen/doObLw
错过
青春灿烂,炫如夏花。你说看过彩色的瀑布,我摸着你的头,笑得像个傻瓜。// 整个动画的关键点 // 整个动画其实是由一条条细线组成,根据下落的时差,造成瀑布的效果 // 根据计算出的屏幕宽度,每条细线1px,然后在屏幕上均匀分布360色 function anim() { window.requestAnimationFrame(anim); // 通过每次在绘制的细线上在绘制透明黑色,因此最先绘制的就会变暗,造成了尾巴的效果 ctx.fillStyle = repaintColor; ctx.fillRect(0, 0, w, h); for(var i = 0; i < total; ++i){ var currentY = dots[i] - 1; // 不断增加每次线段的长度,绘制每次最亮的那一部分 dots[i] += dotsVel[i] += accelleration; // 颜色其实在最开始就已经被分配出来了,根据点在的位置而定 ctx.fillStyle = 'hsl('+ colors[i] + ', 80%, 50%)'; ctx.fillRect(occupation * i, currentY, size, dotsVel[i] + 1); // 从上面出现的条件,也是造成时差的条件 if(dots[i] > h && Math.random() < .01){ dots[i] = dotsVel[i] = 0; } } } anim();
源码:https://codepen.io/towc/pen/VYbYvQ
路过
一个人的记忆就是座城市,时间腐蚀着一切建筑,把高楼和道路全部沙化。如果你不往前走,就会被沙子掩埋。所以我们泪流满面,步步回头,可是只能往前走。var RAIN_DROP = function(width, height, toInit, renderer){ this.width = width; this.height = height; this.toInit = toInit; this.renderer = renderer; this.init(); }; RAIN_DROP.prototype = { SCALE_RANGE : {min : 0.2, max : 1}, // 缩放比例 VELOCITY_RANGE : {min : -1.5, max : -1}, // 水平速度范围 VELOCITY_RATE : 3, // 垂直速度基值 LENGTH_RATE : 20, // 雨滴长度 ACCELARATION_RATE : 0.01, // 加速度比例 VERTICAL_OFFSET_RATE : 0.04, // 垂直偏移量 FRONT_THRESHOLD : 0.8, // 前景临界值(前面的雨滴不至于过小,后面的雨滴不至于过大) REFLECTION_RADIUS_RATE : 0.02, // 雨滴水花半径基值 COLOR : 'rgba(255, 255, 255, 0.5)', // 雨滴颜色 RADIUS_RATE : 0.2, // 用于设置全局透明度 THRESHOLD_RATE : 0.6, init: function(){ // 获取随机缩放比例 this.scale = this.renderer.getRandomValue(this.SCALE_RANGE); // 雨滴长度 this.length = this.LENGTH_RATE * this.scale; // 雨滴水平方向速度 this.vx = this.renderer.getRandomValue(this.VELOCITY_RANGE) * this.scale; // 雨滴垂直方向速度 this.vy = this.VELOCITY_RATE * this.scale; // 雨滴垂直方向加速度 this.ay = this.ACCELARATION_RATE * this.scale; // 角度 this.theta = Math.atan2(this.vy, this.vx); // 用于计算垂直方向是否出边界的偏移量 this.offset = this.height * this.VERTICAL_OFFSET_RATE; // 雨滴水平坐标值 this.x = this.renderer.getRandomValue({min : 0, max : this.width - this.height * Math.cos(this.theta)}); // 雨滴垂直坐标值 this.y = (this.toInit ? this.renderer.getRandomValue({min : 0, max : this.height}) : 0) - this.offset; // 水花半径 this.radius = this.length * this.REFLECTION_RADIUS_RATE; }, render: function(context, toFront){ // 如果雨滴在前面,但是缩放比例小于规定临界值,则去掉雨滴 // 如果雨滴在后面,但是缩放比例大于规定临界值,则去掉雨滴 // 保证了在背景前面的雨滴不至于太小,在背景靠后的雨滴不至于太大 if (toFront && this.scale < this.FRONT_THRESHOLD || !toFront && this.scale >= this.FRONT_THRESHOLD) { return true; } context.save(); context.strokeStyle = this.COLOR; // 如果雨滴的垂直方向坐标大于了临界值,则以水花的形式展示 // 否则以雨滴下落的方式展示 if (this.y >= this.height * (1 - (1 - this.scale) * this.THRESHOLD_RATE) - this.offset) { context.lineWidth = 3; context.globalAlpha = (1 - this.radius / this.length / this.RADIUS_RATE) * 0.5; context.beginPath(); context.arc(this.x, this.y, this.radius, Math.PI, Math.PI * 2, false); context.stroke(); context.restore(); this.radius *= 1.05; if (this.radius > this.length * this.RADIUS_RATE){ return false; } } else { context.lineWidth = 1; context.beginPath(); context.moveTo(this.x, this.y); context.lineTo(this.x + this.length * Math.cos(this.theta), this.y + this.length * Math.sin(this.theta)); context.stroke(); context.restore(); // 通过水平速度改变水平位移 this.x += this.vx; // 通过垂直速度改变垂直位移 this.y += this.vy; // 通过加速度,增加垂直方向的速度 // 因此雨滴并不是沿着直线运动,而是有一定的弧度 this.vy += this.ay; } return true; } };
源码:https://codepen.io/K-T/pen/YVYvdW
都是你
曾经想征服全世界,到最后回首才发现,这世界滴滴点点全部都是你。// 关键点 function loop() { requestAnimationFrame(loop); // 不断绘制半透明画布,用来造成尾巴效果 context.fillStyle = 'rgba(0, 0, 0, 0.2)'; context.fillRect(0, 0, canvas.width, canvas.height); var particle; var i, j, ilen, jlen; cursor.position.x += (mouseX - cursor.position.x)*0.1; cursor.position.y += (mouseY - cursor.position.y)*0.1; for (i = 0, ilen = particles.length; i < ilen; i++) { particle = particles[i]; // 通过速度控制角度大小,用来控制流星划过时的速度 particle.angle += particle.speed; // 以相同转动的速度向鼠标中心点不停的移动 particle.shift.x += (cursor.position.x - particle.shift.x) * particle.speed; particle.shift.y += (cursor.position.y - particle.shift.y) * particle.speed; // sin/cos 用来控制画圆 // orbit 半径轨道不断增加, force用来控制轨道系数,最低为0 // Math.sinx * (particle.orbit*particle.force) 表示以particle.orbit*particle.force为半径画圆 // 加上中心点坐标,造成不断围绕中心点旋转的效果 particle.position.x = particle.shift.x + Math.sin(i + particle.angle) * (particle.orbit*particle.force); particle.position.y = particle.shift.y + Math.cos(i + particle.angle) * (particle.orbit*particle.force); // 不断增加点的半径,最高为100 particle.orbit += (cursor.orbit - particle.orbit) * 0.01; context.beginPath(); // 根据点所在的位置,随机颜色 context.fillStyle = "hsl("+((particle.position.x/canvas.width + particle.position.y/canvas.height) * 180) + ", 100%, 70%)"; context.arc(particle.position.x, particle.position.y, particle.size/2, 0, Math.PI*2, true); context.fill(); } }
源码:https://codepen.io/vennsoh/pen/DuLbo
相关文章推荐
- 那些年下过的大雨
- 那些年,我们一起合作时头痛的事
- 《那些年啊,那些事——一个程序员的奋斗史》——96
- 《那些年啊,那些事——一个程序员的奋斗史》——98
- 《那些年啊,那些事——一个程序员的奋斗史》——100
- 《那些年啊,那些事——一个程序员的奋斗史》——101
- 那些年我们真的不懂沈佳宜
- 那些年我们一起的CSDN
- 那些年,我们一起敲过的代码
- 《那些年啊,那些事——一个程序员的奋斗史》——107
- 《那些年啊,那些事——一个程序员的奋斗史》——109
- 《那些年啊,那些事——一个程序员的奋斗史》——110
- 《那些年啊,那些事——一个程序员的奋斗史》——112
- 《那些年啊,那些事——一个程序员的奋斗史》——114
- 《那些年啊,那些事——一个程序员的奋斗史》——116
- 《那些年啊,那些事——一个程序员的奋斗史》——117
- 那些年我们一起听错的歌词!!!(笑死了都)
- 《那些年啊,那些事——一个程序员的奋斗史》——119
- 《那些年啊,那些事——一个程序员的奋斗史》——121
- [转]那些年我们一起清除过的浮动