【问题标题】:How to add class on specific div when scroll?滚动时如何在特定的div上添加类?
【发布时间】:2018-11-09 07:58:41
【问题描述】:

我正在玩耍并练习我的 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);
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);   
}
<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>

如果有人可以帮助我,请向我展示带有解释的代码,这样我就可以看到并知道什么和如何。 我尝试使用或不使用某些标志来执行此操作,但是每次在元素到达末尾(左填充)时添加类。当元素位于其他元素之上时,我想添加类。如果不是,请删除类。另外,如何使它在鼠标滚轮上工作?我正在用苹果魔术鼠标对此进行测试,但在滚轮上它不起作用。 哦,拜托,如果您发现有什么非常不对的地方,请告诉我,我是初学者,想从这篇文章中学到一些东西。

【问题讨论】:

  • 绕过过滤器并不是最好的事情......在问题中发布代码。使用允许您拥有与 jsfiddle 中相同的功能的 snipplet。 i.stack.imgur.com/522IS.png
  • 另外,它的“哦”,而不是“哦”! :)
  • 完成 ;)。谢谢,我没看到。

标签: javascript css panel


【解决方案1】:

代码提示:

  1. 在您的CSS 代码中,wrapper 元素具有width 属性。这 导致页面和wrapper 元素具有scrollbars。所以, 删除它。
  2. 您不需要使用javascript 来添加粘性到 盒子。唯一的CSS 会为您执行此操作。你只需要 JavaScript 将left 属性和shadow 添加到框中。
  3. 不要尝试在父元素上使用overflow: auto|scroll|hidden position:sticky 元素。它完全打破了粘性。 overflow: visible 很好。请参阅下面的代码 sn-p。
  4. 在您的 JavaScript 代码中,flag 变量值始终为真,所以 shadow 类无法从元素中移除。

其他说明:

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

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

示例:

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代码的最后,下面的代码sn-p:

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.我设置宽度是因为我想模拟窗口,我想要滚动条。这是我获得滚动条的唯一方法。我看到你创建滚动类作为容器,而不是包装器以 100% 的容器宽度 2。我知道这可以用 CSS 完成,但我想添加 JS,因为我稍后会在元素位于左侧时进行悬停,控制阴影等。我也更新了我的代码。但仍有一些问题我不知道答案。请往下看。并感谢您的回复
  • 我已经成功更新了我的代码,请看我的答案(小字符到这里)
【解决方案2】:

现在我已经设法更新了我的代码。当我滚动并且阴影也应用于面板时,它可以工作。我仍然想知道一些事情。

  1. 当我添加阴影类时,我创建了过渡。它工作得很好,但是当我删除影子类时,它就消失了,没有过渡回来。这是为什么?我希望阴影以同样的方式出现和消失
  2. 如何在每个面板到达左边距时跟踪它,然后在鼠标进入和鼠标离开时应用 eventListener?因此,当我将鼠标悬停在“关闭”面板上时,我会得到该项目,如果我将鼠标悬停在非“关闭”面板上,我将不会获得项目。我正在尝试使用 console.log “this”,但它返回了我鼠标输入的每个面板
  3. 如何定位每个面板,所以我以后可以说,当第 4 个面板到达左边距时,堆叠元素的边距会改变?

我更新的代码:

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);
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);
}
<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>

【讨论】:

    【解决方案3】:

    这很有帮助。我知道错误但无法修复它。我已经设置了let leftMargin = 60; 我使用 let 代替 var。 我正在处理边距,如果第 5 个面板到达左边距,则所有面板的边距都为 30px。我也这样做了:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-15
      • 2019-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多