客户端骨架屏详解

html-css013

客户端骨架屏详解,第1张

一直以来,客户端的应用中,为了提升应用的加载等待这段时间的用户感知体验,各种技术层出不穷。其中,尤以菊花图以及由它衍生各种加载动画最为突出。

对于菊花图我们自不必多说,现在对于加载的设计体验有了比菊花加载体验更棒的方法,即大家常看到的Skeleton Screen Loading,中文叫做骨架屏。

所谓Skeleton Screen Loading,即表示在页面完全渲染完成之前,用户会看到一个占位的样式,用以描绘了当前页面的大致框架,加载完成后,最终骨架屏中各个占位部分将被真实的数据替换。很多项目中都有相关的应用,如饿了么h5版本、知乎、facebook等网站中都有应用。 其效果如下图所示:

iOS实现Skeleton效果的第三方库有很多,当然也可以自己创建一个,而骨架屏最核心的就是占位和属性动画。在实现方面,本文介绍几种主流的实现方式:

实现原理

对UIView进行扩展,增加skeletonable、skeletonLayer等属性。调用showSkeleton方法,对属性skeletonable为true的视图进行遍历,找到其最上层的、skeletonable为true的子View,然后创建skeletonLayer添加到上面,构成骨架图,动效效果亦是在skeletonLayer层。需要隐藏效果时,调用hideSkeleton,同样进行遍历,移除skeletonLayer。

简单的说,在显示占位的时候,将tableView的代理设置为通过某个对象,这个对象根据cell的Idenfier创建cell并添加占位显示。关闭显示占位的时候,将代理tableView的代理切回ViewController,正常显示。

特点

1、不需手动写占位控件,不需处理圆角等问题,占位效果与实际控件布局一致。

2、缺点是有的控件是自适应大小,在未获得数据之前,控件位置是错误的,导致占位效果有问题。

同样是扩展UIView,添加属性somoContainer,表示占位视图的容器视图,其中每个占位区域都是一个SomoView。对于想要显示占位效果的View,需实现协议,在协议方法中返回SomoView列表。将这些SomoView添加到somoContainer,并显示。

特点

1、避免了上述自适应控件无数据时大小不正确的问题。

2、需要手工指定每个占位区域,且每个占位区域是UIView级别,不是CALayer。

除此之外,TABAnimated也是一个被使用的比较多的,同样TABAnimated也是扩展的UIView。在ios中集成TABAnimated需要经历以下几步:

1,Install

2,第二步(可选)

可以选择在appDelegate的didFinishLaunchingWithOptions方法全局设置动画属性,设有默认属性。例如:

3,第三步,设置animatedStyle属性

在需要动画的view上,将属性animatedStyle设置为TABTableViewAnimationStart,不需要动画的view不用做额外的操作。

4,第四步

1、将需要动的组件的属性loadStyle,设置为需要的类型,不需要动的组件不用做额外的操作;

2、(可选)新增属性tabViewWidth,其为动画开启时该组件的宽度,有较为合理默认值;

5,第五步

在获取到数据后,停止动画。

示例源码链接: iOS骨架屏示例

在Android中,骨架屏的实现也后很多的第三方框架,常见的有以下几个库:

ShimmerRecyclerView是一个带有闪光和指示效果的库,其运行效果如下图:

源码地址: https://github.com/sharish/ShimmerRecyclerView

Skeleton也是一个使用得比较广泛的库,它现在使用闪存动画的内存优化版本,因此速度更快,您也可以设置更大的布局动画。

项目源码: https://github.com/ethanhua/Skeleton

spruce-android

Spruce 是一个轻量级动画库,可帮助编排屏幕上的动画,该库同时还支持 iOS。

源码地址: https://github.com/willowtreeapps/spruce-android

Skeleton Screen(骨架屏) 指的在页面数据尚未加载前先给用户展示出页面的大致结构,直到请求数据返回后再渲染页面,补充进需要显示的数据内容。常用于内容列表页。

一、page-skeleton-webpack-plugin

page-skeleton-webpack-plugin 是一款由 ElemeFE 团队开发的webpack 插件,该插件的目的是根据你项目中不同的路由页面生成相应的骨架屏页面,并将骨架屏页面通过 webpack 打包到对应的静态路由页面中。

二、插件自动生成骨架屏的主要原理

先demo展示一下如何自动生成骨架屏,后续再通过代码具体分析如何生成骨架屏:

安装运行环境

依赖环境:

安装puppeteer可参考:https://www.jianshu.com/p/a9a55c03f768

启动puppeteer并打开要生成骨架屏的页面

接下来分析makeSkeleton是如何生成骨架屏代码

入口代码在 page-skeleton-webpack-plugin/src/skeleton.js

初始化核心逻辑:

具体各块的骨架结构如何生成的接下来会一一分析

1、SVG块生成骨架结构

非隐藏的元素,会把 svg 元素内部所有元素删除,减少最终生成的骨架页面体积,其次,设置svg 元素的宽、高和形状等。

2、按钮块生成骨架结构

button块的处理相对比较简单,去除边框和阴影,设定好统一的背景色和文字,按钮块就处理完成了。

3、背景块生成骨架结构

背景块指有背景图或者背景色的元素。统一设置背景色即可。

4、图片块生成骨架结构

5、伪元素块处理骨架结构

6、文本块处理骨架结构

文本块相对处理起来会比较复杂些,所以放到最后来讲。

文本块定义:任何包含文本节点的元素都是文本块。

计算文本块的文本行数、文字高度(即要绘制的文本块高度=fontSize):

通过线性渐变生成条纹背景的文本块:

单行文本需要计算文本宽度和text-aligin属性

以上就是elementUI开源的骨架屏插件的主要逻辑啦。当然还有涉及工程化相关的逻辑这里就没贴出来了,后续可以再慢慢探讨。

我抽空把生成骨架屏的逻辑单独抽出来,方便大家定制对骨架屏的工程化处理及调试

https://github.com/wookaoer/page-skeleton-core

骨架屏就是在页面数据尚未加载前先给用户展示出页面的大致结构,直到请求数据返回后再渲染页面,补充进需要显示的数据内容。常用于文章列表、动态列表页等相对比较规则的列表页面。

很多项目中都有应用:ex:饿了么h5版本,知乎,facebook等网站中都有应用。

借个图说例子:

facebook将用户固定的头像,author,日期和一小部分文字作为骨架主体

jira则是标题和logo对应的很整齐

linkedin可以说完全没有对齐,而是使用一种更加的展示骨架布局

slack则是使用混合的loading方式,有骨架图也有旋转圆,不仅如此,slack并没有全部使用同一种灰色值,不同的block的颜色代表的该区域的字体颜色,这又是一种切换顺滑度的提升。

不过他们都有一个共同点,就是采用简约的方式布局,我们可以以此为例,创造出独一无二的风格,来提高用户体验和加强品牌的风格,我想这会比一个loading logo带来更好的效果。

上面简单的介绍了一下骨架图,接下来我们来说一下具体实现吧。

优先我们实现一个简单的带有loading效果的骨架结构: