JS 的平凡之路--学习人气眼中的效果(上)

最近看了看人气眼的界面,感受到学习的地方有不少呀。这里先带你们看看人气值跳动的实现。本篇代码基于Vue2.x.x。函数

1、概要

  首先看一下效果图:学习

人气值动画

  要想实现上面的效果,咱们分为这几个部分:优化

  • 判断元素是否在可视区域内;
  • 函数节流的使用;
  • 元素高度过渡动画;
  • 数字跳动动画;

2、判断元素是否在可视区域以内

  首先咱们要先获取元素的位置信息,这里咱们采用getBoundingClientRect方法,MDN上对于该方法的介绍。而后咱们只要与可视区域作个比较,就OK了。动画

// methods
    isElementInViewport (el, offset) {
        const h = offset || 20,
              box = el.getBoundingClientRect(),
              top = (box.top >= 0),
              left = (box.left >= 0),
              bottom = (box.bottom <= (window.innerHeight || document.documentElement.clientHeight) + h),
              right = (box.right <= (window.innerWidth || document.documentElement.clientWidth) + h);
        return (top && left && bottom && right);
    }
复制代码

3、函数节流的使用

  接下来咱们须要监听'scroll'事件,判断元素是否出如今可视区域内。对于scroll事件的优化之一,咱们须要使用函数节流。你能够选择导入underscore.js的throttle函数,可是这里我尝试了一下requestAnimationFrame来实现函数节流:ui

//mounted: 
    document.addEventListener('scroll', this.onScroll , false);
    
    // methods:
    onScroll (e) {
        if (!this.LOCK) {
            this.LOCK = true;
            window.requestAnimationFrame(this.scrollAction);
        }
    },
    scrollAction () {
        const flag = this.isElementInViewport(this.$refs.zfbitem, 100);
        if (!flag) {
            this.LOCK = false;
        } else {
            //触发元素高度过渡动画
            this.active = true;
            //去除掉事件监听
            document.removeEventListener('scroll', this.onScroll , false);
        }
    }
复制代码

4、元素的高度过渡动画

  在CSS当中,实现一种动画效果,你能够有不少种方式,这里我也就不一一枚举了,此例子中我采用高度过渡的方式实现效果。有人就会说经过高度过渡没有任何难度啊?实际上,你须要注意的点仍是蛮多的:this

  • 想让一个元素的高度为0,并非简单的height:0;就能作到的,前提是你不能设置border、垂直方向的padding等;
  • 当你的元素设置height为100px时,你再设置max-height为0,它同样只显示0的高度;
  • 当height的值为auto时,咱们是没法过渡的。因此对于auto的状况,咱们能够采用max-height来模拟一下,通常状况下,效果还行。

  实现的代码仍是很简单的,这里就不贴代码了。spa

5、数字跳动动画

  首先咱们须要在高度过渡动画完成后执行数字跳动动画,这里咱们须要监听'transitionend'事件,对于这个事件须要特别注意的点:3d

  • 每一个过渡属性完成后多会触发一次transitionend;
  • transitionend事件支持冒泡,若是子元素也有过渡效果的话,必定要阻止冒泡。
// watch : 
    active (newValue) {
        if (newValue) {
            this.$refs.zfbitem.addEventListener('transitionend', this.transitionAction, false);
        }
    }
    
    // methods:
    transitionAction (e) {
        //再也不须要监听时,必定要移除监听
        this.$refs.zfbitem.removeEventListener('transitionend', this.transitionAction, false);
        this.numberBounce();
    }
复制代码

  对于数字跳动的动画,正好利用了Vue响应式的特性偷懒了一波,感受实现的仍是有些生硬,我主要是从这几个方面下手的:code

  • 暂且默认两位数;
  • 个位和十位多须要先跳一轮0~9,而后再跳向最终的数字,这样避免特殊的状况;
  • 个位和十位动画执行的时长是同样的,经过时长和各自须要跳动的字数,计算出每一帧须要的时间。
//组件须要传入的参数
    props: {
        rate: Number
    }
    
    //分割个位 和 十位
    computed: {
        numberArray () {
            return (this.rate + '').split('');
        }
    }
    
    numberBounce () {
        let arr = this.numberArray,
            totalTime = 200,
            a = arr[1],
            aLen = Number.parseInt(a),
            aTime = Math.floor(totalTime / (aLen + 9)),
            i = 0,
            b = arr[0],
            bLen = Number.parseInt(b),
            bTime = Math.floor(totalTime / (bLen + 9)),
            j = 0;
        this.bit = 0;
        this.ten = 0;
        this.bitTimeId = setInterval(_ => {
            i++;
            this.bit = i % 10; // 计数
            if (i - 10 === aLen) {
                //千万不要忘记清除定时器哦
                clearInterval(this.bitTimeId);
                this.bitTimeId = null;
            }
        }, aTime);

        this.tenTimeId = setInterval(_ => {
            j++;
            this.ten = j % 10;
            if (j - 10 === bLen) {
                clearInterval(this.tenTimeId);
                this.tenTimeId = null;
            }
        }, bTime);
    }
复制代码

6、总结

  这虽然是一个简单的效果,可是包含的知识点不少,这里又要强调了:基础非常重要,千万不要浮躁。(^_^)cdn


  喜欢本文的小伙伴们,欢迎关注个人订阅号超爱敲代码,查看更多内容.

相关文章
相关标签/搜索