Blame view

node_modules/element-ui/packages/backtop/src/main.vue 2.33 KB
7820380e   “wangming”   1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
  <template>
    <transition name="el-fade-in">
      <div
        v-if="visible"
        @click.stop="handleClick"
        :style="{
          'right': styleRight,
          'bottom': styleBottom
        }"
        class="el-backtop">
        <slot>
          <el-icon name="caret-top"></el-icon>
        </slot>
      </div>
    </transition>
  </template>
  
  <script>
  import throttle from 'throttle-debounce/throttle';
  
  const cubic = value => Math.pow(value, 3);
  const easeInOutCubic = value => value < 0.5
    ? cubic(value * 2) / 2
    : 1 - cubic((1 - value) * 2) / 2;
  
  export default {
    name: 'ElBacktop',
  
    props: {
      visibilityHeight: {
        type: Number,
        default: 200
      },
      target: [String],
      right: {
        type: Number,
        default: 40
      },
      bottom: {
        type: Number,
        default: 40
      }
    },
  
    data() {
      return {
        el: null,
        container: null,
        visible: false
      };
    },
  
    computed: {
      styleBottom() {
        return `${this.bottom}px`;
      },
      styleRight() {
        return `${this.right}px`;
      }
    },
  
    mounted() {
      this.init();
      this.throttledScrollHandler = throttle(300, this.onScroll);
      this.container.addEventListener('scroll', this.throttledScrollHandler);
    },
  
    methods: {
      init() {
        this.container = document;
        this.el = document.documentElement;
        if (this.target) {
          this.el = document.querySelector(this.target);
          if (!this.el) {
            throw new Error(`target is not existed: ${this.target}`);
          }
          this.container = this.el;
        }
      },
      onScroll() {
        const scrollTop = this.el.scrollTop;
        this.visible = scrollTop >= this.visibilityHeight;
      },
      handleClick(e) {
        this.scrollToTop();
        this.$emit('click', e);
      },
      scrollToTop() {
        const el = this.el;
        const beginTime = Date.now();
        const beginValue = el.scrollTop;
        const rAF = window.requestAnimationFrame || (func => setTimeout(func, 16));
        const frameFunc = () => {
          const progress = (Date.now() - beginTime) / 500;
          if (progress < 1) {
            el.scrollTop = beginValue * (1 - easeInOutCubic(progress));
            rAF(frameFunc);
          } else {
            el.scrollTop = 0;
          }
        };
        rAF(frameFunc);
      }
    },
  
    beforeDestroy() {
      this.container.removeEventListener('scroll', this.throttledScrollHandler);
    }
  };
  </script>