简单的自定义滚动条

  1. 滚动条长度如何计算
滚动条长度 = 可视长度 * 滚动条容器长度 / 内容长度
  1. 移动一像素实际比例
比例 = (内容长度 - 可视长度) / (滚动条容器长度 - 滚动条长度 )
  1. 图解
    在这里插入图片描述
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>


<body>
  <div class="wrap">
    <div class="content">
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec in ligula id sem tristique ultrices eget id neque.
      Duis enim turpis, tempus at accumsan vitae, lobortis id sapien. Pellentesque nec orci mi, in pharetra ligula.
      Nulla
      facilisi. Nulla facilisi. Mauris convallis venenatis massa, quis consectetur felis ornare quis. Sed aliquet nunc
      ac
      ante molestie ultricies. Nam pulvinar ultricies bibendum. Vivamus diam leo, faucibus et vehicula eu, molestie sit
      amet dui. Proin nec orci et elit semper ultrices. Cum sociis natoque penatibus et magnis dis parturient montes,
      nascetur ridiculus mus. Sed quis urna mi, ac dignissim mauris. Quisque mollis ornare mauris, sed laoreet diam
      malesuada quis. Proin vel elementum ante. Donec hendrerit arcu ac odio tincidunt posuere. Vestibulum nec risus eu
      lacus semper viverra.
      Vestibulum dictum consectetur magna eu egestas. Praesent molestie dapibus erat, sit amet sodales lectus congue ut.
      Nam adipiscing, tortor ac blandit egestas, lorem ligula posuere ipsum, nec faucibus nisl enim eu purus. Quisque
      bibendum diam quis nunc eleifend at molestie libero tincidunt. Quisque tincidunt sapien a sapien pellentesque
      consequat. Mauris adipiscing venenatis augue ut tempor. Donec auctor mattis quam quis aliquam. Nullam ultrices
      erat
      in dolor pharetra bibendum. Suspendisse eget odio ut libero imperdiet rhoncus. Curabitur aliquet, ipsum sit amet
      aliquet varius, est urna ullamcorper magna, sed eleifend libero nunc non erat. Vivamus semper turpis ac turpis
      volutpat non cursus velit aliquam. Fusce id tortor id sapien porta egestas. Nulla venenatis luctus libero et
      suscipit. Sed sed purus risus. Donec auctor, leo nec eleifend vehicula, lacus felis sollicitudin est, vitae
      lacinia
      lectus urna nec libero. Aliquam pellentesque, arcu condimentum pharetra vestibulum, lectus felis malesuada felis,
      vel fringilla dolor dui tempus nisi. In hac habitasse platea dictumst. Ut imperdiet mauris vitae eros varius eget
      accumsan lectus adipiscing.
      Quisque et massa leo, sit amet adipiscing nisi. Mauris vel condimentum dolor. Duis quis ullamcorper eros. Proin
      metus dui, facilisis id bibendum sed, aliquet non ipsum. Aenean pulvinar risus eu nisi dictum eleifend. Maecenas
      mattis dolor eget lectus pretium eget molestie libero auctor. Praesent sit amet tellus sed nibh convallis semper.
      Curabitur nisl odio, feugiat non dapibus sed, tincidunt ut est. Nullam erat velit, suscipit aliquet commodo sit
      amet, mollis in mauris. Curabitur pharetra dictum interdum. In posuere pretium ultricies. Curabitur volutpat eros
      vehicula quam ultrices varius. Proin volutpat enim a massa tempor ornare. Sed ullamcorper fermentum nisl, ac
      hendrerit sem feugiat ac. Donec porttitor ullamcorper quam. Morbi pretium adipiscing quam, quis bibendum diam
      congue
      eget. Sed at lectus at est malesuada iaculis. Sed fermentum quam dui. Donec eget ipsum dolor, id mollis nisi.
      Donec
      fermentum vehicula porta.
      Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor
      quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean
      ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra.
      Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt
      condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar
      facilisis.
      Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat.
      Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus
      Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor
      quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean
      ultricies mi vitae est. Mauris placerat eleifend leo.
    </div>
    <div class="scroll">
      <div class="slider"></div>
    </div>
  </div>

  <div class="wrap1">
    <div class="content1">
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec in ligula id sem tristique ultrices eget id neque.
      Duis enim turpis, tempus at accumsan vitae, lobortis id sapien. Pellentesque nec orci mi, in pharetra ligula.
      Nulla
      facilisi. Nulla facilisi. Mauris convallis venenatis massa, quis consectetur felis ornare quis. Sed aliquet nunc
      ac
      ante molestie ultricies. Nam pulvinar ultricies bibendum. Vivamus diam leo, faucibus et vehicula eu, molestie sit
      amet dui. Proin nec orci et elit semper ultrices. Cum sociis natoque penatibus et magnis dis parturient montes,
      nascetur ridiculus mus. Sed quis urna mi, ac dignissim mauris. Quisque mollis ornare mauris, sed laoreet diam
      malesuada quis. Proin vel elementum ante. Donec hendrerit arcu ac odio tincidunt posuere. Vestibulum nec risus eu
      lacus semper viverra.
      Vestibulum dictum consectetur magna eu egestas. Praesent molestie dapibus erat, sit amet sodales lectus congue ut.
      Nam adipiscing, tortor ac blandit egestas, lorem ligula posuere ipsum, nec faucibus nisl enim eu purus. Quisque
      bibendum diam quis nunc eleifend at molestie libero tincidunt. Quisque tincidunt sapien a sapien pellentesque
      consequat. Mauris adipiscing venenatis augue ut tempor. Donec auctor mattis quam quis aliquam. Nullam ultrices
      erat
      in dolor pharetra bibendum. Suspendisse eget odio ut libero imperdiet rhoncus. Curabitur aliquet, ipsum sit amet
      aliquet varius, est urna ullamcorper magna, sed eleifend libero nunc non erat. Vivamus semper turpis ac turpis
      volutpat non cursus velit aliquam. Fusce id tortor id sapien porta egestas. Nulla venenatis luctus libero et
      suscipit. Sed sed purus risus. Donec auctor, leo nec eleifend vehicula, lacus felis sollicitudin est, vitae
      lacinia
      lectus urna nec libero. Aliquam pellentesque, arcu condimentum pharetra vestibulum, lectus felis malesuada felis,
      vel fringilla dolor dui tempus nisi. In hac habitasse platea dictumst. Ut imperdiet mauris vitae eros varius eget
      accumsan lectus adipiscing.
      Quisque et massa leo, sit amet adipiscing nisi. Mauris vel condimentum dolor. Duis quis ullamcorper eros. Proin
      metus dui, facilisis id bibendum sed, aliquet non ipsum. Aenean pulvinar risus eu nisi dictum eleifend. Maecenas
      mattis dolor eget lectus pretium eget molestie libero auctor. Praesent sit amet tellus sed nibh convallis semper.
      Curabitur nisl odio, feugiat non dapibus sed, tincidunt ut est. Nullam erat velit, suscipit aliquet commodo sit
      amet, mollis in mauris. Curabitur pharetra dictum interdum. In posuere pretium ultricies. Curabitur volutpat eros
      vehicula quam ultrices varius. Proin volutpat enim a massa tempor ornare. Sed ullamcorper fermentum nisl, ac
      hendrerit sem feugiat ac. Donec porttitor ullamcorper quam. Morbi pretium adipiscing quam, quis bibendum diam
      congue
      eget. Sed at lectus at est malesuada iaculis. Sed fermentum quam dui. Donec eget ipsum dolor, id mollis nisi.
      Donec
      fermentum vehicula porta.
      Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor
      quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean
      ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra.
      Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt
      condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar
      facilisis.
      Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat.
      Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor, facilisis luctus, metus
      Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor
      quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean
      ultricies mi vitae est. Mauris placerat eleifend leo.
    </div>
    <div class="scroll1">
      <div class="slider1"></div>
    </div>
  </div>
  <style type="text/css">
    .wrap {
      user-select: none;
      position: relative;
      width: 400px;
      height: 300px;
      overflow: hidden;
      border: 1px solid #aaa;
    }

    .wrap .scroll {
      opacity: 0;
      transition: opacity .3s
    }

    .wrap:hover .scroll {
      opacity: 1;
    }

    .content {
      width: 100%;
      height: 300px;
      overflow: auto;
    }

    .content::-webkit-scrollbar {
      width: 0 !important
    }

    .scroll {
      position: absolute;
      width: 10px;
      height: calc(100%);
      right: 0px;
      top: 0px;
      background-color: red;
      opacity: .5;
    }

    .slider {
      position: absolute;
      top: 0px;
      left: 0px;
      width: 100%;
      height: 100px;
      background: blue;
    }
  </style>
  <style type="text/css">
    .wrap1 {
      user-select: none;
      position: relative;
      width: 1000px;
      overflow: hidden;
      border: 1px solid #aaa;
    }

    .wrap1 .scroll1 {
      opacity: 0;
      transition: opacity .3s
    }

    .wrap1:hover .scroll1 {
      opacity: 1;
    }

    .content1 {
      white-space: nowrap;
      width: 100%;
      overflow: auto;
    }

    .content1::-webkit-scrollbar {
      width: 0 !important
    }

    .scroll1 {
      position: absolute;
      width: calc(100%);
      height: 10px;
      right: 0px;
      bottom: 0px;
      background-color: red;
      opacity: .5;
    }

    .slider1 {
      position: absolute;
      top: 0px;
      left: 0px;
      width: 100px;
      height: 10px;
      background: blue;
    }
  </style>
  <script>
    // bar_height/wrap_height = wrap_height/content_height;
    // bar_height = wrap_height*wrap_height/content_height;  // 滚动条的长度
    const wrap = document.querySelector(".wrap")
    const content = document.querySelector(".content")
    const scroll = document.querySelector(".scroll")
    const sliderDom = document.querySelector(".slider")

    const visibleHeight = parseInt(window.getComputedStyle(wrap).height)
    const scrollbarHeight = parseInt(scroll.clientHeight)
    const scrollHeight = content.scrollHeight
    // 根据 visibleHeight / scrollHeight = sliderHeight / scrollbarHeight 得出

    const sliderHeight = visibleHeight * scrollbarHeight / scrollHeight
    const sliderRatio = (scrollHeight - visibleHeight) / (scrollbarHeight - sliderHeight)


    function updateSlider(moveDelta) {
      // 更新滑块的高度和位置
      sliderDom.style.height = sliderHeight + 'px';
      sliderDom.style.top = moveDelta + 'px';
    }

    updateSlider(0);
    let isMove = false
    let initY = 0
    let over = 0
    let moveDelta = 0
    sliderDom.addEventListener('mousedown', (e) => {
      initY = e.pageY - over;
      isMove = true
      document.addEventListener('mousemove', mousemove);
    })

    function mousemove(e) {
      if (!isMove) {
        return
      }
      const dom = e.currentTarget
      // 移动的距离
      moveDelta = e.pageY - initY
      if (moveDelta < 0) {
        moveDelta = 0
      }
      const max = scroll.clientHeight - sliderDom.clientHeight
      if (moveDelta > max) {
        moveDelta = max
      }
      updateSlider(moveDelta);
      content.scrollTo(0, moveDelta * sliderRatio);
    }
    document.addEventListener("mouseup", function (e) {
      isMove = false
      over = moveDelta
      document.removeEventListener("mouse", mousemove)
    })

    scroll.addEventListener('mousedown', (e) => {
      if (e.target !== sliderDom) {
        let moveDeltatmp = e.pageY - sliderDom.clientHeight / 2
        const min = sliderDom.clientHeight / 2
        if (moveDeltatmp < min) {
          moveDeltatmp = 0
        }
        const max = scroll.clientHeight - sliderDom.clientHeight
        if (moveDeltatmp > max) {
          moveDeltatmp = max
        }
        moveDelta = moveDeltatmp
        updateSlider(moveDelta);
        content.scrollTo(0, moveDelta * sliderRatio);
      }
    })


    content.addEventListener('mousewheel', (e) => {
      const scrollTop = e.currentTarget.scrollTop
      const moveDelta = scrollTop / sliderRatio
      updateSlider(moveDelta);
      over = moveDelta
    })
  </script>
  <script>
    // bar_height/wrap_height = wrap_height/content_height;
    // bar_height = wrap_height*wrap_height/content_height;  // 滚动条的长度
    const wrap1 = document.querySelector(".wrap1")
    const content1 = document.querySelector(".content1")
    const scroll1 = document.querySelector(".scroll1")
    const sliderDom1 = document.querySelector(".slider1")

    const visibleWidth1 = parseInt(window.getComputedStyle(wrap1).width)
    const scrollbarWidth1 = parseInt(scroll1.clientWidth)
    const scrollWidth1 = content1.scrollWidth
    // 根据 visibleHeight / scrollHeight = sliderHeight / scrollbarHeight 得出

    const sliderWidth1 = visibleWidth1 * scrollbarWidth1 / scrollWidth1
    const sliderRatio1 = (scrollWidth1 - visibleWidth1) / (scrollbarWidth1 - sliderWidth1)

    function updateSlider1(moveDelta) {
      // 更新滑块的高度和位置
      sliderDom1.style.width = sliderWidth1 + 'px';
      sliderDom1.style.left = moveDelta + 'px';
    }

    updateSlider1(0);
    let isMove1 = false
    let initX1 = 0
    let over1 = 0
    let moveDelta1 = 0
    sliderDom1.addEventListener('mousedown', (e) => {
      initX1 = e.pageX - over1;
      isMove1 = true
      document.addEventListener('mousemove', mousemove1);
    })

    function mousemove1(e) {
      if (!isMove1) {
        return
      }
      const dom = e.currentTarget
      // 移动的距离
      moveDelta1 = e.pageX - initX1
      if (moveDelta1 < 0) {
        moveDelta1 = 0
      }
      const max = scroll1.clientWidth - sliderDom1.clientWidth
      if (moveDelta1 > max) {
        moveDelta1 = max
      }
      updateSlider1(moveDelta1);
      content1.scrollTo(moveDelta1 * sliderRatio1, 0);
    }
    document.addEventListener("mouseup", function (e) {
      isMove1 = false
      over1 = moveDelta1
      document.removeEventListener("mouse", mousemove1)
    })

    scroll1.addEventListener('mousedown', (e) => {
      if (e.target !== sliderDom1) {
        let moveDeltatmp = e.pageX - sliderDom1.clientWidth / 2
        const min = sliderDom1.clientWidth / 2
        if (moveDeltatmp < min) {
          moveDeltatmp = 0
        }
        const max = scroll1.clientWidth - sliderDom1.clientWidth
        if (moveDeltatmp > max) {
          moveDeltatmp = max
        }
        moveDelta1 = moveDeltatmp
        updateSlider1(moveDelta1);
        content1.scrollTo(moveDelta1 * sliderRatio1, 0);
      }
    })


    content1.addEventListener('mousewheel', (e) => {
      const scrollLeft = e.currentTarget.scrollLeft
      const moveDelta = scrollLeft / sliderRatio1
      updateSlider1(moveDelta);
      over1 = moveDelta
    })
  </script>
</body>

</html>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值