Как добавить класс на конкретный div при прокрутке? - PullRequest
0 голосов
/ 30 мая 2018

Я играю и тренируюсь в 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>

Если кто-нибудь может мне помочь, пожалуйста, покажите мне код с объяснением, чтобы я мог видеть и знать, что и как.Я пытаюсь сделать это с некоторым флагом или без, но каждый раз, когда класс добавляется, когда элемент достигает конца (левый отступ).Я хочу добавить класс, когда элемент находится поверх другого элемента.Если это не так, удалите класс.Кроме того, как сделать так, чтобы он работал на колесе прокрутки мыши?Я проверял это с помощью apple magic mouse, но на колесе прокрутки он не работает.О, и пожалуйста, если вы видите что-то очень неправильное, пожалуйста, дайте мне знать, я новичок и хотел бы узнать что-то из этого поста.

Ответы [ 3 ]

0 голосов
/ 31 мая 2018

На данный момент мне удалось обновить мой код.Это работает, когда я прокручиваю и тень также применяется к панели.Есть еще кое-что, что мне интересно.

  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>
0 голосов
/ 01 июня 2018

Это было полезно.Я знаю по ошибке, но не мог это исправить.Я установил let leftMargin = 60; Я использую пусть вместо Var.Я работаю над полями, если 5-я панель достигает левого поля, поля всех панелей получают 30px.Я сделал это также для реверса:

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

Но теперь, когда 5-я панель достигает левого поля, панели менее 5 переходят КАЖДОЙ переход вместо каждого отдельно, но когда 5-й элемент больше не находится в левом поле, всеполучает переход в то же время.Почему это так?Я не понимаю.Можете ли вы объяснить, пожалуйста?

0 голосов
/ 31 мая 2018

Советы для вашего кода:

  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 не может быть удален из элементов.

Другие примечания:

Если вы хотите использовать position:absolute для элемента внутри липкого элемента, вы должны быть осторожны.Если ваше приложение работает в более старом браузере, который не поддерживает position:sticky, то этот прикрепленный элемент не будет действовать как позиционный элемент relative.Таким образом, позиционированный элемент absolute пропустит его и будет искать дерево DOM, пока не найдет следующий non-static элемент (absolute / relative / fixed position), по умолчанию равный элементу html, если ничего не найдено.Другими словами, ваш позиционированный элемент absolute будет находиться в другом месте на экране, чем вы ожидали.

position: sticky; поддерживается многимибраузеры, но еще не в Edge.IE на данном этапе не имеет значения.Существует множество 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 следующий фрагмент кода:

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>
...