动机最近遇到了一个骨架屏的实现需求。粗略的研究了一下市面上应用广泛的骨架屏方案,发现其中很多方案都不能满足我的需求,比如or从第一张图可以看出,骨架屏中的元素都有自己独立的动画效果,也就是说,“波浪”不是从左边的元素跑到右边的元素,而是从每个元素的左边跑到每个元素的右边,看起来有些不雅。在第二个例子中,为了避免图1中暴露出的问题,改用了整体颜色渐变的方法。通过去除“波浪”效果,元素的动画效果看起来是统一的,但这显然让页面不那么“灵动”。另外,这两个骨架屏组件在实现上都采用了相似的接口。可以看出,这样的界面设计基本上决定了骨架屏中的元素只能是圆形或者矩形,布局方式也比较固定。同时动画效果比较固定,只有渐变和“波浪”两种。还有一种用svg的clipPath实现的骨架屏方案,基本解决了以上问题,缺点是使用起来有些困难。很多前端同学自己没有写过svg,不熟悉svg技术的用法和特点,所以这个方案的作者甚至专门实现了一个生成器工具,让用户可以使用这个骨架屏生成一组骨架屏通过gui界面。元器件的配置,可见使用门槛不低。那么有没有一种方法可以实现优雅的效果和灵活的配置界面,同时又简单易用,快速上手呢?首先,一个css动画效果只能在单个dom节点上执行,所以如果要实现元素间流动的“波浪”效果,为每个元素单独设置动画效果肯定是行不通的。所以为了实现一个可以在元素之间流动的“波浪”,我们给骨架屏一个全背景元素,并在背景元素上做一个“波浪”动画效果,然后通过一些方式实现一个带有镂空窗口的遮罩.实现镂空窗面罩,最简单直观的方案就是用几个不透明的元素遮住不需要镂空的位置,留下需要镂空的地方。这样处理矩形的镂空区域比较容易,但是如果要求镂空区域是圆形或者其他复杂的形状就很难实现了。而且从上图可以看出,这样的方案实现起来会很麻烦,尤其是当骨架屏元素的尺寸需要根据外界环境变化时,这个方案的实现难度会变高。代码也很难维护。那么,如果您实现一个简单且易于维护的面罩呢?至此,介绍一下我们文章的重点:mix-blend-mode。mix-blend-mode用于控制图层的混色模式。总共有16种模式。我们将重点关注变暗和变亮两种模式。这两种混色模式的逻辑可以参考这个链接。可以看到这两种模式的算法其实都很简单。在darken模式下混色时,直接取R、G、B三个通道中两种颜色中较小的值,反之,在lighten模式下,三个通道中的两种颜色取较大的值分别为R、G和B通道。再考虑上图中的场景,上层的外层是白色的,中间的矩形是黑色的。此时,如果将这一层的mix-blend-mode设置为lighten,那么外面的白色区域还是会保持白色,因为R、G、B三个通道的白色已经达到了最大值。至于中间的黑色矩形区域,由于黑色已经是R、G、B三个通道中的最小值,所以会成为下面图层的颜色。最终效果如下:到这里,我们已经可以通过mix-blend-mode实现一个简单的骨架屏效果了!再者,如果要求骨架屏的非动画元素部分不能为白色,怎么办?可能你已经想到了,我们使用mix-blend-mode在之前的颜色的基础上得到另一种颜色。如上图所示,我们再构建一个“掩码”。这次我们把最上面的外层设置为需求需要的骨架屏外层颜色,把中间的矩形区域设置为白色,然后给这一层mix-blend-mode设置为darken,这样下面的周边区域的白色在R、G、B三个通道中已经达到了最大值,所以调暗模式调色时会取最上面的颜色。出于同样的原因,中间矩形区域也会引导下方矩形区域的颜色。这样就实现了一个可以任意定义颜色范围的骨架屏组件。小结通过上面的例子,大家应该可以发现使用mix-blend-mode来实现遮罩效果,相比起文开头提到的方案,不仅功能灵活多样,而且非常好用文档。前端开发者只需要编写基本的DOM结构和样式就可以快速得到你想要的效果。而且,基于mix-blend-mode的mask还可以用在其他很多场景,比如下面的效果,选项的边框和选项中的money字符的渐变效果是连续的,如果你不使用遮罩,只能让设计师直接制作图片来实现,但是这样在国际化、深色模式、多分辨率适配等场景下会增加很多复杂度,但是会很简单要用mask来实现。我已经将相关代码封装成一个npm包:skeleton-screen-reactwelcomestar,issue,pr
