点击滚动容器内元素,滚动条自动滚动,元素水平居中或者垂直居中

发布时间 2023-09-14 20:33:43作者: william_new

话不多说,先来个完整的html例子,可以直接复制到一个html文件中看效果:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>点击居中功能</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    /* 水平居中样式 */
    .horizontal-box {
      border: 10px solid red;
      display: flex;
      flex-wrap: nowrap;
      overflow-x: auto;
    }

    .horizontal-box div {
      background: green;
      padding: 0 40px;
      margin-right: 30px;
    }

    .horizontal-box div:nth-last-child(1) {
      margin-right: 0;
    }

    /* 垂直居中样式 */
    .vertical-box {
      border: 10px solid red;
      overflow-y: auto;
    }

    .vertical-box div {
      background: green;
      height: 100px;
      margin-bottom: 30px;
    }

    .vertical-box div:nth-last-child(1) {
      margin-bottom: 0;
    }
  </style>
</head>

<body>
  <div>
    <p>点击水平居中 </p>
    <!-- position: relative一定要设置,决定了 offsetxxx 的值 -->
    <div class="horizontal-box" style="width:500px;height: 100px;position: relative;">
      <div>one</div>
      <div>two</div>
      <div>three</div>
      <div>four</div>
      <div>five</div>
      <div>six</div>
    </div>

    <p style="margin-top: 100px;">点击垂直居中 </p>
    <!-- position: relative一定要设置,决定了 offsetxxx 的值 -->
    <div class="vertical-box" style="width:100px;height: 500px;position: relative;">
      <div>one</div>
      <div>two</div>
      <div>three</div>
      <div>four</div>
      <div>five</div>
      <div>six</div>
    </div>
  </div>

  <script>
    //点击水平居中
    const domListX = document.querySelectorAll('.horizontal-box div')
    for (const dom of domListX) {
      dom.addEventListener('click', (e) => {
        const scrollDom = document.querySelector('.horizontal-box')
        const targetDom = e.target
        setScrollToCenter(scrollDom, targetDom, 'x')
      })
    }
    //点击垂直居中
    const domListY = document.querySelectorAll('.vertical-box div')
    for (const dom of domListY) {
      dom.addEventListener('click', (e) => {
        const scrollDom = document.querySelector('.vertical-box')
        const targetDom = e.target
        setScrollToCenter(scrollDom, targetDom, 'y')
      })
    }

  </script>
  <script>
    /**
      *点击元素自动滚动到水平或垂直中间位置
      * @param {HTMLElement} scrollDom - 滚动的元素
      * @param {HTMLElement} targetDom - 点击的元素
      * @param {string} [type='x'] - x表示水平,y表示垂直,默认为水平
    */
    function setScrollToCenter (scrollDom, targetDom, type = 'x') {
      if (!scrollDom || !targetDom) return false
      //如果是浏览器body的滚动条
      if ([window, document, document.documentElement].includes(scrollDom)) { scrollDom = document.documentElement }
      const { offsetLeft, offsetTop, offsetWidth, offsetHeight } = targetDom
      const { clientWidth, clientHeight } = scrollDom
      const targetDistance = type == 'x' ? offsetLeft : offsetTop
      const scrollClient = type == 'x' ? clientWidth : clientHeight
      const targetOffset = type == 'x' ? offsetWidth : offsetHeight
      const val = targetDistance - scrollClient / 2 + targetOffset / 2
      // x时,相当于:
      // targetDom.offsetLeft - scrollDom.clientWidth / 2 + targetDom.offsetWidth / 2
      // y时,相当于:
      // targetDom.offsetTop - scrollDom.clientHeight / 2 + targetDom.offsetHeight / 2
      const config = { behavior: 'smooth' }
      type === 'x' ? config.left = val : config.top = val
      scrollDom.scrollTo(config)
    }
  </script>
</body>

</html>
点击查看

 

再看效果图:

 

主要功能函数:
 /**
      *点击元素自动滚动到水平或垂直中间位置
      * @param {HTMLElement} scrollDom - 滚动的元素
      * @param {HTMLElement} targetDom - 点击的元素
      * @param {string} [type='x'] - x表示水平,y表示垂直,默认为水平
    */
    function setScrollToCenter (scrollDom, targetDom, type = 'x') {
      if (!scrollDom || !targetDom) return false
      //如果是浏览器body的滚动条
      if ([window, document, document.documentElement].includes(scrollDom)) { scrollDom = document.documentElement }
      const { offsetLeft, offsetTop, offsetWidth, offsetHeight } = targetDom
      const { clientWidth, clientHeight } = scrollDom
      const targetDistance = type == 'x' ? offsetLeft : offsetTop
      const scrollClient = type == 'x' ? clientWidth : clientHeight
      const targetOffset = type == 'x' ? offsetWidth : offsetHeight
      const val = targetDistance - scrollClient / 2 + targetOffset / 2
      // x时,相当于:
      // targetDom.offsetLeft - scrollDom.clientWidth / 2 + targetDom.offsetWidth / 2
      // y时,相当于:
      // targetDom.offsetTop - scrollDom.clientHeight / 2 + targetDom.offsetHeight / 2
      const config = { behavior: 'smooth' }
      type === 'x' ? config.left = val : config.top = val
      scrollDom.scrollTo(config)
    }
如果是body滚动,scrollDom参数传 document 或者 window 或者 document.documentElement 即可