有趣的css—简单的下雨效果2.0版

2023-12-01 10:20

本文主要是介绍有趣的css—简单的下雨效果2.0版,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简单的下雨效果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版的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/440785

相关文章

Mysql表的简单操作(基本技能)

《Mysql表的简单操作(基本技能)》在数据库中,表的操作主要包括表的创建、查看、修改、删除等,了解如何操作这些表是数据库管理和开发的基本技能,本文给大家介绍Mysql表的简单操作,感兴趣的朋友一起看... 目录3.1 创建表 3.2 查看表结构3.3 修改表3.4 实践案例:修改表在数据库中,表的操作主要

springboot简单集成Security配置的教程

《springboot简单集成Security配置的教程》:本文主要介绍springboot简单集成Security配置的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录集成Security安全框架引入依赖编写配置类WebSecurityConfig(自定义资源权限规则

Vue中组件之间传值的六种方式(完整版)

《Vue中组件之间传值的六种方式(完整版)》组件是vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用,针对不同的使用场景,如何选择行之有效的通信方式... 目录前言方法一、props/$emit1.父组件向子组件传值2.子组件向父组件传值(通过事件形式)方

css中的 vertical-align与line-height作用详解

《css中的vertical-align与line-height作用详解》:本文主要介绍了CSS中的`vertical-align`和`line-height`属性,包括它们的作用、适用元素、属性值、常见使用场景、常见问题及解决方案,详细内容请阅读本文,希望能对你有所帮助... 目录vertical-ali

如何使用Python实现一个简单的window任务管理器

《如何使用Python实现一个简单的window任务管理器》这篇文章主要为大家详细介绍了如何使用Python实现一个简单的window任务管理器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 任务管理器效果图完整代码import tkinter as tkfrom tkinter i

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

浅析CSS 中z - index属性的作用及在什么情况下会失效

《浅析CSS中z-index属性的作用及在什么情况下会失效》z-index属性用于控制元素的堆叠顺序,值越大,元素越显示在上层,它需要元素具有定位属性(如relative、absolute、fi... 目录1. z-index 属性的作用2. z-index 失效的情况2.1 元素没有定位属性2.2 元素处

Python实现html转png的完美方案介绍

《Python实现html转png的完美方案介绍》这篇文章主要为大家详细介绍了如何使用Python实现html转png功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 1.增强稳定性与错误处理建议使用三层异常捕获结构:try: with sync_playwright(

Vue 调用摄像头扫描条码功能实现代码

《Vue调用摄像头扫描条码功能实现代码》本文介绍了如何使用Vue.js和jsQR库来实现调用摄像头并扫描条码的功能,通过安装依赖、获取摄像头视频流、解析条码等步骤,实现了从开始扫描到停止扫描的完整流... 目录实现步骤:代码实现1. 安装依赖2. vue 页面代码功能说明注意事项以下是一个基于 Vue.js

CSS @media print 使用详解

《CSS@mediaprint使用详解》:本文主要介绍了CSS中的打印媒体查询@mediaprint包括基本语法、常见使用场景和代码示例,如隐藏非必要元素、调整字体和颜色、处理链接的URL显示、分页控制、调整边距和背景等,还提供了测试方法和关键注意事项,并分享了进阶技巧,详细内容请阅读本文,希望能对你有所帮助...