• 横向滚动条 css js html


    目的:

    1. 练习手写滚动条

    2. 市面上多是竖向滚动条,横向滚动条较少

    3. 横向滚动条,需要滑动到容器底部才能使用,不方便,因此想自己写一个横向滚动条放置在容器内部的视口高度的最低处

    3. 问题复现:

    如果容器的内容超过了容器的宽度,就会出现横向滚动条(暂不考虑换行),但是如果该容器的高度过高,用户需要滑到容器的底部才能操作横向滚动条(横向滚动条默认在容器的底部,当然我们不考虑使用shift+鼠标左键的方式横向移动)

    问题演示视频:

    横向滚动条-问题演示

    制作横向滚动条

    样式:

    滚动条包含两个方面:track(滚动轨道) + thumb(滚动块)

    最开始是只有content容器的,然后我们在content下面添加横向滚动条容器,并且在最外层添加box容器。

    最外层的box是相对定位(没有宽高),滚动条是绝对定位

    1. .box {
    2. position: relative;
    3. }
    4. .content {
    5. width: 100px;
    6. height: 1000px;
    7. background-color: pink;
    8. overflow: auto;
    9. }
    10. .content::-webkit-scrollbar {
    11. display: none;
    12. }
    13. .track {
    14. position: absolute;
    15. left: 0;
    16. bottom: 0; /*0<=bottom<=1000-10px*/
    17. width: 100px;
    18. height: 10px;
    19. background-color: red;
    20. }
    21. .thumb {
    22. cursor: grab;
    23. position: absolute;
    24. left: 0;
    25. top: 0;
    26. width: 10px;
    27. height: 100%;
    28. background-color: blue;
    29. }
    30. <div class="box">
    31. <div class="content">
    32. asdawdkjaslkdjalkwjdlkasjdlawkldakslldjawlkdjlkasjdkawdasdawes
    33. asdawdkjaslkdjalkwjdlkasjdlawkldakslldjawlkdjlkasjdkawdasdawes
    34. asdawdkjaslkdjalkwjdlkasjdlawkldakslldjawlkdjlkasjdkawdasdawes
    35. </div>
    36. <div class="track" id="scrollbar">
    37. <div class="thumb" id="scrollbar-thumb"></div>
    38. </div>
    39. </div>

    逻辑:

    监听容器横向滚动,同步滑块位置

    监听content容器的滚动动作,同步到滑块的位置

    1. const content = document.querySelector(".content")
    2. const track = document.querySelector(".track")
    3. const thumb = document.querySelector(".thumb")
    4. function updateScrollbar() {
    5. const scrollPercentage =
    6. content.scrollLeft / (content.scrollWidth - content.clientWidth)
    7. const thumbPosition =
    8. scrollPercentage * (track.clientWidth - thumb.clientWidth)
    9. thumb.style.left = thumbPosition + "px"
    10. }
    11. // content(这样还包括了shift+鼠标左键)
    12. content.addEventListener("scroll", updateScrollbar)

    拖动滑块

    然后,我们再来制作拖动滑块同时横向移动容器的功能,主要用到三个动作,mousedown,mousemove,mouseup

    1. // 监听滑块拖动事件
    2. let isDragging = false
    3. let startX
    4. let startScrollLeft
    5. thumb.addEventListener("mousedown", function (e) {
    6. isDragging = true
    7. startX = e.clientX
    8. startScrollLeft = content.scrollLeft
    9. // 拖动开始时改变鼠标样式为正在抓取
    10. thumb.style.cursor = "grabbing"
    11. // 防止在拖动时选择文本
    12. e.preventDefault()
    13. })
    14. document.addEventListener("mousemove", function (e) {
    15. if (isDragging) {
    16. const deltaX = e.clientX - startX
    17. const scrollDelta =
    18. (deltaX / track.clientWidth) *
    19. (content.scrollWidth - content.clientWidth)
    20. content.scrollLeft = startScrollLeft + scrollDelta
    21. }
    22. })
    23. document.addEventListener("mouseup", function () {
    24. isDragging = false
    25. })

    规定横向滚动条的位置的界限

    (横向滚动条的位置最低不低于容器的边界底部,最高不高于容器的边界顶部)

    1. let contentRec = content.getBoundingClientRect()//得到content容器的边界
    2. track.style.bottom =
    3. content.clientHeight - (window.innerHeight - contentRec.top) + "px"
    4. let trackBottom = parseInt(track.style.bottom) // 获取轨道的底部位置
    5. if (
    6. trackBottom <= 0 ||
    7. trackBottom >= content.clientHeight - track.clientHeight
    8. ) {
    9. track.style.bottom = "0px" // 设置时加上单位
    10. }
    11. // 更新 track.style.bottom 的逻辑
    12. document.addEventListener("scroll", function () {
    13. let viewHeight = window.innerHeight + scrollY
    14. contentRec = content.getBoundingClientRect()
    15. // 计算新的 bottom 值
    16. let newBottom =
    17. content.clientHeight - (window.innerHeight - contentRec.top)
    18. // 确保 newBottom 不小于 0 且不大于 content.clientHeight - track.clientHeight
    19. newBottom = Math.max(
    20. 0,
    21. Math.min(newBottom, content.clientHeight - track.clientHeight)
    22. )
    23. // 更新 track 的 bottom 样式
    24. track.style.bottom = `${newBottom}px`
    25. })

    成品

    代码:

    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8" />
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    6. <title>Document</title>
    7. <style>
    8. * {
    9. margin: 0;
    10. padding: 0;
    11. box-sizing: border-box;
    12. }
    13. .header {
    14. width: 100px;
    15. height: 1000px;
    16. background-color: skyblue;
    17. }
    18. .footer {
    19. width: 100px;
    20. height: 300px;
    21. background-color: green;
    22. }
    23. .box {
    24. position: relative;
    25. }
    26. .content {
    27. width: 100px;
    28. height: 1000px;
    29. background-color: pink;
    30. overflow: auto;
    31. }
    32. .content::-webkit-scrollbar {
    33. display: none;
    34. }
    35. .track {
    36. position: absolute;
    37. left: 0;
    38. bottom: 0; /*0<=bottom<=1000-10px*/
    39. width: 100px;
    40. height: 10px;
    41. background-color: red;
    42. }
    43. .thumb {
    44. cursor: grab;
    45. position: absolute;
    46. left: 0;
    47. top: 0;
    48. width: 10px;
    49. height: 100%;
    50. background-color: blue;
    51. }
    52. </style>
    53. </head>
    54. <body>
    55. <div class="header"></div>
    56. <div class="box">
    57. <div class="content">
    58. asdawdkjaslkdjalkwjdlkasjdlawkldakslldjawlkdjlkasjdkawdasdawes
    59. asdawdkjaslkdjalkwjdlkasjdlawkldakslldjawlkdjlkasjdkawdasdawes
    60. asdawdkjaslkdjalkwjdlkasjdlawkldakslldjawlkdjlkasjdkawdasdawes
    61. asdawdkjaslkdjalkwjdlkasjdlawkldakslldjawlkdjlkasjdkawdasdawes
    62. asdawdkjaslkdjalkwjdlkasjdlawkldakslldjawlkdjlkasjdkawdasdawes
    63. asdawdkjaslkdjalkwjdlkasjdlawkldakslldjawlkdjlkasjdkawdasdawes
    64. </div>
    65. <!-- 我觉得这个滚动条应该是不能在内容容器内部的 -->
    66. <div class="track" id="scrollbar">
    67. <div class="thumb" id="scrollbar-thumb"></div>
    68. </div>
    69. </div>
    70. <div class="footer"></div>
    71. <script>
    72. const content = document.querySelector(".content")
    73. const track = document.querySelector(".track")
    74. const thumb = document.querySelector(".thumb")
    75. // console.log("window.innerHeight", window.innerHeight)
    76. // track.style.bottom = window.innerHeight + "px"
    77. let contentRec = content.getBoundingClientRect()
    78. track.style.bottom =
    79. content.clientHeight - (window.innerHeight - contentRec.top) + "px"
    80. function updateScrollbar() {
    81. const scrollPercentage =
    82. content.scrollLeft / (content.scrollWidth - content.clientWidth)
    83. const thumbPosition =
    84. scrollPercentage * (track.clientWidth - thumb.clientWidth)
    85. thumb.style.left = thumbPosition + "px"
    86. }
    87. // content(这样还包括了shift+鼠标左键)
    88. content.addEventListener("scroll", updateScrollbar)
    89. // 提取数值进行比较
    90. let trackBottom = parseInt(track.style.bottom) // 将字符串转换为整数
    91. if (
    92. trackBottom <= 0 ||
    93. trackBottom >= content.clientHeight - track.clientHeight
    94. ) {
    95. track.style.bottom = "0px" // 设置时加上单位
    96. }
    97. // 更新 track.style.bottom 的逻辑
    98. document.addEventListener("scroll", function () {
    99. let viewHeight = window.innerHeight + scrollY
    100. contentRec = content.getBoundingClientRect()
    101. // 计算新的 bottom
    102. let newBottom =
    103. content.clientHeight - (window.innerHeight - contentRec.top)
    104. // 确保 newBottom 不小于 0 且不大于 content.clientHeight - track.clientHeight
    105. newBottom = Math.max(
    106. 0,
    107. Math.min(newBottom, content.clientHeight - track.clientHeight)
    108. )
    109. // 更新 track 的 bottom 样式
    110. track.style.bottom = `${newBottom}px`
    111. console.log(track.style.bottom)
    112. })
    113. // 监听滑块拖动事件
    114. let isDragging = false
    115. let startX
    116. let startScrollLeft
    117. thumb.addEventListener("mousedown", function (e) {
    118. isDragging = true
    119. startX = e.clientX
    120. startScrollLeft = content.scrollLeft
    121. // 拖动开始时改变鼠标样式为正在抓取
    122. thumb.style.cursor = "grabbing"
    123. // 防止在拖动时选择文本
    124. e.preventDefault()
    125. })
    126. document.addEventListener("mousemove", function (e) {
    127. if (isDragging) {
    128. const deltaX = e.clientX - startX
    129. const scrollDelta =
    130. (deltaX / track.clientWidth) *
    131. (content.scrollWidth - content.clientWidth)
    132. content.scrollLeft = startScrollLeft + scrollDelta
    133. }
    134. })
    135. document.addEventListener("mouseup", function () {
    136. isDragging = false
    137. })
    138. </script>
    139. </body>
    140. </html>

     演示视频:

    横向滚动条

  • 相关阅读:
    【开源项目】libfaketime安装、使用——小白教程
    XSS攻击
    《JVM学习笔记》字节码基础
    FFmpeg 从视频流中抽取图片
    基于ssm的志愿者管理系统(idea+spring+springmvc+mybatis+jsp)
    elasticsearch基本语法
    MFC 中创建并显示二维码
    2022.11.12-----leetcode.790
    Fortinet Universal SASE能力再度进化!保障用户访问任意应用程序便捷无忧
    输出司机和乘客重合的时间点
  • 原文地址:https://blog.csdn.net/Java_Coder2021/article/details/140945223