Skeleton Screen骨架屏

背景

传统的优化用户等待的体验 - 白屏使用动画,菊花图,加载进度条等:


image.png

It can be bad because progress indicators by definition call attention to the fact that someone needs to wait.
It’s like watching the clock tick down -when you do, time seems to go slower.

简介

骨架屏是在2015年由Luke提出的一种全新的优化用户等待体验的方案,它可以被视为是原来加载菊花图的一种升级版。
骨架屏可以理解为是当数据还未加载进来前,页面的一个空白版本。

image.png

下面的示例图是主流网站骨架屏实例。相比于传统的菊花图,骨架屏会在感官上觉得内容出现的流畅而不突兀,体验更加优良。


image.png

如下图所示,从左到右依次是Profile页面从初始化到最终content渲染完毕。
在页面完全渲染完成之前,用户会看到一个样式简单,描绘了当前页面的大致框架的骨架屏页面,然后骨架屏中各个占位部分被实际资源完全替换,这个过程中用户会觉得内容正在逐渐加载即将呈现,降低了用户的焦躁情绪,使得加载过程主观上变得流畅。


image.png

Immutable regions of a page are rendered instantly on load, appearing as neutral color blocks, and are gradually replaced with content such as images, headings, and interface labels.
This creates the sense that things are happening immediately as information is incrementally displayed on the screen.

骨架屏的生成方式

1. 手写骨架屏

自定义 样式/ 使用 插件,用来把我们写的骨架屏代码插入到页面模板的挂载点中,完成骨架屏的注入


image.png

2. 自动生成并插入静态骨架屏

以page-skeleton-webpack-plugin(饿了么开源的插件 )为例,它根据项目中不同的路由页面生成相应的骨架屏页面,并将骨架屏页面通过 webpack 打包到对应的静态路由页面中:

* Step1. 启动Puppeteer并打开要生成骨架屏的页面
const puppeteer = require('puppeteer');
const devices = require('puppeteer/DeviceDescriptors');
const iPhone = devices['iPhone 6'];
const { Skeleton } = require('page-skeleton-webpack-plugin');
let skeleton = new Skeleton();

(async () => {
    const browser = await (puppeteer.launch({
        timeout: 15000, //设置超时时间
        ignoreHTTPSErrors: true, //如果是访问https页面 此属性会忽略https错误
        devtools: true, // 打开开发者工具, 当此值为true时, headless总为false
        headless: false  // 非headless模式,为了能直观看到页面生成骨架屏的过程
    }));

    const page = await browser.newPage();
    await page.emulate(iPhone); // 因为是移动端,设置模拟iphone6
    await page.goto(‘XXX’); // 打开需要生成骨架屏的XXX网站
    await page.waitForSelector('.YYYY'); // 等待首屏加载完成
    await skeleton.makeSkeleton(page); // 开始build骨架屏
})();
* Step2. 构建骨架页面

在打开的页面进行 CSS 样式的覆盖,对元素进行增减,来生成骨架页面。

// page-skeleton-webpack-plugin/src/skeleton.js
async makeSkeleton(page) {
    const {defer} = this.options
    // 脚本路径在page-skeleton-webpack-plugin/src/script/index.js
    await page.addScriptTag({content: this.scriptContent}) // 把生成骨架屏代码注入puppeteer同时执行初始化
    await sleep(defer) // 延迟逻辑,用于等待某些异步操作
    await page.evaluate((options) => { // 在当前打开的页面实例上下文中执行方法
      Skeleton.genSkeleton(options) // 执行genSkeleton方法生成骨架屏
    }, this.options)
}
genSkeleton() -
image.png

image.png
  1. 将分类好的文本块,按钮块等处理生成骨架结构代码
    将页面划分为不同的块,然后分别对每个块进行处理,这样不会破坏页面整体的样式和布局。
    当我们最终生成骨架屏后,骨架屏的布局样式将和真实页面的布局样式完全一致,这样就达到了复用样式及页面布局的目的。
image.png
附: 初始化参数
image.png

image.png
* Step3. 根据 Puppeteer 渲染的骨架页面获取HTML 和 CSS
function getHtmlAndStyle() {
   const root = document.documentElement
   const rawHtml = root.outerHTML
   const styles = Array.from($$('style')).map(style => style.innerHTML || style.innerText)
   // other code
   const cleanedHtml = document.body.innerHTML
   return { rawHtml, styles, cleanedHtml }
}

总结:

通过 puppeteer 打开需要生成骨架屏的页面,
等待页面加载渲染完成之后,在保留页面布局样式的前提下,
对页面中元素进行删减或增添,对已有元素通过层叠样式进行覆盖,使得其展示为灰色块。
然后将修改后的 template和样式code提取出来,这样就生成骨架屏了。

image.png

Reference

https://uxdesign.cc/what-you-should-know-about-skeleton-screens-a820c45a571a
https://css-tricks.com/building-skeleton-screens-css-custom-properties/
https://github.com/dvtng/react-loading-skeleton
https://github.com/ElemeFE/page-skeleton-webpack-plugin
https://www.lukew.com/ff/entry.asp?1797
https://medium.com/mobify-design-team/designing-for-the-appearance-of-speed-aaabc7f568c2
https://blog.logrocket.com/improve-ux-in-react-apps-by-showing-skeleton-ui/
https://juejin.im/post/5c9890166fb9a070b8506341#heading-0

你可能感兴趣的:(Skeleton Screen骨架屏)