代码之家  ›  专栏  ›  技术社区  ›  Ardeus

带溢出的可视容器中的中心点

  •  0
  • Ardeus  · 技术社区  · 6 年前

    如何在可视容器溢出中居中点,如您所见 fiddle here

    当单击第一个点1到3时,它们按计划粘在顶部工作,从第4个点和第5个点开始,它们应调整顶部距离,使其居中于容器,单击第6个点、第7个点、第8个点应保持在底部。

    当然,当我增加总点数(比如9或10个点)时,这个例子不起作用。我找不到正确的数学公式,知道吗?

    非常感谢。

    const ul = document.getElementsByClassName('list')[0];
    const list = document.querySelectorAll('.list li');
    const total = 5;
    const offset = total / 2;
    const circleTotalHeight = 40;
    
    const totalViewable = 5;
    const totalHeight = circleTotalHeight * list.length;
    const totalViewableHeight = total * circleTotalHeight;
    const limitTopOffset = totalViewableHeight - totalHeight; // -120
    const halfViewableCount = Math.ceil(totalViewable / 2); //3
    const halfTotalCount = Math.ceil(list.length / 2); //4
    const centerViewablePx = 160;
    
    let activeIndex = 0;
    let nthActiveIndex = activeIndex + 1;
    
    Array.prototype.forEach.call(list, (li) => {
      li.addEventListener('click', (e) => {
        let data = e.target.getAttribute("data-number");
        const prevElement = `[data-number="${activeIndex}"]`;
        const nextElement = `[data-number="${data}"]`;
    
        ul.querySelector(nextElement).style.color = '#FFF';
        ul.querySelector(prevElement).style.color = '#000';
    
        nthActiveIndex = parseInt(data) + 1;
        var nthActiveOffset = nthActiveIndex - halfViewableCount;
        if (data < halfTotalCount && data < halfViewableCount) {
          ul.style.top = '0';
        } else if (data > halfTotalCount && data > halfViewableCount) {
          ul.style.top = `${limitTopOffset}px`;
        } else {
          let midTopOffset = 0;
          if (data < halfTotalCount) {
            midTopOffset = (nthActiveIndex * circleTotalHeight) / 2;
          } else {
            midTopOffset = (nthActiveIndex * circleTotalHeight) - 160;
          }
    
          const dotContainerTopValue = midTopOffset + limitTopOffset;
          //alert(midTopOffset);
          if (dotContainerTopValue >= 0) {
            ul.style.top = '0';
          } else {
            ul.style.top = `${dotContainerTopValue}px`;
          }
        }
    
        activeIndex = data;
      });
    })
    .list {
      list-style-type: none;
      position: absolute;
      top: 0;
      left: 0;
      padding: 0;
      margin: 0;
    }
    .list li {
      width: 20px;
      height: 20px;
      display: block;
      background: red;
      border-radius: 50%;
      text-align: center;
      margin-top: 10px;
      margin-bottom: 10px;
      cursor: pointer;
      font-size: 12px;
      float: right;
    }
    .list-container {
      height: 200px;
      width: 20px;
      background: #42b549;
      opacity: 0.5;
      position: relative;
      margin: auto;
      top: 160px;
    }
    <div class="list-container">
      <ul class="list">
        <li data-number="0">1</li>
        <li data-number="1">2</li>
        <li data-number="2">3</li>
        <li data-number="3">4</li>
        <li data-number="4">5</li>
        <li data-number="5">6</li>
        <li data-number="6">7</li>
        <li data-number="7">8</li>
      </ul>
    </div>
    1 回复  |  直到 6 年前
        1
  •  0
  •   Ardeus    6 年前

    我想我找到了一个解决办法 here . 我希望不要错过任何东西。

    const ul = document.getElementsByClassName('list')[0];
    const list = document.querySelectorAll('.list li');
    const total = 5;
    const offset = total / 2;
    const circleTotalHeight = 30;
    
    const totalViewable = 5;
    const totalHeight = circleTotalHeight * list.length;
    const totalViewableHeight = totalViewable * circleTotalHeight;
    const limitTopOffset = totalViewableHeight - totalHeight; // -120
    const halfViewableCount = totalViewable / 2; //2.5
    const halfTotalCount = Math.ceil(list.length / 2); //4
    const diffTotalAndView = list.length - totalViewable; // 3
    
    
    let activeIndex = 0;
    let nthActiveIndex = activeIndex + 1;
    
    Array.prototype.forEach.call(list, (li) => {
      li.addEventListener('click', (e) => {
        let data = e.target.getAttribute("data-number");
        const prevElement = `[data-number="${activeIndex}"]`;
        const nextElement = `[data-number="${data}"]`;
    
        ul.querySelector(nextElement).style.color = '#FFF';
        ul.querySelector(prevElement).style.color = '#000';
    
        nthActiveIndex = parseInt(data) + 1;
        var nthActiveOffset = nthActiveIndex - halfViewableCount;
        var nthOffset = Math.floor(nthActiveIndex - halfViewableCount);
    
        if (nthOffset >= 0) {
    
          //console.log(nthOffset);
          if (nthOffset < diffTotalAndView) {
            var topDistance = -1 * (nthOffset * circleTotalHeight);
            ul.style.top = `${topDistance}px`;
          } else {
            ul.style.top = `${limitTopOffset}px`;
          }
    
        } else {
          ul.style.top = '0';
        }
    
        activeIndex = data;
      });
    })