简单的下雨效果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. elf.h

    1 /* This file defines standard ELF types, structures, and macros. 2 Copyright (C) 1995-2019 Free So ...

  2. 在docker容器中使用cplex-python37

    技术背景 线性规划是常见的问题求解形式,可以直接跟实际问题进行对接,包括目标函数的建模和各种约束条件的限制等,最后对参数进行各种变更,以找到满足约束条件情况下可以达到的最优解.Cplex是一个由IBM ...

  3. CodeForces CF877D题解(BFS+STL-set)

    解法\(1:\) 正常的\(bfs\)剪枝是\(\Theta(nm4k)\),这个时间复杂度是只加一个\(vis\)记录的剪枝的,只能保证每个点只进队一次,并不能做到其他的减少时间,所以理论上是过不了 ...

  4. nginx 本地配置(解决跨域问题)

    前端做跨域本身就是扯淡的事情.后台人员不配合说什么都是白搭.索性整理了一下心得,(可以直接部署自配置)发不多说上代码: 1 #user nobody; 2 worker_processes 1; 3 ...

  5. 设计原则:单一职责(SRP)原则

    1 什么是单一职责(SRP)原则 单一职责原则的英文是 Single Responsibility Principle,缩写为 SRP.翻译过来就是:一个类或者模块只负责完成一个职责(或者功能). 所 ...

  6. 第一个 vue-cli项目

    第一个 vue-cli项目 什么是vue-cli vue-cli官方提供的一个脚手架,用于快速生成一个vue的项目模板: 预先定义好的目录结构及基础代码,就好比咱们在创建Maven项目时可以选择创建一 ...

  7. 【笔记】《Redis设计与实现》chapter17 集群

    17.1 节点 启动节点 Redis服务器启动时会根据cluster-enabled配置选项是否为yes来决定是否开启服务器的集群模式 节点会继续使用redisServer结构来保存服务器的状态,使用 ...

  8. 会议更流畅,表情更生动!视频生成编码 VS 国际最新 VVC 标准

    阿里云视频云的标准与实现团队与香港城市大学联合开发了基于 AI 生成的人脸视频压缩体系,相比于 VVC 标准,两者质量相当时可以取得 40%-65% 的码率节省,旨在用最前沿的技术,普惠视频通话.视频 ...

  9. Kubernetes Secrets

    Secrets 背景信息 Kubernetes版本 [09:08:04 yhf@test ~]$ kubectl version Client Version: version.Info{Major: ...

  10. Go-30-main包

    main包 package main import ( "fmt" "kubeflow-tool/main/cmd" "os" ) func ...