前端 实战项目·优雅实现 BackTop

作者 : jamin 本文共2763个字,预计阅读时间需要7分钟 发布时间: 2020-10-18 共1088人阅读

优雅实现 BackTop

BackTop 即滚动到页面顶部,是很多网站都会用到的基础功能,实现方法很多,Github 上也有许多优秀的三方库,如 smooth-scroll,但如何优雅实现也是一门学问。

事件绑定和解绑

滚动到页面顶部的按钮一般位于页面角落,并且只有在需要的时候才显示出来。所以首先需要监听页面滚动事件,直到滚动到一定距离后显示 BackTop 按钮。

监听页面滚动最简单的实现方式是使用 addEventListener 监听 scroll 事件,并在页面卸载时解除监听,代码如下:

window.addEventListener('scroll', handleScroll, false)
window.removeEventListener('scroll', handleScroll, false)

但既然称为最优雅的实现方式,为了兼任各种浏览器,可以将绑定和解绑事件提取出公共方法,并作兼容优化,代码如下:

/**
 * @description 绑定事件 on(element, event, handler)
 */
export const on = (function() {
  if (document.addEventListener) {
    return function(element, event, handler) {
      if (element && event && handler) {
        element.addEventListener(event, handler, false)
      }
    }
  } else {
    return function(element, event, handler) {
      if (element && event && handler) {
        element.attachEvent('on' + event, handler)
      }
    }
  }
})()

/**
 * @description 解绑事件 off(element, event, handler)
 */
export const off = (function() {
  if (document.removeEventListener) {
    return function(element, event, handler) {
      if (element && event) {
        element.removeEventListener(event, handler, false)
      }
    }
  } else {
    return function(element, event, handler) {
      if (element && event) {
        element.detachEvent('on' + event, handler)
      }
    }
  }
})()

调用方式:

on(window, 'scroll', handleScroll)
off(window, 'scroll', handleScroll)

function handleScroll() {
  console.log(window.pageYOffset)
}

回到顶部动画

window.requestAnimationFrame() 方法请求浏览器在下一次重绘之前调用指定的函数来更新动画。该方法使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。回调的次数通常是每秒 60 次。由于兼容问题,在不同浏览器需要带上前缀,并且在浏览器不支持时使用 setTimeout 模拟。

requestAnimationFrame 目的是为了让各种网页动画效果(DOM 动画、Canvas 动画、SVG 动画、WebGL 动画)能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。

使用 requestAnimationFrame 来实现滚动到页面顶部的动画,核心是按帧来滚动小段距离来实现平滑滚动的效果,代码如下:

// scrollTop animation
export function scrollTop(el, from = 0, to, duration = 500, endCallback) {
  if (!window.requestAnimationFrame) {
    window.requestAnimationFrame =
      window.webkitRequestAnimationFrame ||
      window.mozRequestAnimationFrame ||
      window.msRequestAnimationFrame ||
      function(callback) {
        return window.setTimeout(callback, 1000 / 60)
      }
  }
  const difference = Math.abs(from - to)
  const step = Math.ceil((difference / duration) * 50)

  function scroll(start, end, step) {
    if (start === end) {
      endCallback && endCallback()
      return
    }

    let d = start + step > end ? end : start + step
    if (start > end) {
      d = start - step < end ? end : start - step
    }

    if (el === window) {
      window.scrollTo(d, d)
    } else {
      el.scrollTop = d
    }
    window.requestAnimationFrame(() => scroll(d, end, step))
  }
  scroll(from, to, step)
}

调用方式:

function backTop() {
  const sTop = document.documentElement.scrollTop || document.body.scrollTop
  scrollTop(window, sTop, 0, 2000)
}

扩展:该 API 还提供 cancelAnimationFrame 方法用来取消重绘,参数是 requestAnimationFrame 返回的一个代表任务 ID 的整数值,使用如下:

const requestID = window.requestAnimationFrame(() => scroll(d, end, step))
window.cancelAnimationFrame(requestID)

如果不需要考虑浏览器兼容性,在 Chrome、Firefox 浏览器上,window.scrollTo 还支持第二种参数形式,传入参数 options 是一个包含三个属性的对象:

  • top 等同于 y-coord,代表纵轴坐标
  • left 等同于 x-coord,代表横轴坐标
  • behavior 类型 String,表示滚动行为,支持参数 smooth(平滑滚动),instant(瞬间滚动),默认值 auto,效果等同于 instant
window.scrollTo({
  top: 0,
  behavior: 'smooth'
})

此方法简单高效,可惜 Edge、IE、Safari 皆不支持。

本站所提供的部分资源来自于网络,版权争议与本站无关,版权归原创者所有!仅限用于学习和研究目的,不得将上述内容资源用于商业或者非法用途,否则,一切后果请用户自负。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容资源。如果上述内容资对您的版权或者利益造成损害,请提供相应的资质证明,我们将于3个工作日内予以删除。本站不保证所提供下载的资源的准确性、安全性和完整性,源码仅供下载学习之用!如用于商业或者非法用途,与本站无关,一切后果请用户自负!本站也不承担用户因使用这些下载资源对自己和他人造成任何形式的损失或伤害。如有侵权、不妥之处,请联系站长以便删除!
金点网络 » 前端 实战项目·优雅实现 BackTop

常见问题FAQ

免费下载或者VIP会员专享资源能否直接商用?
本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。
是否提供免费更新服务?
持续更新,永久免费
是否经过安全检测?
安全无毒,放心食用

提供最优质的资源集合

立即加入 友好社区
×