纯CSS实现动态晴阴雨雪
1 引言
本期分享一下如何仅用CSS3,实现单标签的动态晴阴雨雪。技术关键点就是“单标签”和“纯CSS”。先看下最终效果:
再看看HTML代码:
<!--晴-->
<div class="weather sunny"></div>
<!--阴-->
<div class="weather cloudy"></div>
<!--雨-->
<div class="weather rainy"></div>
<!--雪-->
<div class="weather snowy"></div>
复制代码
没错,就是这么任性,每个动图就一个标签,而且无图无JS!下面就来详细介绍下技术实现。
涉及到的关键CSS3属性:
- transform:用于移位、旋转、缩放效果
- box-shadow:利用投影实现图像的复制(关键!)
- clip-path:基于绘制的形状对元素进行遮罩处理
- animation:设置元素的动画
以及实现单标签最关键的:before、:after伪元素运用。
通过本期分享,能学到什么?
最大的一点就是:box-shadow的另类玩法——“影分身”。
下面开始逐个讲解。
2 基础背景
图中的蓝块背景区域,很基础了,不用讲了。
设置了区域的宽高、背景色和圆角效果。
.weather {position: relative;display: inline-block;width: 180px;height: 240px;background: #23b7e5;border-radius: 8px;
}
复制代码
3 晴天
晴天图标由两个元素组成:太阳和内六角形阳光。
:before、:after 两个伪元素可以在元素内部分别“添加”一个元素,正好都利用上了。
3.1 绘制太阳
首先,用 :before实现太阳。
.sunny:before {content: "";position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);width: 60px;height: 60px;background: #F6D963;border-radius: 50%;box-shadow: 0 0 20px #ff0;z-index: 2;
}
复制代码
content用来生成一个元素。
position、top、left、transform用来实现中心居中。
box-shadow实现外发光效果,这只是box-shadow最基本最常用的使用方式。
3.2 绘制内六角形
用 :after实现内六角形。
实现的关键就是使用遮罩。通过clip-path绘制一个内六角形。这就变成了一个简单的初中几何问题。
内六角形由两个等边三角形拼合而成。
合并之后,我们可以把整体划分为若干个完全相同的小等边三角形。
在垂直方向做个辅助线,连接中间顶部和底部两点。不难发现,“垂直方向的最大长度”要大于“水平方向的最大长度”。
设小等边三角形的边长为1,以内六角形中心为坐标原点,可以计算出每个点的坐标,如下:
为了使用clip-path的百分比定位来绘制图像,下一步需要把长度坐标转换为百分比坐标。
设垂直方向最大长度为100%,仍以内六角形中心为坐标原点,每个点的坐标值转换如下:
由于clip-path绘制原点是在左上角,x轴右侧为正值,y轴下方为正值。需要做下坐标系转换。即:
新x轴坐标值 = 旧x轴坐标值 + 50%
新y轴坐标值 = (旧y轴坐标值 - 50%) * -1
使用clip-path的polygon方法绘制内六角形,坐标已通过上面的步骤计算出来了。
样式代码如下:
.sunny:after {content: "";position: absolute;top: 50%;left: 50%;margin: -45px 0 0 -45px; width: 90px;height: 90px;background: #FFEB3B;clip-path: polygon(50% 0%,64.43% 25%,93.3% 25%,78.87% 50%,93.3% 75%,64.43% 75%,50% 100%,35.57% 75%,6.7% 75%,21.13% 50%,6.7% 25%,35.57% 25%);z-index: 1;animation: sunScale 2s linear infinite;
}
@keyframes sunScale {0% {transform: scale(1);}50% {transform: scale(1.1);}100% {transform: scale(1);}
}
复制代码
※注:safari需要将clip-path改为-webkit-clip-path。由于代码太占篇幅,这里就不重复写两遍了。
<figcaption></figcaption>
实现原理就是通过clip-path绘制了一个内六角形遮罩,把黄颜色背景通过遮罩变成了最终的内六角形。
animation通过关键帧动画实现了“放大缩小”交替动效。
最终效果:
4 阴天
观察图形发现,有两个云朵:前面的白云和后面的乌云。貌似需要分别用 :before和 :after实现。如果这样做的话,后续章节的雨天和雪天的雨雪元素就没有多余的伪元素可用了。所以只能用一个伪元素实现两朵云。 这里就用到了box-shadow的“影分身”了!
由于后续章节的雨天和雪天都复用了云的样式,所以写在一起了,代码如下:
.cloudy:before,
.rainy:before,
.snowy:before {content: "";position: absolute;top: 50%;left: 25%;transform: translate(-50%, -50%);width: 36px;height: 36px;background: #fff;border-radius: 50%;z-index: 2;
}
复制代码
真实的元素(真身)就是一个圆。通过box-shodow来把投影作为“分身”。
先来看看box-shadow的属性:
box-shadow: h-shadow v-shadow blur spread color inset;
参数详解:
h-shadow: 阴影的水平偏移量。
v-shadow: 阴影的垂直偏移量。
blur: 模糊距离(就是渐变的距离,设为0就没有渐变)。
spread: 投影的尺寸,通过这个控制“影分身”的大小。
color: 投影颜色,通过这个实现后方的乌云。
inset: 改为内阴影。这里用不到。
先复制一个影分身试试:
box-shadow: #fff 22px -15px 0 6px;
复制代码
继续复制多个影分身,带全部影分身的完整代码如下:
.cloudy:before,
.rainy:before,
.snowy:before {content: "";position: absolute;top: 50%;left: 25%;transform: translate(-50%, -50%);width: 36px;height: 36px;background: #fff;border-radius: 50%;box-shadow: #fff 22px -15px 0 6px,#fff 57px -6px 0 2px, #fff 87px 4px 0 -4px,#fff 33px 6px 0 6px,#fff 61px 6px 0 2px,#ccc 29px -23px 0 6px,#ccc 64px -14px 0 2px,#ccc 94px -4px 0 -4px;z-index: 2;
}
复制代码
五个分身的白圆(#fff),三个分身的灰圆(#ccc)拼成了两朵云。
再给云朵加上“上下浮动”的动效:
.cloudy:before {animation: cloudMove 2s linear infinite;
}
@keyframes cloudMove {0% {transform: translate(-50%, -50%);}50% {transform: translate(-50%, -60%);}100% {transform: translate(-50%, -50%);}
}复制代码
5 雨天
云朵的代码直接复用第4章的阴天。这里使用 :after 伪元素实现雨滴。
先实现一个雨滴(为方便观看,暂时隐藏云朵):
.rainy:after {content: "";position: absolute;top:50%;left: 25%;width: 4px;height: 14px;background: #fff;border-radius: 2px;
}
复制代码
然后通过box-shadow“影分身”:
.rainy:after {content: "";position: absolute;top:50%;left: 25%;width: 4px;height: 14px;background: #fff;border-radius: 2px;
+ box-shadow:
+ #fff 25px -10px 0,
+ #fff 50px 0 0,
+ #fff 75px -10px 0,
+ #fff 0 25px 0,
+ #fff 25px 15px 0,
+ #fff 50px 25px 0,
+ #fff 75px 15px 0,
+ #fff 0 50px 0,
+ #fff 25px 40px 0,
+ #fff 50px 50px 0,
+ #fff 75px 40px 0;}
复制代码
再加入下雨的移动动效,修改如下:
.rainy:after {...(略)
+ animation: rainDrop 2s linear infinite; }
+ @keyframes rainDrop {
+ 0% {
+ transform: translate(0, 0) rotate(10deg);
+ }
+ 100% {
+ transform: translate(-4px, 24px) rotate(10deg);
+ box-shadow:
+ #fff 25px -10px 0,
+ #fff 50px 0 0,
+ #fff 75px -10px 0,
+ #fff 0 25px 0,
+ #fff 25px 15px 0,
+ #fff 50px 25px 0,
+ #fff 75px 15px 0,
+ rgba(255, 255, 255, 0) 0 50px 0,
+ rgba(255, 255, 255, 0) 25px 40px 0,
+ rgba(255, 255, 255, 0) 50px 50px 0,
+ rgba(255, 255, 255, 0) 75px 40px 0;
+ }
+ }
复制代码
动画添加了10度的旋转,让雨滴倾斜,以及垂直方向的移动。
这里的关键就是:虽然本质是垂直移动,但为了看上去是“循环”效果,需要将最下面的雨滴进行透明渐变,同时调节X和Y轴的值,让最终位置正好跟初始位置重合,就不会显得“断开”。
我们生成的是三行雨滴,第一行被云朵挡住了,实际能看到的是下面两行。在第一行移动到第二行位置的时候,原第三行已经透明看不见了,正好与初始状态一样,实现了无缝循环拼接。
6 雪天
雪天与雨天的区别就是把雨滴换成圆形,取消旋转角度。 代码如下:
.snowy:after {content: "";position: absolute;top:50%;left: 25%;width: 8px;height: 8px;background: #fff;border-radius: 50%;box-shadow:#fff 25px -10px 0,#fff 50px 0 0,#fff 75px -10px 0,#fff 0 25px 0,#fff 25px 15px 0,#fff 50px 25px 0,#fff 75px 15px 0,#fff 0 50px 0,#fff 25px 40px 0,#fff 50px 50px 0,#fff 75px 40px 0;animation: snowDrop 2s linear infinite;
}
@keyframes snowDrop {0% {transform: translateY(0);}100% {transform: translateY(25px);box-shadow:#fff 25px -10px 0,#fff 50px 0 0,#fff 75px -10px 0,#fff 0 25px 0,#fff 25px 15px 0,#fff 50px 25px 0,#fff 75px 15px 0,rgba(255, 255, 255, 0) 0 50px 0,rgba(255, 255, 255, 0) 25px 40px 0,rgba(255, 255, 255, 0) 50px 50px 0,rgba(255, 255, 255, 0) 75px 40px 0;}
}
复制代码
7 全部源码
源码如下,方便粘贴保存为html:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>单标签!纯CSS实现动态晴阴雨雪</title>
</head><body><div class="weather sunny"></div><div class="weather cloudy"></div><div class="weather rainy"></div><div class="weather snowy"></div>
</body>
<style>
.weather {position: relative;display: inline-block;width: 180px;height: 240px;background: #23b7e5;border-radius: 8px;
}
.sunny:before {content: "";position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);width: 60px;height: 60px;background: #F6D963;border-radius: 50%;box-shadow: 0 0 20px #ff0;z-index: 2;
}
.sunny:after {content: "";position: absolute;top: 50%;left: 50%;margin: -45px 0 0 -45px; width: 90px;height: 90px;background: #FFEB3B;clip-path: polygon(50% 0%,64.43% 25%,93.3% 25%,78.87% 50%,93.3% 75%,64.43% 75%,50% 100%,35.57% 75%,6.7% 75%,21.13% 50%,6.7% 25%,35.57% 25%);z-index: 1;animation: sunScale 2s linear infinite;
}
@keyframes sunScale {0% {transform: scale(1);}50% {transform: scale(1.1);}100% {transform: scale(1);}
}
.cloudy:before,
.rainy:before,
.snowy:before {content: "";position: absolute;top: 50%;left: 25%;transform: translate(-50%, -50%);width: 36px;height: 36px;background: #fff;border-radius: 50%;box-shadow: #fff 22px -15px 0 6px,#fff 57px -6px 0 2px, #fff 87px 4px 0 -4px,#fff 33px 6px 0 6px,#fff 61px 6px 0 2px,#ccc 29px -23px 0 6px,#ccc 64px -14px 0 2px,#ccc 94px -4px 0 -4px;z-index: 2;
}
.cloudy:before {animation: cloudMove 2s linear infinite;
}
@keyframes cloudMove {0% {transform: translate(-50%, -50%);}50% {transform: translate(-50%, -60%);}100% {transform: translate(-50%, -50%);}
}
.rainy:after {content: "";position: absolute;top:50%;left: 25%;width: 4px;height: 14px;background: #fff;border-radius: 2px;box-shadow:#fff 25px -10px 0,#fff 50px 0 0,#fff 75px -10px 0,#fff 0 25px 0,#fff 25px 15px 0,#fff 50px 25px 0,#fff 75px 15px 0,#fff 0 50px 0,#fff 25px 40px 0,#fff 50px 50px 0,#fff 75px 40px 0;animation: rainDrop 2s linear infinite;
}
@keyframes rainDrop {0% {transform: translate(0, 0) rotate(10deg);}100% {transform: translate(-4px, 24px) rotate(10deg);box-shadow:#fff 25px -10px 0,#fff 50px 0 0,#fff 75px -10px 0,#fff 0 25px 0,#fff 25px 15px 0,#fff 50px 25px 0,#fff 75px 15px 0,rgba(255, 255, 255, 0) 0 50px 0,rgba(255, 255, 255, 0) 25px 40px 0,rgba(255, 255, 255, 0) 50px 50px 0,rgba(255, 255, 255, 0) 75px 40px 0;}
}
.snowy:after {content: "";position: absolute;top:50%;left: 25%;width: 8px;height: 8px;background: #fff;border-radius: 50%;box-shadow:#fff 25px -10px 0,#fff 50px 0 0,#fff 75px -10px 0,#fff 0 25px 0,#fff 25px 15px 0,#fff 50px 25px 0,#fff 75px 15px 0,#fff 0 50px 0,#fff 25px 40px 0,#fff 50px 50px 0,#fff 75px 40px 0;animation: snowDrop 2s linear infinite;
}
@keyframes snowDrop {0% {transform: translateY(0);}100% {transform: translateY(25px);box-shadow:#fff 25px -10px 0,#fff 50px 0 0,#fff 75px -10px 0,#fff 0 25px 0,#fff 25px 15px 0,#fff 50px 25px 0,#fff 75px 15px 0,rgba(255, 255, 255, 0) 0 50px 0,rgba(255, 255, 255, 0) 25px 40px 0,rgba(255, 255, 255, 0) 50px 50px 0,rgba(255, 255, 255, 0) 75px 40px 0;}
}
</style>
</html>
复制代码
纯CSS实现动态晴阴雨雪相关推荐
- before css 旋转_单标签!纯CSS实现动态晴阴雨雪
引言 本期分享一下如何仅用CSS3,实现单标签的动态晴阴雨雪.技术关键点就是"单标签"和"纯CSS".先看下最终效果: 再看看HTML代码: <div c ...
- 有趣的纯CSS实现动态晴阴雨雪
我们先来看看实现的效果吧 非常的美腻,对吧.这个是纯css,且单标签实现的哦~ 先贴完整代码,我们再来看看这个里面究竟有什么可以借鉴的知识点 <!DOCTYPE html> <htm ...
- 单标签实现纯CSS实现动态晴阴雨雪
1 引言 本期分享一下如何仅用CSS3,实现单标签的动态晴阴雨雪.技术关键点就是"单标签"和"纯CSS".先看下最终效果: 再看看HTML代码: <!-- ...
- css单标签,单标签!纯CSS实现动态晴阴雨雪
封面.jpg 1 引言 本期分享一下如何仅用CSS3,实现单标签的动态晴阴雨雪.技术关键点就是"单标签"和"纯CSS".先看下最终效果: 效果预览.gif 再看 ...
- html如何动态显示天气,纯CSS实现动态的天气图标
单标签!纯CSS实现动态晴阴雨雪 .weather { position: relative; display: inline-block; width: 180px; height: 240px; ...
- html怎么把字做成动画效果,利用纯CSS实现动态的文字效果实例
大家可能经常会看到类似酷炫的网站: 在这类网站中能看到,一打开页面,无论是文字还是图片,都随着规定时间的而变化.原理很简单,主要用到CSS中animation属性. 接下来,我以我目前的工程项目为例, ...
- php动态字体,利用纯CSS实现动态的文字效果实例
相信大家都曾在网站中看到过中效果,一打开页面,无论是文字还是图片,都随着规定时间的而变化,今天我们将介绍如何通过用纯CSS来实现这种效果,下面一起来看看. 大家可能经常会看到酷炫的网站 在这类网站中能 ...
- 前端学习——纯CSS实现动态翻转导航条
纯CSS实现动态翻转导航条 在学习动画的时候,一开始不知道写一个生命东西来进行学习,后来在网上看到了一些CSS实现的动画效果,觉得很酷炫,就在其中选了导航条来进行学习,导航条比较基础而且用的比较多,以 ...
- 结合vue和纯css实现动态流量小球
前记 在数据可视化页面开发中,经常会有流量小球的开发需求.如何通过纯前端实现动态流量小球,而不需要使用设计小哥嗟来之图呢? 静态CSS实现波浪效果 探索前端实现波浪效果的过程中,我查阅到一些不同的实现 ...
最新文章
- eclipse插件之easyshell
- java ee cdi_Java EE CDI bean范围
- Leecode 136. 只出现一次的数字
- 如何判断线程池已经执行完所有任务了?
- 组件通信-父组件为子组件传递数据-静态数据//动态数据 // 数据校验
- SQL必知必会第五版笔记
- 苹果无线笔记本怎么连不上win服务器,苹果笔记本连不上无线_苹果笔记本连不上wifi...
- 2021年美赛M奖,圆我两年建模梦
- 英特尔cpu linux驱动程序,Intel处理器现身!Linux芯片组驱动放出
- 3d打印技术是计算机在哪一方面的应用,3D打印技术的应用范围 3D打印技术的应用领域有哪些?...
- 计算机毕业设计ssm农村老人管理系统的设计与实现36jlv系统+程序+源码+lw+远程部署
- 求俩向量角度 允许超过180度 python
- 驰网云数据库MySQL SQL Server
- crond atd 定时处理
- G - 。。。。。。。
- vue 格式化数值方法
- 如何把图片无损放大?教你图片怎么无损放大
- 鼎信设备设置通道增益,提高音量
- c++ opencv cv::solvePnPRansac 的使用和注意事项
- hackinglab基础关系列
热门文章
- 庄明浩回应熊猫直播被传破产:已离开挺久 不了解情况
- 【漏洞发现-1】操作系统之漏洞探针类型及利用
- 【论文精读】Temporal Fusion Transformers for Interpretable Multi-horizon Time Series Forecasting
- python帕多瓦数列前n项和的_几种求数列前n项和的方法
- [思想][管理]《壹百度》 -- 朱光
- 提醒软件如何设置语音提醒功能?
- 和Xiong的一段对话
- 规范的版权Copyright说明怎么写?
- uni-app h5、app模式下集成turn.js 翻书动画
- Cisco Viptela SD-WAN 基本部署