有趣的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

相关文章

Java实现Excel与HTML互转

《Java实现Excel与HTML互转》Excel是一种电子表格格式,而HTM则是一种用于创建网页的标记语言,虽然两者在用途上存在差异,但有时我们需要将数据从一种格式转换为另一种格式,下面我们就来看看... Excel是一种电子表格格式,广泛用于数据处理和分析,而HTM则是一种用于创建网页的标记语言。虽然两

利用Python编写一个简单的聊天机器人

《利用Python编写一个简单的聊天机器人》这篇文章主要为大家详细介绍了如何利用Python编写一个简单的聊天机器人,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 使用 python 编写一个简单的聊天机器人可以从最基础的逻辑开始,然后逐步加入更复杂的功能。这里我们将先实现一个简单的

vue解决子组件样式覆盖问题scoped deep

《vue解决子组件样式覆盖问题scopeddeep》文章主要介绍了在Vue项目中处理全局样式和局部样式的方法,包括使用scoped属性和深度选择器(/deep/)来覆盖子组件的样式,作者建议所有组件... 目录前言scoped分析deep分析使用总结所有组件必须加scoped父组件覆盖子组件使用deep前言

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

使用IntelliJ IDEA创建简单的Java Web项目完整步骤

《使用IntelliJIDEA创建简单的JavaWeb项目完整步骤》:本文主要介绍如何使用IntelliJIDEA创建一个简单的JavaWeb项目,实现登录、注册和查看用户列表功能,使用Se... 目录前置准备项目功能实现步骤1. 创建项目2. 配置 Tomcat3. 项目文件结构4. 创建数据库和表5.

使用PyQt5编写一个简单的取色器

《使用PyQt5编写一个简单的取色器》:本文主要介绍PyQt5搭建的一个取色器,一共写了两款应用,一款使用快捷键捕获鼠标附近图像的RGB和16进制颜色编码,一款跟随鼠标刷新图像的RGB和16... 目录取色器1取色器2PyQt5搭建的一个取色器,一共写了两款应用,一款使用快捷键捕获鼠标附近图像的RGB和16

四种简单方法 轻松进入电脑主板 BIOS 或 UEFI 固件设置

《四种简单方法轻松进入电脑主板BIOS或UEFI固件设置》设置BIOS/UEFI是计算机维护和管理中的一项重要任务,它允许用户配置计算机的启动选项、硬件设置和其他关键参数,该怎么进入呢?下面... 随着计算机技术的发展,大多数主流 PC 和笔记本已经从传统 BIOS 转向了 UEFI 固件。很多时候,我们也

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

基于Python实现PDF动画翻页效果的阅读器

《基于Python实现PDF动画翻页效果的阅读器》在这篇博客中,我们将深入分析一个基于wxPython实现的PDF阅读器程序,该程序支持加载PDF文件并显示页面内容,同时支持页面切换动画效果,文中有详... 目录全部代码代码结构初始化 UI 界面加载 PDF 文件显示 PDF 页面页面切换动画运行效果总结主

React实现原生APP切换效果

《React实现原生APP切换效果》最近需要使用Hybrid的方式开发一个APP,交互和原生APP相似并且需要IM通信,本文给大家介绍了使用React实现原生APP切换效果,文中通过代码示例讲解的非常... 目录背景需求概览技术栈实现步骤根据 react-router-dom 文档配置好路由添加过渡动画使用