简单的下雨效果2.0版

前言

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

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



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

思路

制作背景

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

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

制作雨滴

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

.raindrop {
display: inline-block;
position: absolute;
top: 0;
left: 150px;
width: 5px;
height: 5px;
background: radial-gradient(#8fd4fc, #52b1f2, #0599fc);
border-radius: 5000px;
transform: rotateY(45deg);
animation: raindrop .8s;
} @keyframes raindrop {
0% {top:5%;}
10% {top:10%;}
20% {top:20%;}
30% {top:30%;}
40% {top:40%;}
50% {top:50%;}
60% {top:60%;}
70% {top:70%;}
80% {top:80%;}
90% {top:90%;}
100% {top:95%;}
}

制作波纹效果

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

.ripple {
display: inline-block;
position: absolute;
top: 60vh;
left: 50vh;
border: 2px solid #8fd4fc;
border-radius: 5000px;
background: rgba(0, 0, 0, 0);
transform: rotateX(72deg);
animation: ripple .6s;
} @keyframes ripple {
0% {
width: 2px;
height: 2px;
}
10% {
width: 4px;
height: 4px;
}
20% {
width: 6px;
height: 6px;
}
30% {
width: 8px;
height: 8px;
}
40% {
width: 10px;
height: 10px;
}
50% {
width: 12px;
height: 12px;
}
60% {
width: 14px;
height: 14px;
}
70% {
width: 16px;
height: 16px;
}
80% {
width: 18px;
height: 18px;
}
90% {
width: 20px;
height: 20px;
}
100% {
width: 22px;
height: 22px;
}
}

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

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

let clientWidth;
let clientHeight;
window.onload = function onload(){
let rain = document.getElementById('rain');
clientWidth = document.body.clientWidth;
clientHeight = document.body.clientHeight; function dorpRain(){
setTimeout(() => {
if(typeof clientWidth !== 'undefined' && null !== clientWidth){
let el = document.createElement('div');
el.setAttribute('class', 'raindrop');
let left = parseInt(Math.random() * clientWidth, 10) + 'px';
el.style.left = left;
rain.appendChild(el); let time = parseInt(Math.random() * 350, 10); setTimeout(() => {
rain.removeChild(el); let newEl = document.createElement('div');
newEl.setAttribute('class', 'ripple');
newEl.style.left = left;
newEl.style.top = parseInt(clientHeight / 100 * 50 + (time / 350 * (clientHeight / 100 * 50)), 10) + 'px';
rain.appendChild(newEl); setTimeout(() => {
rain.removeChild(newEl);
}, 600)
}, 400 + time, 10)
}
}, parseInt(10 + Math.random() * 10, 10))
}
dorpRain();
}

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

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

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

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

.raindrop {
/* 将transform: rotateY(45deg)改为transform: translate(-50%, -50%),其余不变*/
transform: translate(-50%, -50%);
/* ...... 其余的css不要删除*/
}
.ripple {
/* 将transform: rotateX(75deg)改为transform: translate(-50%, -50%),其余不变*/
transform: translate(-50%, -50%);
/* ...... 其余的css不要删除*/
}

效果图:



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

.raindrop {
/* 将transform: translate(-50%, -50%)改为transform: rotateY(45deg) translate(-50%, -50%),其余不变*/
transform: rotateY(45deg) translate(-50%, -50%);
/* ...... 其余的css不要删除*/
}
.ripple {
/* 将transform: translate(-50%, -50%)改为transform: rotateX(75deg) translate(-50%, -50%),其余不变*/
transform: rotateX(75deg) translate(-50%, -50%);
/* ...... 其余的css不要删除*/
}

效果图:



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

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

<!DOCTYPE html>
<html>
<head>
<meta name="charset" content="utf-8"/>
<title>测试</title>
</head> <style type="text/css">
* {
padding: 0;
margin: 0;
} div {
width: 100px;
height: 100px;
background-color: #fe0000;
margin-top: 20px;
} </style>
<body>
<div></div>
<div style="transform: rotateX(75deg);"></div>
</body>
</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%),也就是:

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

rotateX(75deg)

sin(90° - 75°)

= sin(15°)

= 0.25881904510252

≈ 0.26

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

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

效果图:



随后再递归调用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. menuStrip鼠标滑过自动弹出

    public partial class FrmMain : Form { public FrmMain() { InitializeComponent(); } private void 退出系统T ...

  2. Apache Pulsar 在能源互联网领域的落地实践

    关于 Apache Pulsar Apache Pulsar 是 Apache 软件基金会顶级项目,是下一代云原生分布式消息流平台,集消息.存储.轻量化函数式计算为一体,采用计算与存储分离架构设计,支 ...

  3. gstreamer常用命令

    由于有好一段时间没做GStreamer相关项目了,早前的一些记录需要做下记录,以待需要的时候查阅. 还是分几个小节来介绍吧,这样思路清晰一点.(格式有点乱,没时间整理,读者自行脑补) 1. 播放视频. ...

  4. 8、MyBatis之使用注解开发

    9.使用注解开发 mybatis最初配置信息是基于 XML ,映射语句(SQL)也是定义在 XML 中的.而到MyBatis 3提供了新的基于注解的配置.不幸的是,Java 注解的的表达力和灵活性十分 ...

  5. 使用 Velero 跨云平台迁移集群资源到 TKE

    概述 Velero 是一个非常强大的开源工具,可以安全地备份和还原,执行灾难恢复以及迁移Kubernetes群集资源和持久卷,可以在 TKE 平台上使用 Velero 备份.还原和迁移集群资源,关于如 ...

  6. Java中的集合List - 入门篇

    前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的集合List - 入门篇>,希望对大家有帮助,谢谢 简介 说实话,Java中的集合有很多种,但是这里作为入门级别,先简单介绍第一种 ...

  7. SqlServer触发器的创建与使用

    前言 上期我们介绍了SqlServer的视图和存储过程创建与使用,这期我们介绍一下触发器. 有需要回顾的可以电梯直达看一下: SqlServer视图的创建与使用 SqlServer存储过程的创建与使用 ...

  8. Etcd常用运维命令

    目录 常用命令 常见操作 如何缩容? 如何扩容? 数据目录丢失或被误删除,节点启动失败或者加入集群报错? 操作步骤 操作步骤不正确的各种常见错误日志 常用命令 #查看集群member情况 etcdct ...

  9. [Fundamental of Power Electronics]-PART II-8. 变换器传递函数-8.1 Bode图回顾

    8.0 序 工程设计过程主要包括以下几个过程: 1.定义规格与其他设计目标 2.提出一个电路.这是一个创造性的过程,需要利用工程师的实际见识和经验. 3.对电路进行建模.变换器的功率级建模方法已经在第 ...

  10. 02_利用numpy解决线性回归问题

    02_利用numpy解决线性回归问题 目录 一.引言 二.线性回归简单介绍 2.1 线性回归三要素 2.2 损失函数 2.3 梯度下降 三.解决线性回归问题的五个步骤 四.利用Numpy实战解决线性回 ...