评论

Skeleton Screen(骨架屏)

使用Skeleton Screen Loading,在页面数据尚未加载前先给用户展示出页面的大致结构,相较于传统loading的“菊花图”,用户体验会更好。

一、背景

用户体验一直是前端开发需要考虑的重要部分,在数据请求时常见到锁屏的loading动画,而现在越来越多的产品倾向于使用Skeleton Screen Loading(骨架屏)替代,以优化用户体验。
Skeleton Screen(骨架屏)就是在页面数据尚未加载前先给用户展示出页面的大致结构,直到请求数据返回后再渲染页面,补充进需要显示的数据内容。常用于文章列表、动态列表页。
我们都知道Ajax的请求,从客户端到服务端的数据请求之间有一段时间间隔,我们往往用一个loading图来提示用户数据正在加载来改善用户体验,就是我们经常用的菊花图:

loading图这种方式只能给提示用户,数据正在加载,但是这个时候页面往往是一片空白,视觉效果不是很好,在这里可以用另外一种方式来改善体验:Skeleton Screen,又称为骨架屏;即下面这种方式:

二、实现代码
完整例子:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Skeleton Screen</title>
  <style type="text/css">
    body {
    	background-color: #eaeef2;
    }

    .blog-container {
        width: 1200px;
        min-width: 1200px;
        margin: 0 auto;
        overflow: hidden;
    }

    .blog-wrap {
      	margin-top: 100px;
      	width: 860px;
    }

    .article {
    	position: relative;
        width: 100%;
        height: 214px;
        padding: 20px 30px;
        box-sizing: border-box;
        background-color: #fff;
        border-radius: 3px;
    }

    .article + .article {
    	margin-top: 10px;
    }

    .article-head {
    	width: 100%;
        height: 25px;
        line-height: 25px;
        font-size: 20px;
        margin-bottom: 15px;
        cursor: pointer;
        color: #00a67c;
    }

    .article-cover-box {
        float: left;
        margin-right: 20px;
        width: 200px;
        height: 123px;
    }

    .article-cover {
        width: 100%;
        height: 100%;
    }

    .article-content {
        width: calc(100% - 220px);
        height: 120px;
        color: #888;
        font-size: 14px;
        line-height: 24px;
        overflow: hidden;
    }

    .article-info {
        position: absolute;
        bottom: 0;
        right: 30px;
        min-width: 300px;
        height: 20px;
        line-height: 20px;
        margin-bottom: 10px;
        overflow: hidden;
        text-align: right;
    }

    .article_info_item {
        font-size: 13px;
        color: #999;
    }

    .article_info_item + .article_info_item {
    	margin-left: 20px;
    }


    @keyframes placeHolderShimmer {
        0% {
            background-position: -860px 0
        }
        100% {
            background-position: 860px 0
        }
    }

    .animation-loading .animated-background {
        animation-duration: 2s;
        animation-fill-mode: forwards;
        animation-iteration-count: infinite;
        animation-name: placeHolderShimmer;
        animation-timing-function: linear;
        background: #f6f7f8;
        background: linear-gradient(to right, #eeeeee 8%, #dddddd 18%, #eeeeee 33%);
        background-size: 860px 104px;
    }
  </style>
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>

<body>
  <div id="main" class="blog-container">
      <div class="blog-wrap">
          <div class="article" :class="{'animation-loading': loading}" v-for="(article, index) in list" :key="index">
              <div class="article-head animated-background">{{article.title || ''}}</div>
              <div class="article-cover-box animated-background">
                  <img class="article-cover" v-if="article.bg" :src="article.bg">
              </div>
              <div class="article-content animated-background">{{article.content || ''}}</div>
              <div class="article-info animated-background">
                  <span class="article_info_item">{{article.author || ''}}</span>
                  <span class="article_info_item">{{article.createdTime || ''}}</span>
                  <span class="article_info_item">{{article.viewNum || ''}}</span>
              </div>
          </div>
      </div>
  </div>
</body>

<script>
    var vm = new Vue({
        el: '#main',
        data: {
            loading: false,
            list: [{}, {}, {}, {}, {}]
        },
        created: function () {
            var that = this;
            that.loading = true;
            setTimeout(function () {
                that.list = [
                    {
                        title: 'Skeleton Screen最帅',
                        content: 'Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅',
                        bg: './images/img10.jpg',
                        createdTime: '2019/08/30 19:42:42',
                        author: 'GloryAce',
                        viewNum: '37浏览'
                    },
                    {
                        title: 'Skeleton Screen最帅',
                        content: 'Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅',
                        bg: './images/img12.jpg',
                        createdTime: '2019/08/30 19:42:42',
                        author: 'GloryAce',
                        viewNum: '37浏览'
                    },
                    {
                        title: 'Skeleton Screen最帅',
                        content: 'Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅',
                        bg: './images/img11.jpg',
                        createdTime: '2019/08/30 19:42:42',
                        author: 'GloryAce',
                        viewNum: '37浏览'
                    },
                    {
                        title: 'Skeleton Screen最帅',
                        content: 'Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅',
                        bg: './images/img13.jpg',
                        createdTime: '2019/08/30 19:42:42',
                        author: 'GloryAce',
                        viewNum: '37浏览'
                    },
                    {
                        title: 'Skeleton Screen最帅',
                        content: 'Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅,Skeleton Screen超级无敌帅',
                        bg: './images/img14.jpg',
                        createdTime: '2019/08/30 19:42:42',
                        author: 'GloryAce',
                        viewNum: '37浏览'
                    }
                ];
                that.loading = false;
            }, 5000);
        }
    })
</script>
</html>

三、总结

在网络环境比较差的情况下,使用Skeleton Screen可以显示一些视觉元素展现内容的轮廓,给用户比较友好的体验、一些等待预期。Skeleton Screen被越来越多的公司产品采用,如:支付宝,淘宝上都有很多的运用。

参考文章:

1、https://blog.csdn.net/i10630226/article/details/79590799
2、https://zhuanlan.zhihu.com/p/32941727

最后一次编辑于  01-06  
点赞 0
收藏
评论

1 个评论

登录 后发表内容