简单的下雨效果2.0版

前言

笔者上一篇发布的文章有趣的css—简单的下雨效果中有位老哥给我提了一个很棒的建议,大致意思是波纹应该产生于雨滴的消失处

这是按照老哥的建议完善后的效果图:



由于我制作GIF图片的工具最多只支持制作33FPS的GIF图,所以看起来可能有一点点卡顿,实际的效果比图片还是要好一些的,点击这里可以在线查看2.0版的效果。

思路

制作背景

首先给body中添加一个id为rain的div,并通过背景颜色线性渐变得到天空-地平线-海面的效果。

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta name="charset" content="utf-8"/>
  5. <title>简单的下雨效果2.0</title>
  6. </head>
  7. <body>
  8. <div id="rain"></div>
  9. </body>
  10. </html>
  1. #rain {
  2. position: relative;
  3. height: 100%;
  4. background: linear-gradient(#333,#999 ,#1f4794);
  5. background-repeat: no-repeat;
  6. background-size: 100% 100%;
  7. }

制作雨滴

通过设置背景颜色径向渐变得到圆形的水滴,再将其沿Y轴进行旋转得到椭圆形的水滴,最后给其添加水滴下落的动画效果。

  1. .raindrop {
  2. display: inline-block;
  3. position: absolute;
  4. top: 0;
  5. left: 150px;
  6. width: 5px;
  7. height: 5px;
  8. background: radial-gradient(#8fd4fc, #52b1f2, #0599fc);
  9. border-radius: 5000px;
  10. transform: rotateY(45deg);
  11. animation: raindrop .8s;
  12. }
  13. @keyframes raindrop {
  14. 0% {top:5%;}
  15. 10% {top:10%;}
  16. 20% {top:20%;}
  17. 30% {top:30%;}
  18. 40% {top:40%;}
  19. 50% {top:50%;}
  20. 60% {top:60%;}
  21. 70% {top:70%;}
  22. 80% {top:80%;}
  23. 90% {top:90%;}
  24. 100% {top:95%;}
  25. }

制作波纹效果

通过背景透明和圆形边框得到圆形的环,再将其沿X轴进行旋转得到椭圆形的环,最后给其添加环逐渐扩大的动画效果。

  1. .ripple {
  2. display: inline-block;
  3. position: absolute;
  4. top: 60vh;
  5. left: 50vh;
  6. border: 2px solid #8fd4fc;
  7. border-radius: 5000px;
  8. background: rgba(0, 0, 0, 0);
  9. transform: rotateX(72deg);
  10. animation: ripple .6s;
  11. }
  12. @keyframes ripple {
  13. 0% {
  14. width: 2px;
  15. height: 2px;
  16. }
  17. 10% {
  18. width: 4px;
  19. height: 4px;
  20. }
  21. 20% {
  22. width: 6px;
  23. height: 6px;
  24. }
  25. 30% {
  26. width: 8px;
  27. height: 8px;
  28. }
  29. 40% {
  30. width: 10px;
  31. height: 10px;
  32. }
  33. 50% {
  34. width: 12px;
  35. height: 12px;
  36. }
  37. 60% {
  38. width: 14px;
  39. height: 14px;
  40. }
  41. 70% {
  42. width: 16px;
  43. height: 16px;
  44. }
  45. 80% {
  46. width: 18px;
  47. height: 18px;
  48. }
  49. 90% {
  50. width: 20px;
  51. height: 20px;
  52. }
  53. 100% {
  54. width: 22px;
  55. height: 22px;
  56. }
  57. }

在雨滴被移除的位置添加波纹

通过计算移除雨滴的随机时间得到雨滴消失时距离顶部的距离。

  1. let clientWidth;
  2. let clientHeight;
  3. window.onload = function onload(){
  4. let rain = document.getElementById('rain');
  5. clientWidth = document.body.clientWidth;
  6. clientHeight = document.body.clientHeight;
  7. function dorpRain(){
  8. setTimeout(() => {
  9. if(typeof clientWidth !== 'undefined' && null !== clientWidth){
  10. let el = document.createElement('div');
  11. el.setAttribute('class', 'raindrop');
  12. let left = parseInt(Math.random() * clientWidth, 10) + 'px';
  13. el.style.left = left;
  14. rain.appendChild(el);
  15. let time = parseInt(Math.random() * 350, 10);
  16. setTimeout(() => {
  17. rain.removeChild(el);
  18. let newEl = document.createElement('div');
  19. newEl.setAttribute('class', 'ripple');
  20. newEl.style.left = left;
  21. newEl.style.top = parseInt(clientHeight / 100 * 50 + (time / 350 * (clientHeight / 100 * 50)), 10) + 'px';
  22. rain.appendChild(newEl);
  23. setTimeout(() => {
  24. rain.removeChild(newEl);
  25. }, 600)
  26. }, 400 + time, 10)
  27. }
  28. }, parseInt(10 + Math.random() * 10, 10))
  29. }
  30. dorpRain();
  31. }

使波纹以水滴消失位置为圆心扩散

其实到这一步还是有个问题,就是波纹是向右下方扩散的,下面是笔者将动画时间增大10倍,以及将波纹动画中的属性的宽高增大10倍后的效果:

产生此效果的原因是此时只能达到雨滴与波纹两个属性左上角的点重合,如果要使波纹以水滴消失位置为圆心扩散,需要让两个元素的中心点重合。

修改代码,先去掉rotate(原因后面再说),再使用translate(-50%, -50%)将元素向左上方移动,使两个元素的中心点等于雨滴被移除时的位置。

  1. .raindrop {
  2. /* 将transform: rotateY(45deg)改为transform: translate(-50%, -50%),其余不变*/
  3. transform: translate(-50%, -50%);
  4. /* ...... 其余的css不要删除*/
  5. }
  6. .ripple {
  7. /* 将transform: rotateX(75deg)改为transform: translate(-50%, -50%),其余不变*/
  8. transform: translate(-50%, -50%);
  9. /* ...... 其余的css不要删除*/
  10. }

效果图:



此时已经达到了波纹以水滴消失位置为圆心扩散,但要是加入了rotate之后,效果就完全不一样了:

  1. .raindrop {
  2. /* 将transform: translate(-50%, -50%)改为transform: rotateY(45deg) translate(-50%, -50%),其余不变*/
  3. transform: rotateY(45deg) translate(-50%, -50%);
  4. /* ...... 其余的css不要删除*/
  5. }
  6. .ripple {
  7. /* 将transform: translate(-50%, -50%)改为transform: rotateX(75deg) translate(-50%, -50%),其余不变*/
  8. transform: rotateX(75deg) translate(-50%, -50%);
  9. /* ...... 其余的css不要删除*/
  10. }

效果图:



可以看出此时的波纹是向下方扩散,这是为什么呢?

让我们先看一段很简单的代码:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta name="charset" content="utf-8"/>
  5. <title>测试</title>
  6. </head>
  7. <style type="text/css">
  8. * {
  9. padding: 0;
  10. margin: 0;
  11. }
  12. div {
  13. width: 100px;
  14. height: 100px;
  15. background-color: #fe0000;
  16. margin-top: 20px;
  17. }
  18. </style>
  19. <body>
  20. <div></div>
  21. <div style="transform: rotateX(75deg);"></div>
  22. </body>
  23. </html>

效果图:



rotateX会改变元素的高度,但其并不会改变元素在rotateX前占据的位置的大小!!!所以当我们使用同时使用 rotate 和translate(-50%, -50%)时并达到预期的效果。

就比如上面的数据,元素的宽高皆为100px,将其rotateX(75deg)后,宽度不变,translateX(-50%)会将元素移动到Y轴的中心线上;但此时元素的高度已经变为25.88px,translateY(-50%)只能将其向上移动12.94px,实际上是需要向上移动50px才能达到X轴的中心线上。

就比如下图(尝试将看待元素的视角从XY转移到YZ



A、B、C、D四条线,B的长度与A一致,AB之间的角度为45°,AD与CD之间皆为直角,那么根据正弦定理,C的长度等于B的长度的sin45°,也就是A的长度的sin45°。

元素rotateX(75deg)后,height由100px变为25.88,也就是:

100 * sin(90° - 75°)

= 100 * sin(15°)

= 100 * 0.25881904510252

≈ 100 * 0.2588

≈ 25.88

所以rotateY(45deg)

sin(45°)

= 0.70710678118655

≈ 0.71

要使雨滴达到rotateY(45deg)前 translateX(-50%)的效果,需要 translateX(-50% / 0.71) 约等于 translateX(-70%),也就是:

  1. .raindrop {
  2. /* 将transform: rotateY(45deg) translate(-50%, -50%)改为transform: rotateY(45deg) translate(-70%, -50%),其余不变*/
  3. transform: rotateY(45deg) translate(-70%, -50%);
  4. /* ...... 其余的css不要删除*/
  5. }

rotateX(75deg)

sin(90° - 75°)

= sin(15°)

= 0.25881904510252

≈ 0.26

同理,要使波纹达到rotateX(75deg)前translateY(-50%)的效果,需要 translateY(-50% / 0.26) 约等于 translateY(-192%) ,也就是:

  1. .ripple {
  2. /* 将transform: rotateX(75deg) translate(-50%, -50%)改为transform: rotateX(75deg) translate(-50%, -192%),其余不变*/
  3. transform: rotateX(75deg) translate(-50%, -192%)
  4. /* ...... 其余的css不要删除*/
  5. }

效果图:



随后再递归调用dorpRain方法,即可生成批量的雨滴以及对应的波纹。

结尾

笔者才疏学浅,慌忙之下难免有遗漏或是疏忽,如有错误之处,还望各位看官不吝赐教,笔者在此感谢。

最终的代码我放在简单的下雨效果2.0

作者:Fatman

博客园地址:https://www.cnblogs.com/liujingjiu

CSDN地址:https://blog.csdn.net/qq_35508835

版权归Fatman所有,欢迎保留原文链接进行转载:)

有趣的css—简单的下雨效果2.0版的更多相关文章

  1. 有趣的css—简单的下雨效果

    简单的下雨效果 前言 最近在b站上看到一个下雨效果的视频,感觉思路很清奇,我也按照自己的思路做了一个简单的下雨效果. 由于我制作GIF图片的工具最多只支持制作33FPS的GIF图,所以看起来可能有一点 ...

  2. 用PHP写的一个简单的分页类 1.0版

    <?php /* 分页类 用于实现对多条数据分页显示 version:1.0 author:Knight E-Mail:S.Knight.Work@gmail.com Date:2013-10- ...

  3. 用PHP写的一个简单的分页类 2.0版

    <?php /* 分页类 用于实现对多条数据分页显示 version:2.0 //基于1.0 数据库查询用mysqli实现 author:Knight E-Mail:S.Knight.Work@ ...

  4. 使用CSS实现一个简单的幻灯片效果

    方法一: 简单的CSS代码实现幻灯片效果 方法二: 使用CSS3 Animation来制作幻灯片 方法一: 简单的CSS代码实现幻灯片效果 话不多说,直接上代码 <!DOCTYPE html&g ...

  5. HTML与CSS简单页面效果实例

    本篇博客实现一个HTML与CSS简单页面效果实例 index.html <!DOCTYPE html> <html> <head> <meta charset ...

  6. Css实现一个简单的幻灯片效果页面

    使用animation动画实现一个简单的幻灯片效果. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 2 ...

  7. css实现简单音乐符效果

    css实现简单音乐符效果 利用css3中的transform.animation.keyframes实现 <!DOCTYPE html> <html lang="en&qu ...

  8. 3.8.1 HTML与CSS简单页面效果实例

    HTML与CSS简单页面效果实例 <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...

  9. 谈谈一些有趣的CSS题目(三)-- 层叠顺序与堆栈上下文知多少

    开本系列,讨论一些有趣的 CSS 题目,抛开实用性而言,一些题目为了拓宽一下解决问题的思路,此外,涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉 ...

随机推荐

  1. HTML的基础语法

    区别于c语言这类高级语言,HTML不是编程语言,而好似一种描述型语言,用于描述网页中内容的显示方式. HTML标记以<>来进行标记.HTML中的标记按其是否成对出现,可以分为单标记和双标记 ...

  2. 根据数据渲染DOM树形菜单——中途感想

    根据数据渲染DOM树形菜单,这个需求做了几天了.一开始觉得用while也可以实现一层一层查找数据,但后来发现while还是做不到,因为我查找这个动作必须有进入有出来然后进入下一个条目,但while只能 ...

  3. 攻防世界 reverse easy_Maze

    easy_Maze 从题目可得知是简单的迷宫问题 int __cdecl main(int argc, const char **argv, const char **envp) { __int64 ...

  4. windows与远程linux服务器进行文件传输

    在学习pwn时找到了http://pwnable.kr这个网站,很多题目通过ssh连接, ssh otp@pwnable.kr -p2222 (pw:guest) 连接脚本: pwn_ssh=ssh( ...

  5. 14、MyBatis教程之全部(包括所有章节)

    MyBatis 3.5.5 教程 1.环境准备 jdk 8 + MySQL 5.7.19 maven-3.6.1 IDEA 学习前需要掌握: JDBC MySQL Java 基础 Maven Juni ...

  6. 通过xshell实现内网linux上公网yum、apt-get安装软件

    环境:在内网,我的机器可上网,内网服务器不可上网,本来在我机器上开个代理,服务器直接通过我机器上网就可以,奈何网络配置太复杂,目前只有ssh端口可通. 先安装ccproxy软件,配置http监听端口为 ...

  7. 基于Hive进行数仓建设的资源元数据信息统计:Hive篇

    在数据仓库建设中,元数据管理是非常重要的环节之一.根据Kimball的数据仓库理论,可以将元数据分为这三类: 技术元数据,如表的存储结构结构.文件的路径 业务元数据,如血缘关系.业务的归属 过程元数据 ...

  8. 批量SSH key-gen无密码登陆认证脚本 附件脚本

    # 批量实现SSH无密码登陆认证脚本 ## 问题背景 使用为了让linux之间使用ssh不需要密码,可以采用了数字签名RSA或者DSA来完成.主要使用ssh-key-gen实现. 1.通过 ssh-k ...

  9. 【RocketMQ源码分析】深入消息存储(3)

    前文回顾 CommitLog篇 --[RocketMQ源码分析]深入消息存储(1) ConsumeQueue篇 --[RocketMQ源码分析]深入消息存储(2) 前面两篇已经说过了消息如何存储到Co ...

  10. java面试-公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解

    一.公平锁/非公平锁/可重入锁/递归锁/自旋锁谈谈你的理解 公平锁:多个线程按照申请的顺序来获取锁. 非公平锁:多个线程获取锁的先后顺序与申请锁的顺序无关.[ReentrantLock 默认非公平.s ...