有很长一段时间,我都想在博客中集成拟物化的访问计数器用于增加一些趣味性,可是我这网站一开始是纯静态的,没用到任何数据库,所以后边不了了之,但最近我在博客中赋予了一些动态能力,这个想法随之也就又浮现了出来。
这个创意最初来自大佬 Joshua Comeau 开源的 react-retro-hit-counter,但后续我产生了自己的一些想法。
本教程不会涉及任何关于数据库的东西,我假设你已经准备了一个数字,不关心你的数据来源,这里就以 1024
来做演示啦~
认识七段数码管
最初我只想实现一个类似计算器那种数字显示效果,它专业点叫做七段数码管(Seven-segment display),你可以在 wikipedia 上见到具体介绍,它一般长下边这种样子,地球人都见过:
这种形态还是比较好处理的,让我们先实现这个效果,最终要实现的霓虹灯效果也是以此为基础才行。
以下所有组件皆是用 tailwindcss
+ react
编写,为了教程简练省略了部分代码,具体请阅读源码。
SevenSegmentDisplay 组件开发
开发之前让我们先分析该组件有哪些部分构成,它可以拆分为哪些子组件?
- 入口组件,也就是父组件,我们将它命名为
SevenSegmentDisplay.jsx
。 - 数字单元组件,我们将它命名为
Digit.jsx
。 - 数字单元的片段,每个数字有 7 个片段,我们将它命名为
Segment.jsx
。
SevenSegmentDisplay
作为入口组件,它负责接收所有的 props 配置,并且将传入的 value 分解为单个数字后传给 Digit 组件。
Digit
一个 Digit 包含 7 个 Segment,通过控制不同 Segment 的点亮状态,便可以模拟数字显示。
Segment
根据 segmentId
以及激活状态用 SVG 渲染出对应的 Segment,这是一个不复杂但是比较繁琐的工作 🤖。
基础效果展示
到此,基础的显示组件已经完成了,让我们测试一下显示效果:
这是它的配置参数 👇
粗略一看还不错,但这与霓虹效果还相差甚远,因为它看起来有些扁平,边缘过于“锐利”,不够真实,所以接下来的目标是要把它变得更真实拟物一些。
如果你不需要霓虹效果,其实到这一步就足够了 😣,在我的网站中浅色模式也是使用的扁平风格,只有在切换到深色模式才会显示为拟物风格,算是一个小小的彩蛋吧。
霓虹灯效果
先分析一下为什么上边的样式看上去不够真实?
- 也许是曝光问题?真实世界中发光物本身相对于它的边缘来说看上去会更亮、更白,并且会稍微模糊一些。
- 很多情况下发光源做不到均匀照射到所有地方,所以会产生一片区域亮一片区域稍暗的效果,如果你留意过,很多透字键盘背光灯就是这样。
基于以上两点,接下来就想办法用 CSS 将它模拟的更真实一些。
让我们在 SevenSegmentDisplay
组件的基础上再封装一个 NeonHitCounter
组件。
模拟曝光过度效果
我们可以使用 CSS 中的 backdrop-filter
属性模拟过曝效果。
在上边代码中我们新建了一个 div 盖在 SevenSegmentDisplay
上边并使用 badckdrop-filter
使组件变亮变模糊,看上去效果已经好了不少。
模拟亮度不均匀效果
让我们将组件中间部分变得更亮,用于模拟亮度不均匀的效果。我们可以用 radial-gradient
创建一个白色径向渐变盖在它上边,然后通过 mix-blend-mode
来控制混合模式,这里用 overlay
比较合适。
有关
mix-blend-mode
的更多详细介绍你可以参考这篇文章。
在上边代码中又创建了一层 div,它利用 radial-gradient
+ mix-blend-mode: overlay
实现局部颜色增亮,并且根据颜色相对亮度动态判断增益比例,看起来是不是更真实了 👇
模拟玻璃质感
为了模拟透明玻璃质感,我用 Figma 画了一个 SVG 背景(也可以用 CSS 实现,我偷懒了),另外又用 conic-gradient
实现了 4 颗螺丝效果。
大功告成 ✨
Playground
最后我还给组件设置了一个闪烁效果动画,挑选一个喜欢的颜色尽情玩耍吧。