backtop.vue 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. <template>
  2. <div :class="['nut-backtop', {'show': backTop}]" :style="styles" @click="goto">
  3. <slot>
  4. <div class="nut-backtop-main"></div>
  5. </slot>
  6. </div>
  7. </template>
  8. <script>
  9. export default {
  10. name: "nut-backtop",
  11. props: {
  12. distance: {
  13. type: Number,
  14. default: 200
  15. },
  16. bottom: {
  17. type: Number,
  18. default: 20
  19. },
  20. right: {
  21. type: Number,
  22. default: 10
  23. },
  24. duration: {
  25. type: Number,
  26. default: 1000
  27. },
  28. zIndex: {
  29. type: Number,
  30. default: 1111
  31. }
  32. },
  33. data() {
  34. return {
  35. backTop: false
  36. };
  37. },
  38. mounted() {
  39. window.addEventListener("scroll", this.handleScroll, false);
  40. window.addEventListener("resize", this.handleScroll, false);
  41. },
  42. beforeDestroy() {
  43. window.removeEventListener("scroll", this.handleScroll, false);
  44. window.removeEventListener("resize", this.handleScroll, false);
  45. },
  46. computed: {
  47. styles() {
  48. return {
  49. bottom: `${this.bottom}px`,
  50. right: `${this.right}px`,
  51. "z-index": this.zIndex
  52. };
  53. }
  54. },
  55. methods: {
  56. handleScroll() {
  57. this.backTop = window.pageYOffset >= this.distance;
  58. },
  59. goto() {
  60. const sTop =
  61. document.documentElement.scrollTop || document.body.scrollTop;
  62. this.scrollTop(window, sTop, 0, this.duration);
  63. this.$emit("click");
  64. },
  65. scrollTop(el, from = 0, to, duration = 500, endCallback) {
  66. this.el = el;
  67. let lastTime = 0;
  68. let vendors = ["webkit", "moz"];
  69. for (
  70. let x = 0;
  71. x < vendors.length && !window.requestAnimationFrame;
  72. ++x
  73. ) {
  74. window.requestAnimationFrame =
  75. window[vendors[x] + "RequestAnimationFrame"];
  76. window.cancelAnimationFrame =
  77. window[vendors[x] + "CancelAnimationFrame"] ||
  78. window[vendors[x] + "CancelRequestAnimationFrame"];
  79. }
  80. if (!window.requestAnimationFrame) {
  81. window.requestAnimationFrame = function(callback, element) {
  82. let currTime = new Date().getTime();
  83. let timeToCall = Math.max(0, 16.7 - (currTime - lastTime));
  84. let id = window.setTimeout(function() {
  85. callback(currTime + timeToCall);
  86. }, timeToCall);
  87. lastTime = currTime + timeToCall;
  88. return id;
  89. };
  90. }
  91. if (!window.cancelAnimationFrame) {
  92. window.cancelAnimationFrame = function(id) {
  93. clearTimeout(id);
  94. };
  95. }
  96. const difference = Math.abs(from - to);
  97. const step = Math.ceil((difference / duration) * 50);
  98. this.scroll(from, to, step, endCallback);
  99. },
  100. scroll(start, end, step, endCallback) {
  101. if (start === end) {
  102. endCallback && endCallback();
  103. return;
  104. }
  105. let d = start + step > end ? end : start + step;
  106. if (start > end) {
  107. d = start - step < end ? end : start - step;
  108. }
  109. if (this.el === window) {
  110. window.scrollTo(d, d);
  111. } else {
  112. this.el.scrollTop = d;
  113. }
  114. window.requestAnimationFrame(() => this.scroll(d, end, step));
  115. }
  116. }
  117. };
  118. </script>