奇迹开屏效果的纯 CSS 实现
起因
看到漫威App的开屏启动效果很好看想着用CSS
来实现一波,效果如图!
gif
本身可能有点掉帧,但是实际操作是非常丝滑的,让我一眼就狠狠爱上了!
第一个难点-如何实现一个镂空的U
我们首先来简单的拆解一下布局,首先这个镂空的U该如何实现
说来惭愧我也做了很久的前端了,最开始的这个难点就把我彻底男难倒了,首先我尝试使用background-clip: text
但是发现background-clip: text
的作用是把背景裁剪成文字,而这个需求的点是把文字从背景剪裁出来,后来经过了一些查找资料的过程我终于找到完美实现该方案的办法了。
mix-blend-mode
mix-blend-mode
CSS 属性描述了元素的内容应该与元素的直系父元素的内容和元素的背景如何混合。
mix-blend-mode中文直译为混合模式,相信很多人都听说过但是没有实际上手使用过(比如我...????
mix-blend-mode
模式可选的属性很多
mix-blend-mode: normal;
mix-blend-mode: multiply;
mix-blend-mode: screen;
mix-blend-mode: overlay;
mix-blend-mode: darken;
mix-blend-mode: lighten;
mix-blend-mode: color-dodge
mix-blend-mode: color-burn;
mix-blend-mode: hard-light;
mix-blend-mode: soft-light;
mix-blend-mode: difference;
mix-blend-mode: exclusion;
mix-blend-mode: hue;
mix-blend-mode: saturation;
mix-blend-mode: color;
mix-blend-mode: luminosity;
mix-blend-mode: initial;
mix-blend-mode: inherit;
mix-blend-mode: unset;
本文就不详细展开描述了,主要讲讲mix-blend-mode: darken
的使用
mix-blend-mode: darken
是一种CSS混合模式,它可以将元素的颜色与背景颜色进行混合。在这种模式下,元素的最终颜色将取决于源颜色和背景颜色的亮度。如果源颜色的亮度低于背景颜色的亮度,那么最终颜色将更接近于背景颜色。如果源颜色的亮度高于背景颜色的亮度,那么最终颜色将更接近于源颜色。
具体的算法是将每个颜色通道(红、绿、蓝)的值相加,然后将得到的值除以3然后比较源颜色和背景颜色的亮度。如果源颜色的亮度小于背景颜色的亮度,则使用源颜色作为最终颜色;否则,使用背景颜色作为最终颜色
举一个????如果我们的输入源颜色是白色,则不管背景是颜色都会只保留背景色,因为白色是最亮的颜色经过mix-blend-mode: darken
后无论如何都会比底色更亮所以只会保留底色啦!!效果如下
ok,我们的第一个难题就解决了,此时效果如下
第二个难点-如何实现一个描边的U
第一个问题解决后马上就碰到了第二个难题????,观察最初的效果我们可以发现动画进行中有一个白色的描边U渐隐渐显。
因为刚才用mix-blend-mode: darken
实现了一个镂空效果所以下意识的还想用mix-blend-mode
来扣除一个描边白色的镂空U,但是很快我就发现这是不可能的。
- 因为白色已经是最亮的颜色了所以
mix-blend-mode: darken
是不可能对白色的U产生什么效果 - 如果反其道而行之使用两个U叠加
mix-blend-mode: lighten
效果可以扣住一个U但是无法完成和效果图上类似的效果,因为不同字号的字体大小差距是不可控的。 - 布局异常麻烦= =!
text-stroke
CSS 属性
-webkit-text-stroke
指定了文本字符的笔触宽度和笔触颜色。此属性为全称属性 -webkit-text-stroke-width 和 -webkit-text-stroke-color 的简写属性。
其实仔细想想这个描边的白色U可以是一个透明颜色字体+白色描边,这两个要求text-stroke
一次性的都满足了!!
思路就是在镂空的U上再叠加一个字体颜色透明、text-stroke
白色的文本。此时效果如下
第三步-从中间展开的MARVEL
这个展开的MARVEL
效果,我们可以观察到是从中间逐渐往两边延伸,此时就要欢迎我们的clip-path
出场啦。
clip-path
CSS 属性使用裁剪方式创建元素的可显示区域。区域内的部分显示,区域外的隐藏。
我们从50% 50%
裁剪然后扩展到0% 0%
就可以完成类似的效果!
第四步-整体动起来~
此时我们的效果已经有点内味儿了,就是现在主体的U还不会动看着有点死板,观察效果能看出来最开始的U有一个放大缩小同时渐隐渐显,然后描边的白色U有一定的延时出现的效果!改造一下我们的代码
芜湖起飞!????
效果已经快要出来了,BUT,魔鬼都是藏在细节中,我们从效果图中看到,动画执行到末尾后整个背景图其实是从图片过渡到一个U。
第五步-图片过渡到U
有时候我确实感觉如果一个魔术师来转行做前端会不会很快上手,图片是不可能过渡到一个U上的,这又是我们的一个障眼法!在底图上叠加一个U在动画的结尾出现并且给一定量的偏移就可以让肉眼看起来从图片过渡到了一个U,但是在地图上叠加的U有几个注意事项。
- 需要一定的黑边
- 最后要产生一定量的偏移把黑边暴露出来
- 文字不是纯色而是渐变色!
问题一,我们依旧使用text-stroke
来搞定。
问题二,偏移没问题!使用transform: translate
轻松搞定。
问题三,不是纯色的文本omg,这个让我又苦思冥想了一阵,突然意识到在这个项目刚开始的难度一中我最开始想要使用的background-clip: text
属性不是完美实现嘛!
最终步-优化一些细节
呼呼,终于到最后一步了,说老实话我自己都没想到我真的可以仿照这个效果,没想到坚持下来了,给自己点个赞。到最后了我们就补上最后的一个UNLIMITED标题!
结束语
希望大家喜欢这个效果,也再次感叹一下,美国的app一些用户体验方面确实还领先我们国内不少,加油吧骚年!
掘金的代码审核应该有bug...
代码发到codepen了,点击查看