如何使用JavaScript / CSS制作圆形ScrollBox?

时间:2019-03-02 16:58:48

标签: javascript jquery html css scroll

我要重新创建圆形滚动框,如下面的GIF所示,

enter image description here

我不认为为什么可以使用css制作圆形滚动框,所以我想到将padding-left添加到ul的每个子元素中以使滚动框显示为圆形。

要实现这一目标,
将0px的填充添加到li-1
将2px的填充添加到li-2
将4px的填充添加到li-3
将6px的填充内容添加到li-4
将8px的填充添加到li-5
将6px的填充添加到li-6
将4px的填充添加到li-7
将2px的填充添加到li-8
将0px的填充内容添加到li-9

滚动填充上的

可以更改为 将0px的填充添加到li-2
将2px的填充添加到li-3
将4px的填充添加到li-4
将6px的填充内容添加到li-5
将8px的填充添加到li-6
将6px的填充添加到li-7
向li-8添加4px的填充
将2px的填充添加到li-9
将0px的填充添加到li-10上,依此类推...

我的代码存在的问题是,当通过鼠标滚轮滚动滚动框时,它可以正常运行,但是当用户使用滚动标签/滚动按钮时 在滚动条中,填充急剧增加。

到目前为止,我的代码是:

var scrollBox = $(".circularScrollbox"),
  num = $(".scrollboxList li").length,
  vjListItem = $(".vjListItem"),
  max = num * 3,
  padding = 0,
  currentPadding = padding,
  scrollPos = scrollBox.scrollTop();

scrollBox.scroll(function() {
  if (scrollPos < scrollBox.scrollTop() && currentPadding < max) {
    currentPadding += 2;
    vjListItem.css("padding", "0 0 0 " + currentPadding + "px");
  } else if (scrollPos > scrollBox.scrollTop() && currentPadding > padding) {
    currentPadding -= 2;
    vjListItem.css("padding", "0 0 0 " + currentPadding + "px");
  }
  if (scrollBox.scrollTop() == 0) vjListItem.css("padding", padding + "px");
  scrollPos = scrollBox.scrollTop();
});
body {
  display: flex;
  flex-direction: column;
  height: 95vh;
  justify-content: center;
  align-items: center;
  background: #222;
  color: #eee;
  font-family: 'Ubuntu Mono', monospace;
}

.circularScrollbox {
  width: 200px;
  height: 10.6em;
  padding: 0 2em;
  overflow-Y: scroll;
  background: #161616;
  border: 2px solid aqua;
}

.circularScrollbox>ol {
  list-style-type: none;
  padding-left: 0;
}
<head>
  <link href="https://fonts.googleapis.com/css?family=Ubuntu+Mono" rel="stylesheet">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>

<body>
  <div class='circularScrollbox'>
    <ol class='scrollboxList'>
      <li class="vjListItem">Item 01</li>
      <li class="vjListItem">Item 02</li>
      <li class="vjListItem">Item 03</li>
      <li class="vjListItem">Item 04</li>
      <li class="vjListItem">Item 05</li>
      <li class="vjListItem">Item 06</li>
      <li class="vjListItem">Item 07</li>
      <li class="vjListItem">Item 08</li>
      <li class="vjListItem">Item 09</li>
      <li class="vjListItem">Item 10</li>
      <li class="vjListItem">Item 11</li>
      <li class="vjListItem">Item 12</li>
      <li class="vjListItem">Item 13</li>
      <li class="vjListItem">Item 14</li>
      <li class="vjListItem">Item 15</li>
      <li class="vjListItem">Item 16</li>
      <li class="vjListItem">Item 17</li>
      <li class="vjListItem">Item 18</li>
      <li class="vjListItem">Item 19</li>
      <li class="vjListItem">Item 20</li>
      <li class="vjListItem">Item 21</li>
      <li class="vjListItem">Item 22</li>
      <li class="vjListItem">Item 23</li>
      <li class="vjListItem">Item 24</li>
      <li class="vjListItem">Item 25</li>
      <li class="vjListItem">Item 26</li>
      <li class="vjListItem">Item 27</li>
      <li class="vjListItem">Item 28</li>
      <li class="vjListItem">Item 29</li>
      <li class="vjListItem">Item 30</li>
      <li class="vjListItem">Item 31</li>
      <li class="vjListItem">Item 32</li>
      <li class="vjListItem">Item 33</li>
      <li class="vjListItem">Item 34</li>
      <li class="vjListItem">Item 35</li>
      <li class="vjListItem">Item 36</li>
      <li class="vjListItem">Item 37</li>
      <li class="vjListItem">Item 38</li>
      <li class="vjListItem">Item 39</li>
      <li class="vjListItem">Item 40</li>
    </ol>
  </div>
</body>

我确定我在填充和填充方面使问题变得过于复杂。有没有更简单的方法可以达到这种效果?

2 个答案:

答案 0 :(得分:5)

对于列表中的每个项目,填充量取决于:

  1. 它在框中的位置
  2. 滚动框多少
  3. 由于“圆形”的东西,盒子有多大

使用jQuery,$item.offset().top可以在页面上显示项目的Y位置。
其中包括滚动,因此滚动框时该值会降低。

现在$item.offset().top - $box.offset().top相对于框顶部的位置
如果滚动了该框,以使Item 23位于顶部,则其值将为0,而位于底部(但仍可见)的任何项目的值将为该框的高度。

所以除以高度:($item.offset().top - $box.offset().top) / $box.height()

每个(可见)项目现在的值都在0到1之间,告诉您当前该项目是在框的顶部,底部还是在之间!

然后您可以使用三角函数,例如:Math.sin(value*Math.PI) * maxPadding

Working example

答案 1 :(得分:4)

这是一个仅依赖CSS和少量JS的解决方案。诀窍是考虑使shape-outside具有曲线,而JS仅用于调整形状在滚动上的位置。

这是一种非常简单的方法,但是您需要注意浏览器的支持(https://caniuse.com/#feat=css-shapes

var shape = document.querySelector(".left");

document.querySelector(".circularScrollbox").onscroll=function() {
   shape.style.marginTop = this.scrollTop+"px";
};
body {
  display: flex;
  flex-direction: column;
  height: 95vh;
  justify-content: center;
  align-items: center;
  background: #222;
  color: #eee;
  font-family: 'Ubuntu Mono', monospace;
}

.circularScrollbox {
  width: 200px;
  height: 10.6em;
  padding: 0 2em;
  overflow-Y: scroll;
  background: #161616;
  border: 2px solid aqua;
}

.circularScrollbox>ol {
  list-style-type: none;
  padding-left: 0;
}

.left {
  float: left;
  shape-outside: ellipse(50px 85px at 0% calc(100% - 85px));
  width: 100px;
  height: 100%;
  margin-top:0;
}
<link href="https://fonts.googleapis.com/css?family=Ubuntu+Mono" rel="stylesheet">

<div class='circularScrollbox'>
  <div class="left"></div>
  <ol class='scrollboxList'>
    <li class="vjListItem">Item 01</li>
    <li class="vjListItem">Item 02</li>
    <li class="vjListItem">Item 03</li>
    <li class="vjListItem">Item 04</li>
    <li class="vjListItem">Item 05</li>
    <li class="vjListItem">Item 06</li>
    <li class="vjListItem">Item 07</li>
    <li class="vjListItem">Item 08</li>
    <li class="vjListItem">Item 09</li>
    <li class="vjListItem">Item 10</li>
    <li class="vjListItem">Item 11</li>
    <li class="vjListItem">Item 12</li>
    <li class="vjListItem">Item 13</li>
    <li class="vjListItem">Item 14</li>
    <li class="vjListItem">Item 15</li>
    <li class="vjListItem">Item 16</li>
    <li class="vjListItem">Item 17</li>
    <li class="vjListItem">Item 18</li>
    <li class="vjListItem">Item 19</li>
    <li class="vjListItem">Item 20</li>
    <li class="vjListItem">Item 21</li>
    <li class="vjListItem">Item 22</li>
    <li class="vjListItem">Item 23</li>
    <li class="vjListItem">Item 24</li>
    <li class="vjListItem">Item 25</li>
    <li class="vjListItem">Item 26</li>
    <li class="vjListItem">Item 27</li>
    <li class="vjListItem">Item 28</li>
    <li class="vjListItem">Item 29</li>
    <li class="vjListItem">Item 30</li>
    <li class="vjListItem">Item 31</li>
    <li class="vjListItem">Item 32</li>
    <li class="vjListItem">Item 33</li>
    <li class="vjListItem">Item 34</li>
    <li class="vjListItem">Item 35</li>
    <li class="vjListItem">Item 36</li>
    <li class="vjListItem">Item 37</li>
    <li class="vjListItem">Item 38</li>
    <li class="vjListItem">Item 39</li>
    <li class="vjListItem">Item 40</li>
  </ol>
</div>