滚动时如何在特定div上添加类?

时间:2018-05-30 12:46:03

标签: javascript css panel

我正在玩我的JS(初学者)。我已经创建了堆叠面板,我撞墙了。我只是无法定位并向移动元素添加阴影类(仅当一个面板高于其他面板时,类应该添加)。 现在我有这个:



const boxes = Array.from(document.querySelectorAll(".box"));
    const wrapper = document.querySelector(".wrapper");
    const leftMargin = 60; //px

    function scrollWrap(e) {
        let scrollCoord = wrapper.scrollLeft; // horizontal scroll value
        
        boxes.forEach((box, index) => {
            let leftMarginStop = index * leftMargin;
            const boxCoord = box.getBoundingClientRect();
            let leftCoordPanel = boxCoord.left;
            let flag = false;
            
            
            //console.log({scrollCoord, leftMarginStop, leftCoordPanel, box});
            if (boxCoord.left <= leftMarginStop) { // if left side of pannel is less than margin 60, 120, 180,... 
                //console.log("STAHP!!");
                box.style.position = "sticky";
                box.style.left = `${leftMarginStop}px`; // sets the left to 60, 120, 180,...
                flag = true;
                
                if (flag) {
                    box.classList.add("shadow");
                    console.log(this) //how to target each panel rather than wrapper?
                } else {
                    box.classList.remove("shadow");
                }
                
            } else {
                box.style.position = "static";
                box.style.left = 0;
                flag = false;
            }
        });
    }
    
wrapper.addEventListener("scroll", scrollWrap);
&#13;
body {
    margin: 0;
    padding: 0;
} 
.wrapper, .box1, .box2, .box3, .box4, .box5, .box6, .box7, .box8 {
    position: sticky;
    height: 750px;
    z-index: 1;
} 
.wrapper {
    width: 1442px;
    border-right: 1px solid #f2f2f2;
    border-bottom: 1px solid #f2f2f2;
    display: flex;
    overflow: scroll;
}  
.wrapper .box1 {
    min-width: 357px;
    height: 750px;
    background-color: #1a1a1a;
}
.wrapper .box2 {
    min-width: 357px;
    height: 750px;
    background-color: #333;
}
.wrapper .box3 {
    min-width: 702px;
    height: 750px;
    background-color: #4d4d4d;
}
.wrapper .box4 {
    min-width: 630px;
    height: 750px;
    background-color: #666;
}
.wrapper .box5 {
    min-width: 630px;
    height: 750px;
    background-color: #808080;
}
.wrapper .box6 {
    min-width: 357px;
    height: 750px;
    background-color: #999;
}
.wrapper .box7 {
    min-width: 630px;
    height: 750px;
    background-color: #b3b3b3;
}
.wrapper .box8 {
    min-width: 630px;
    height: 750px;
    background-color: #ccc;
}
.shadow {
    box-shadow: -4px 0px 40px rgba(0, 0, 0, 0.2);   
}
&#13;
<div class="wrapper">
	<div class="box box1"></div>
	<div class="box box2"></div>
	<div class="box box3"></div>
	<div class="box box4"></div>
	<div class="box box5"></div>
	<div class="box box6"></div>
	<div class="box box7"></div>
	<div class="box box8"></div>
</div>
&#13;
&#13;
&#13;

如果有人可以帮助我,请告诉我代码说明,这样我就可以看到并知道什么以及如何。 我尝试使用一些标志或不使用,但每次在元素到达结尾时添加类(左边填充)。我想在元素位于其他元素之上时添加类。如果不是,请删除课程。另外,如何使它适用于鼠标滚轮?我用苹果魔法鼠标测试它,但在滚轮上它不起作用。 哦,拜托,如果你看到一些非常错误的地方请告诉我,我是初学者,并想从这篇文章中学到一些东西。

3 个答案:

答案 0 :(得分:0)

您的代码提示:

  1. CSS代码中,wrapper元素具有width属性。这个 导致页面和wrapper元素具有scrollbars。所以, 删除它。
  2. 您无需使用javascript添加粘性 框。唯一的CSS将为您完成此操作。你只需要JavaScript 用于将left属性和shadow添加到框中。
  3. 不要尝试在父元素上使用overflow: auto|scroll|hidden 一个position:sticky元素。它完全打破了粘性。 overflow: visible没问题。请参阅下面的代码段。
  4. 在您的JavaScript代码中,flag变量值始终为true,所以 shadow类无法从元素中删除。
  5. 其他说明:

    1. 如果您想在内部元素上使用position:absolute 一个粘性元素,你必须要小心。如果您的应用正在运行 一个不支持position:sticky的旧浏览器,那么 粘性元素不会像relative定位元素那样。所以 absolute定位元素将跳过它并查找DOM 树直到找到下一个non-static元素(absolute / relative / fixed position),如果没有,则默认为html元素 找到。换句话说,您的absolute定位元素正在进行中 在屏幕上的方式不同于你预期的方式 是

    2. 很多浏览器都支持
    3. position: sticky;,但还没有 在EdgeIE此时无关紧要。有许多 polyfills如果你绝对必须有这种行为, 但他们都使用JavaScript。更好的选择是设计您的应用程序 所以粘性位置是一个光滑的添加,但应用程序仍然 没有它的功能。

    4. 示例:

      const boxes = Array.from( document.querySelectorAll( '.box' ) ),
            scroller = document.querySelector( '.scroller' ),
            leftMargin = 30,
            length = boxes.length - 1;
      
      function scrollWrap() {
          boxes.forEach( function( box, index ) {
              let leftMarginStop = index * leftMargin;
              const boxCoord = box.getBoundingClientRect();
              let leftCoordPanel = boxCoord.left;
      
              if ( leftCoordPanel <= leftMarginStop ) {
                  box.style.left = leftMarginStop + 'px';
                  if ( index < length ) boxes[ index + 1 ].classList.add( 'shadow' )
                  if ( index == 0 && boxes[ 1 ].getBoundingClientRect().left == box.offsetWidth ) boxes[ 1 ].classList.remove( 'shadow' )
              } else {
                  box.style.left = 0;
                  if ( index < length ) boxes[ index + 1 ].classList.remove( 'shadow' )
              }
          } );
      }
      
      scroller.addEventListener( 'scroll', scrollWrap )
      html,
      body {
          margin: 0;
          height: 100%
      }
      .scroller {
          height: 100%;
          display: flex;
          align-items: center;
          overflow-x: auto;
          overflow-y: hidden
      }
      .wrapper {
          height: 100%;
          display: flex
      }
      .box {
          min-width: 630px;
          height: 100%;
          position: -webkit-sticky;
          position: sticky;
          left: 0 /* <-- become sticky once touching left edge */
      }
      .box1 {
          min-width: 357px;
          background: #1a1a1a url(https://cdn.pixabay.com/photo/2015/12/10/16/09/seamless-pattern-1086662__340.jpg)
      }
      .box2 {
          min-width: 357px;
          background: #333 url(https://cdn.pixabay.com/photo/2015/12/18/23/46/template-1099298__340.png)
      }
      .box3 {
          min-width: 702px;
          background: #4d4d4d url(https://cdn.pixabay.com/photo/2014/07/28/16/00/pattern-403769__340.png)
      }
      .box4 {
          background: #666 url(https://cdn.pixabay.com/photo/2017/06/10/03/14/damask-2388884__340.png)
      }
      .box5 {
          background: #808080 url(https://cdn.pixabay.com/photo/2015/12/12/17/34/seamless-pattern-1089797__340.png)
      }
      .box6 {
          min-width: 357px;
          background: #999 url(https://cdn.pixabay.com/photo/2016/03/06/16/23/background-1240686__340.png)
      }
      .box7 {
          background: #b3b3b3 url(https://cdn.pixabay.com/photo/2018/04/24/05/00/backdrop-3346304__340.png)
      }
      .box8 {
          background: #ccc url(https://cdn.pixabay.com/photo/2016/04/01/09/03/floral-1299131__340.png)
      }
      .shadow {
          box-shadow: -10px 0px 40px rgba(0, 0, 0, 1);
      }
      <div class="scroller">
          <div class="wrapper">
              <div class="box box1"></div>
              <div class="box box2"></div>
              <div class="box box3"></div>
              <div class="box box4"></div>
              <div class="box box5"></div>
              <div class="box box6"></div>
              <div class="box box7"></div>
              <div class="box box8"></div>
          </div>
      </div>

      关于您更新的代码:

      jS代码中的以下行:

      const leftSideOfNextItem = box.nextElementSibling.getBoundingClientRect().left;
      

      导致错误。因为,当index变为8时,box.nextElementSibling无法检索任何元素。所以你可以改成它:

      const leftSideOfNextItem = ( index < boxes.length - 1 ) ? box.nextElementSibling.getBoundingClientRect().left : 0;
      

      在JS代码的最后,还有以下代码片段:

      if (index[4] && leftSideOfCurrent < leftMarginStop) {
        console.log("helo");
      }
      

      必须改为:

      // when panel 5 reach left margin, left margin change from 60 to 30 to all panels
      if (index == 4 && leftSideOfCurrent <= leftMarginStop) {
        console.log("helo");
        leftMargin = 30
      }
      

      此外,您必须将const leftMargin = 60;更改为var leftMargin = 60;

      更新代码:

      const boxes = Array.from(document.querySelectorAll(".box"));
      const wrapper = document.querySelector(".wrapper");
      var leftMargin = 60; //px
      
      function scrollWrap(e) {
          let scrollCoord = wrapper.scrollLeft; // horizontal scroll value
      
          boxes.forEach((box, index) => {
              let leftMarginStop = (index) * leftMargin; // calculation for left margin stop (60, 120, 180,...)
              const boxCoord = box.getBoundingClientRect();
              const leftSideOfCurrent = boxCoord.left; // coordinarion of left side of panel
              const rightSideOfCurrent = boxCoord.right; // coordinarion of right side of panel
              const leftSideOfNextItem = ( index < boxes.length - 1 ) ? box.nextElementSibling.getBoundingClientRect().left: 0; // coordinarion of left side of NEXT panel
      
              box.style.position = "sticky";
              box.style.left = `${leftMarginStop}px`;
      
              // controll shadow of first element
              scrollCoord > 0 ? boxes[1].classList.add("shadow") : boxes[1].classList.remove("shadow");
              // controll shadow of all 0+ elements
              if (leftSideOfCurrent <= leftMarginStop) { // if left side of pannel is less than margin 60, 120, 180,... 
                  box.nextElementSibling.classList.add("shadow");
              }
              // controll removal of shadow of all 0+ elements
              if (leftSideOfNextItem === rightSideOfCurrent) {
                  box.nextElementSibling.classList.remove("shadow");  
              }
              // when panel 5 reach left margin, left margin change from 60 to 30 to all panels
              if (index == 4 && leftSideOfCurrent <= leftMarginStop) {
                  console.log("helo");
                  leftMargin = 30
              }
          });
      }
      
      wrapper.addEventListener("scroll", scrollWrap);
      body {
          margin: 0;
          padding: 0;
      } 
      .wrapper, .box0, .box1, .box2, .box3, .box4, .box5, .box6, .box7 {
          position: sticky;
          height: 750px;
          z-index: 1;
      } 
      .wrapper {
          width: 1442px;
          border-right: 1px solid #f2f2f2;
          border-bottom: 1px solid #f2f2f2;
          display: flex;
          overflow: scroll;
      }  
      .wrapper .box0 {
          min-width: 357px;
          background-color: #1a1a1a;
      }
      .wrapper .box1 {
          min-width: 357px;
          background-color: #333;
      }
      .wrapper .box2 {
          min-width: 702px;
          background-color: #4d4d4d;
      }
      .wrapper .box3 {
          min-width: 630px;
          background-color: #666;
      }
      .wrapper .box4 {
          min-width: 630px;
          background-color: #808080;
      }
      .wrapper .box5 {
          min-width: 357px;
          background-color: #999;
      }
      .wrapper .box6 {
          min-width: 630px;
          background-color: #b3b3b3;
      }
      .wrapper .box7 {
          min-width: 630px;
          background-color: #ccc;
      }
      .shadow {
          box-shadow: -4px 0px 40px rgba(0, 0, 0, 1.2);
          -webkit-transition: box-shadow 0.2s cubic-bezier(0.4,-0.01, 0, 0.98);
          -moz-transition: box-shadow 0.2s cubic-bezier(0.4,-0.01, 0, 0.98);
          -o-transition: box-shadow 0.2s cubic-bezier(0.4,-0.01, 0, 0.98);
          transition: box-shadow 0.2s cubic-bezier(0.4,-0.01, 0, 0.98);
      }
      /* To make the console visible. */
      .box0 {
        height: 700px;
      )
      <div class="wrapper">
              <div class="box box0"></div>
              <div class="box box1"></div>
              <div class="box box2"></div>
              <div class="box box3"></div>
              <div class="box box4"></div>
              <div class="box box5"></div>
              <div class="box box6"></div>
              <div class="box box7"></div>
      </div>

答案 1 :(得分:0)

现在我已设法更新我的代码。它适用于我滚动和阴影也适用于面板。还有一些我不知道的事情。

  1. 当我添加阴影类时,我创建了转换。它工作得很完美,但是当我删除阴影类时它就会消失,没有过渡回来。这是为什么?我希望阴影以同样的方式出现和消失
  2. 如果每个面板到达左边距,如何跟踪每个面板,并且在鼠标输入和鼠标停留的情况下应用eventListener?所以,当我徘徊到&#34;关闭&#34;小组,我得到那个项目,如果我徘徊在NOT&#34;关闭&#34;小组我不会得到项目。我正在尝试使用console.log&#34;这个&#34;但它返回了鼠标输入的每个面板
  3. 如何定位每个面板,以后我可以说,当第4个面板到达左边距时,堆叠元素的边距会发生变化?
  4. 我的更新代码:

    &#13;
    &#13;
    const boxes = Array.from(document.querySelectorAll(".box"));
    const wrapper = document.querySelector(".wrapper");
    const leftMargin = 60; //px
    
    function scrollWrap(e) {
        let scrollCoord = wrapper.scrollLeft; // horizontal scroll value
    
        boxes.forEach((box, index) => {
            let leftMarginStop = (index) * leftMargin; // calculation for left margin stop (60, 120, 180,...)
            const boxCoord = box.getBoundingClientRect();
            const leftSideOfCurrent = boxCoord.left; // coordinarion of left side of panel
            const rightSideOfCurrent = boxCoord.right; // coordinarion of right side of panel
            const leftSideOfNextItem = box.nextElementSibling.getBoundingClientRect().left; // coordinarion of left side of NEXT panel
    
            box.style.position = "sticky";
            box.style.left = `${leftMarginStop}px`;
    
            // controll shadow of first element
            scrollCoord > 0 ? boxes[1].classList.add("shadow") : boxes[1].classList.remove("shadow");
            // controll shadow of all 0+ elements
            if (leftSideOfCurrent <= leftMarginStop) { // if left side of pannel is less than margin 60, 120, 180,... 
                box.nextElementSibling.classList.add("shadow");
            }
            // controll removal of shadow of all 0+ elements
            if (leftSideOfNextItem === rightSideOfCurrent) {
                box.nextElementSibling.classList.remove("shadow");  
            }
            // when panel 5 reach left margin, left margin change from 60 to 30 to all panels
            if (boxes[4] && leftSideOfCurrent < leftMarginStop) {
                console.log("helo");
            }
        });
    }
    
    wrapper.addEventListener("scroll", scrollWrap);
    &#13;
    body {
        margin: 0;
        padding: 0;
    } 
    .wrapper, .box1, .box2, .box3, .box4, .box5, .box6, .box7, .box8 {
        position: sticky;
        height: 750px;
        z-index: 1;
    } 
    .wrapper {
        width: 1442px;
        border-right: 1px solid #f2f2f2;
        border-bottom: 1px solid #f2f2f2;
        display: flex;
        overflow: scroll;
    }  
    .wrapper .box0 {
        min-width: 357px;
        background-color: #1a1a1a;
    }
    .wrapper .box1 {
        min-width: 357px;
        background-color: #333;
    }
    .wrapper .box2 {
        min-width: 702px;
        background-color: #4d4d4d;
    }
    .wrapper .box3 {
        min-width: 630px;
        background-color: #666;
    }
    .wrapper .box4 {
        min-width: 630px;
        background-color: #808080;
    }
    .wrapper .box5 {
        min-width: 357px;
        background-color: #999;
    }
    .wrapper .box6 {
        min-width: 630px;
        background-color: #b3b3b3;
    }
    .wrapper .box7 {
        min-width: 630px;
        background-color: #ccc;
    }
    .shadow {
        box-shadow: -4px 0px 40px rgba(0, 0, 0, 1.2);
        -webkit-transition: box-shadow 0.2s cubic-bezier(0.4,-0.01, 0, 0.98);
        -moz-transition: box-shadow 0.2s cubic-bezier(0.4,-0.01, 0, 0.98);
        -o-transition: box-shadow 0.2s cubic-bezier(0.4,-0.01, 0, 0.98);
        transition: box-shadow 0.2s cubic-bezier(0.4,-0.01, 0, 0.98);
    }
    &#13;
    <div class="wrapper">
            <div class="box box0"></div>
            <div class="box box1"></div>
            <div class="box box2"></div>
            <div class="box box3"></div>
            <div class="box box4"></div>
            <div class="box box5"></div>
            <div class="box box6"></div>
            <div class="box box7"></div>
        </div>
    &#13;
    &#13;
    &#13;

答案 2 :(得分:0)

这很有帮助。我知道错误但无法修复它。我已设置let leftMargin = 60;我使用let而不是var。 我正在边缘工作,如果第5个面板到达左边距,所有面板的边距都会达到30px。我这样做也是为了逆转:

&#13;
&#13;
if (index > 4 && leftSideOfCurrent <= leftMarginStop) {
    leftMargin = 30;
} else if (index < 5 && leftSideOfCurrent > leftMarginStop) {
    leftMargin = 60;
}
&#13;
&#13;
&#13;

但是现在当第5个面板到达左边距时,小于5的面板单独转换而不是全部转换,但是当第5个元素不再处于左边距时,所有面板都会同时转换。为什么会那样?我不明白。你能解释一下吗?