侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

使用纯CSS实现动态晴阴雨雪(单标签)

前端  /  管理员 发布于 7年前   133

本期分享一下如何仅用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%,        65.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);    }}

 


 

实现原理就是通过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%,        65.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实现动态晴阴雨雪(单标签),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!


  • 上一条:
    纯css实现选中切换效果的示例
    下一条:
    css 中background 设置文本框背景图 的方法
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 使用 Alpine.js 排序插件对元素进行排序(0个评论)
    • 在js中使用jszip + file-saver实现批量下载OSS文件功能示例(0个评论)
    • 在vue中实现父页面按钮显示子组件中的el-dialog效果(0个评论)
    • 使用mock-server实现模拟接口对接流程步骤(0个评论)
    • vue项目打包程序实现把项目打包成一个exe可执行程序(0个评论)
    • 近期文章
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-06
    • 2017-07
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-03
    • 2018-04
    • 2018-05
    • 2018-06
    • 2018-09
    • 2018-11
    • 2018-12
    • 2019-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2021-04
    • 2021-05
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-11
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-09
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-02
    • 2024-03
    • 2024-04
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客