box-shadow 高阶玩法:纯 CSS 画蒙娜丽莎和粒子星空

news2024/11/14 21:11:29

想必写过 CSS 的同学都用过 box-shadow,它可以给元素设置阴影,增加立体效果。

比如说这样:

但它能做的可不只是阴影,还可以用来做出很多有趣的效果:

比如画蒙娜丽莎:

画星空:

这些效果都是 box-shadow 实现的!

是不是不敢相信?

今天我们就一起研究下 box-shadow 的高阶用法,来实现这些效果吧。

先过一下基础:

box-shadow 基础

box-shadow 可以设置 5 个值:x偏移量 y偏移量 阴影模糊半径 阴影扩散半径 阴影颜色

box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2); 

比如这个案例:

阴影中心点 x 轴偏移了 300px,y 轴偏移了 300px:

那阴影扩散半径是啥意思?

看这张图就明白了:

还有阴影模糊半径:

再来看下这几个值:

box-shadow: 300px 300px 30px 100px blue; 

x 轴位移、y 轴位移都是指中心点的位移。阴影的半径就是元素的 width/2 + 扩散半径 + 模糊半径。

而且 box-shadow 可以设置多个,通过逗号分隔,也就是多重阴影。

这样就可以用来做一些有意思的事情了:

比如把 width、height 设置为 0,然后设置多个阴影:

width、height 为 0,模糊半径为 0,扩散半径为 5px,那整个阴影就是一个 10px * 10px 的方块。

这样设置不同位置的 8 个阴影块就是上面的效果。

如果这样的块多了,是不是就类似像素块那样能展示图像了呢?

没错,蒙娜丽莎就是这么画出来的:

box-shadow 画蒙娜丽莎

整体思路上面已经分析出来了,就是通过 box-shadow 多重阴影设置每个像素块的颜色和位置:

这里 width、height 为 0,模糊半径为 0,扩散半径为 2px,那总体宽高就是 4px。

而每个块的中心点相距 5px,所以会留下一个间距。

我们试一下:

确实,通过这样一个个阴影块就能把蒙娜丽莎画出来。

然后我们把间距去掉,也就是把扩散半径设置大一点:

现在就连在一起了:

但这样看起来像素感太强了,我们给它加点模糊半径,比如设置个 4px:

这样好多了:

至此,神秘的蒙娜丽莎的微笑就完成了,只用到了 box-shadow 和一个 div!

这里是画了蒙娜丽莎,其实各种图片都能画,只要拿到像素数据就行,这个可以通过 canvas 的 getImageData 来拿到。

这里是一个个排列的阴影块,那如果随机打算这些阴影块,是不是可以做一些粒子效果呢?

比如星空。

我们来试一下:

box-shadow 画星空

星空大概是这样的:

画完蒙娜丽莎,我们知道了可以通过 box-shadow 多重阴影画出任意多个方块。不过那时是顺序排列的,现在我们希望把位置打乱,增加一些随机效果。

怎么随机呢?

css 里确实设置不了随机的东西,但是可以通过预处理器来做到,比如 sass。

我们通过 sass 来一个写循环生成随机 box-shadow 的函数:

@function multiple-box-shadow($n) {$value: '#{random(2000)}px #{random(2000)}px #FFF';@for $i from 2 through $n {$value: '#{$value} , #{random(2000)}px #{random(2000)}px #FFF';}@return unquote($value);
} 

这段代码是通过 @function 声明 sass 的函数,作用是传入 n,生成随机位置的白色 n 个阴影块。

声明了一个 $value 的变量作为初始值,然后循环生成 box-shadow 的值加到 $value 里,最后返回 $value,但要用 unquote 把引号去掉。

循环使用 @for $i from xx through yy 的语法,每次循环调用 random 函数生成 2000 内的随机整数。

这样就完成了 n 个随机位置的 box-shadow 的生成逻辑。

然后我们用一下它:

在 html 里放个 div:

<div id='stars'></div> 

给它设置宽高和 box-shadow:

#stars {width: 1px;height: 1px;box-shadow: multiple-box-shadow(700);
} 

这里就没有设置扩散半径和模糊半径了,所以阴影块大小就是元素的宽高。

效果是这样的:

看下现在的 css:

确实有随机生成的 700 个 box-shadow 值。

这就是预处理器的作用。

当然,这种逻辑也可以用 JS 来写,运行时生成随机 box-shadow,但是渲染速度上会比 sass 编译期间生成的方案慢很多。

然后我们让它动起来,加上 animation:

#stars {animation: animStar 50s linear infinite;
}
@keyframes animStar{from{transform: translateY(0px)}to {		transform: translateY(-2000px)}
} 

前面随机生成的 700 个星星的位置就是 0 到 2000px 的,所以这里是从 0 运动到 -2000px。

先把时间改短点,改成 3s 看下效果:

你会发现有段时间下面全是黑的,没有星星,这是为什么呢?

这个很容易想明白:当 translateY 快到 -2000px 的时候,剩下的部分星星不到一屏,其余的位置自然就没有星星了。

怎么解决这个问题呢?

其实这种还是比较经典的 CSS 问题,比如轮播图的无缝滚动也是同种原因。

解决方式就是在后面再接一个一模一样的,然后位移到了 -2000px 的时候,马上定位到 0 重新开始。这样就无缝了。

我们通过伪元素来设置这个:

$shadows-small:multiple-box-shadow(700);

#stars {width: 1px;height: 1px;box-shadow: $shadows-small;animation: animStar 3s linear infinite;&:after {content: " ";position: absolute;top: 2000px;width: 1px;height: 1px;box-shadow: $shadows-small;}
} 

注意,这里要保证两次的 box-shadow 是一样的,所以通过一个变量来保存生成的值,两处都引用这个变量。

这样就无缝了:

但现在还是有点假,我们多加两种不同大小不同运动速度的星星:

当然,个数也不一样,越大的越少,分别生成 200 和 100个,动画时长分别设置 100s 和 150s:

<div id='stars2'></div>
<div id='stars3'></div> 
$shadows-medium: multiple-box-shadow(200);
$shadows-big:multiple-box-shadow(100);

#stars2 {width: 2px;height: 2px;box-shadow: $shadows-medium;animation: animStar 100s linear infinite;&:after {content: " ";position: absolute;top: 2000px;width: 2px;height: 2px;box-shadow: $shadows-medium;}
}

#stars3 {width: 3px;height: 3px;box-shadow: $shadows-big;animation: animStar 150s linear infinite;&:after {content: " ";position: absolute;top: 2000px;width: 3px;height: 3px;box-shadow: $shadows-big;}
} 

看下效果:

星空的感觉是不是就出来了!

不过现在的代码还有点不优雅,star 的样式重复写了 3 次,既然用了 sass,那可以把它抽成一个 mixin 来复用:

@mixin stars($size, $duration, $boxShadow) {width: $size;height: $size;background: transparent;box-shadow: $boxShadow;animation: animStar $duration linear infinite;&:after {content: " ";position: absolute;top: 2000px;width: $size;height: $size;background: transparent;box-shadow: $shadows-small;}
} 

三处样式只要 include 这个 mixin,传入参数即可:

#stars {@include stars(1px, 50s, $shadows-small);
}

#stars2 {@include stars(2px, 100s, $shadows-medium);
}

#stars3 {@include stars(3px, 150s, $shadows-big);
} 

代码优雅了很多!

全部 scss 代码如下:

@function multiple-box-shadow($n) {$value: '#{random(2000)}px #{random(2000)}px #FFF';@for $i from 2 through $n {$value: '#{$value} , #{random(2000)}px #{random(2000)}px #FFF';}@return unquote($value);
}


$shadows-small:multiple-box-shadow(700);
$shadows-medium: multiple-box-shadow(200);
$shadows-big:multiple-box-shadow(100);

html {height: 100%;background: #000;overflow: hidden;
}

@mixin stars($size, $duration, $boxShadow) {width: $size;height: $size;background: transparent;box-shadow: $boxShadow;animation: animStar $duration linear infinite;&:after {content: " ";position: absolute;top: 2000px;width: $size;height: $size;background: transparent;box-shadow: $shadows-small;}
}

#stars {@include stars(1px, 50s, $shadows-small);
}

#stars2 {@include stars(2px, 100s, $shadows-medium);
}

#stars3 {@include stars(3px, 150s, $shadows-big);
}@keyframes animStar{from{transform: translateY(0px)}to {		transform: translateY(-2000px)}
} 

总结

box-shadow 我们一般用来做阴影,但其实也可以用来做一些有趣的效果。

阴影块的大小是由元素宽高、扩散半径、模糊半径这些决定的。

通过多重阴影顺序排列阴影块可以达到像素块的效果,画出蒙娜丽莎或者其他任意的图片。

也可以通过 sass 预处理器随机生成不同位置的阴影块来做出粒子效果,比如星空。

除了可以随机生成样式外,还可以通过 sass 的 mixin 来抽离相似的代码,多处复用,让 css 代码更优雅。这就是预处理器的意义。

box-shadow 的高阶玩法,你学会了么?

最后

整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。

有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享

部分文档展示:



文章篇幅有限,后面的内容就不一一展示了

有需要的小伙伴,可以点下方卡片免费领取

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/131996.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

尚医通-医院查询接口-上传科室接口(十九)

目录 &#xff08;1&#xff09;医院查询接口-功能实现 &#xff08;2&#xff09;上传科室接口-功能实现 &#xff08;1&#xff09;医院查询接口-功能实现 接口文档&#xff1a; 4.4.查询医院 医院信息 4.4.1.提交地址 http://localhost/api/hosp/hospital/show 在ApiC…

《东晋门阀政治》

《东晋门阀政治》 关于作者 田余庆&#xff0c;北京大学历史系教授&#xff0c;国务院古 籍整理出版规划小组成员&#xff0c;是魏晋南北朝 政治史专家。他在学术界拥有重要的地位&#xff0c;参加编著的《中国史纲要》曾获国家 教委特等奖。著有《秦汉魏晋史探微》 《拓跋史…

ubuntu 22.04上vim-plug插件管理器,相关插件与ROS2的安装

前言 最近&#xff0c;新配置了一版虚拟机&#xff0c;因为学校已经配置好环境的虚拟机忘了带回来&#xff0c;我还想系统的学习一下ROS&#xff0c;并将其用于机械臂的控制&#xff0c;因此用了新的方式配置了vim&#xff0c;并将树莓派raspberry buster系统配置上了ROS1的环…

Flink系列Table API和SQL之:滚动窗口、滑动窗口、累计窗口、分组聚合

Flink系列Table API和SQL之&#xff1a;窗口一、窗口(Window)二、分组窗口(Group Window)三、窗口表值函数(Windowing TVFs)1.滚动窗口(TUMBLE)2.滑动窗口(HOP)3.累计窗口(CUMULATE)四、分组聚合五、分组聚合实现代码六、分组窗口聚合代码实现七、窗口聚合&#xff1a;滚动窗口…

【SCL】博图SCL应用之音乐喷泉

使用Scl语言编写博图应用&#xff1a;音乐喷泉 文章目录 目录 一、音乐喷泉 1.控制要求 2.I/O分配 3.编写程序 4.效果和完整代码 二、装配流水线模拟控制&#xff08;练习&#xff09; 1.控制要求 2.场景 前言 承接上文&#xff0c;这里写一下上一篇的练习题 音乐喷泉应用案…

使用Typora+PicGo+SM.MS实现本地博客图片自动上传

使用TyporaPicGoSM.MS实现本地博客图片自动上传 Typora&#xff1a;一款Markdown 编辑器 PicGo: 一个用于快速上传图片并获取图片 URL 链接的工具. SM.MS: 一个图床网站&#xff0c;注册后有5G免费空间 为什么要让本地图片自动上传 对于一个随时随刻都有可能在文章中贴代码的计…

快来领取你的JavaScript正则表达式速查表

如果我们想对字符串进行相关&#xff08;增、删、改、查、检索&#xff09;操作&#xff0c;就可以用接下来的正则表达式实现 什么是正则表达式 正则表达式是用于匹配字符串中字符组合的模式正则表达式通常被用来检索、替换那些符合某个模式&#xff08;规则&#xff09;的文本…

家装中,你最后悔的事是什么?上海极家装修公司简介!

家装中&#xff0c;你最后悔的事是什么&#xff1f;上海极家装修公司简介&#xff01;接触过很多业主&#xff0c;就没有不后悔的!至于原因&#xff0c;因为总会出现各种“考虑不周”&#xff0c;有些真的是失之毫厘差之千里&#xff01; 下面上海极家装修公司简介&#xff01;…

Cadence每日一学_12 | 使用 Padstack Editor 制作贴片焊盘和通孔焊盘

最近在学习小马哥的Cadence课程&#xff0c;该系列课程为学习笔记&#xff1a;使用Cadence Allegro绘制小马哥DragonFly四轴飞行器(STM32F4主控)PCB四层板教程。 文章目录一、获取焊盘封装尺寸的途径二、Padstack Editor三、绘制贴片焊盘&#xff08;以电阻焊盘为例&#xff09…

Odoo 16 企业版手册 - 库存管理之产品类别

产品类别 您可以使用Odoo 库存模块中提供的产品类别功能对产品进行分类。为了执行各种产品操作&#xff0c;必须在Odoo中定义产品类别。Odoo将使产品更容易找到&#xff0c;因为它允许您按产品类别进行筛选。用户可以从库存模块的「配置」菜单访问「产品类别」窗口&#xff0c;…

【Python】sklearn机器学习之Birch聚类算法

文章目录基本原理sklearn调用基本原理 BIRCH&#xff0c;即Balanced Iterative Reducing and Clustering Using Hierarchies&#xff0c;利用分层的平衡迭代规约和聚类&#xff0c;特点是扫描一次数据就可以实现聚类&#xff0c; 而根据经验&#xff0c;一般这种一遍成功的算…

02 elf 的 binary 解析

前言 需求来自于 linux binary 的执行分析, 以及一些反编译工具的实现 比如 readelf, hopper disassemble 什么的 主要的目的是 更加详细了解 elf 的文件格式 为 后续的一些 理解做准备 elf 解析 elf 文件主要分为 四个部分 elfHeader, programHeaders, segments, …

2022年度盘点|聚焦运维服务,云智慧的高光时刻

回首2022&#xff0c;从IE 浏览器退役到AIGC 火遍全球&#xff0c;每一次科技的兴衰演进都打破着技术的新边界。与此同时&#xff0c;随着各行业数据规模爆发式地增长&#xff0c;云智慧作为国内全栈智能运维解决方案服务商&#xff0c;企业数字化地加速转型也为其带来了更多的…

Hibernate validator注解及Spring Boot自定义Hibernate Validator注解校验(超级详细)

一 Hibernate validator是什么 验证数据是贯穿整个应用层&#xff08;从表示层到持久层&#xff09;的常见任务。通常在每一层中都需要实现相同的验证逻辑&#xff0c;这样既耗时又容易出错。为了避免这些验证的重复&#xff0c;开发认原经常将验证逻辑直接捆绑到Model域中&…

1.9 基础综合案例|pyechart第三方包

文章目录json数据格式pyecharts模块介绍pyecharts快速入门数据处理这里使用比较经典的pyechart的第三方包。json数据格式 json是一种轻量级的数据交互形式。可以按照json指定的格式去组织和封装数据。或者这么说本质上json就是一个带有特定格式的字符串。 主要功能&#xff1…

【金猿案例展】正官庄——全渠道会员数据治理驱动商业增长

‍珍岛集团案例本项目案例由珍岛集团投递并参与“数据猿年度金猿策划活动——《2022大数据产业年度创新服务企业》榜单/奖项”评选。‍数据智能产业创新服务媒体——聚焦数智 改变商业随着商业品牌的全渠道裂变式发展&#xff0c;对DTC直营会员为中心的综合数据运营提出了新的…

【自学Java】Java基本数据类型

Java基本数据类型 Java基本数据类型 Java 基本数据类型如下表&#xff1a; 序号数据类型大小/位可表示的数据范围默认值1long&#xff08;长整数&#xff09;64-9223372036854775808&#xff5e;92233720368547758070L2int&#xff08;整数&#xff09;32-2147483648&#x…

设置 MYSQL 数据库编码为 utf8mb4

utf-8编码可能2个字节、3个字节、4个字节的字符&#xff0c;但是MySQL的utf8编码只支持3字节的数据&#xff0c;而移动端的表情数据是4个字节的字符。如果直接往采用utf-8编码的数据库中插入表情数据&#xff0c;java程序中将报SQL异常&#xff1a; java.sql.SQLException: Inc…

带音频播放的MPlayer播放器在ARM上的移植笔记

前言 mplayer想要播放带音频的视频文件&#xff0c;需要依赖alsa-lib和zlib&#xff0c;所以交叉编译mplayer前还需要先编译alsa-lib和zlib 一、alsa-lib alsa-lib 是 ALSA 提供的一套 Linux 下的 C 语言函数库&#xff0c;需要将 alsa-lib 移植到板卡上&#xff0c;这样基于…

人话解读LGPLv3

大家都知道&#xff1a;你调用了 LGPL的库&#xff0c;你还是可以开发一个闭源程序。这就说明&#xff0c;LGPL比GPL要宽松。但并不像想象的那么简单。一、为什么会有LGPL作为GPL的发明人Stallman&#xff0c;是自由软件的死忠坚定维护者&#xff0c;为什么还允许让别人用了自己…