Изменение вертикальной прокрутки на горизонтальную в точке для определенного элемента

#javascript #html #css #reactjs #scroll

#javascript #HTML #css #reactjs #прокрутка

Вопрос:

Что такое контекст?

У меня есть веб-сайт, который представляет собой одну страницу, где я представлю свою деятельность и проекты После прокрутки нескольких разделов, у нас есть проекты подряд.

Что я хочу сделать?

Я хочу поменять вертикальную прокрутку на horizonta, когда мы перейдем к строке моих проектов. Когда вы находитесь в конце строки, он просто должен вернуться к нормальному состоянию с помощью вертикальной прокрутки.

Код

 <div className="projectsContainer">     // <--- height 100vh
    <div className="row projects">     //  <--- Positioned in the middle of the parent ↑
        <project1  />
        <project2  />
        <project3  />
        <project4  />
        <project5  />
    </div>
</div>
  

Каков мой код? И что я подумал

У меня есть метод inTheMiddle() , который является логическим. Если <div className="row projects"> он находится в середине окна просмотра, он возвращает true else false .

Метод scrollDirection() , который также является логическим, true когда прокрутка идет вниз false , когда она идет вверх.

Много разных методов disableScroll() Последний disableScroll() метод отменяет прокрутку путем ее повторного вычисления

 componentDidMount() {
     window.addEventListener('wheel', (this.handleScroll));
}
...
disableScroll() {
    // Get the current page scroll position 
    const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
    const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
    // if any scroll is attempted, set this to the previous value 
    window.onscroll = () => {
        window.scrollTo(scrollLeft, scrollTop);
    };
}
  

И мой метод handleScroll(), который управляет всем этим

 handleScroll(event) {
    const rowProjects = document.querySelector(".row.projects")
    const projectsContainer = document.querySelector(".projectsContainer")
    const isSticky = rowProjects.classList.contains("sticky") 
// isSticky is useless now was try by adding position fixed and no need to use disableScroll()

    if (this.inTheMiddle() amp;amp; this.state.scrollDown amp;amp; this.state.count < 1400 ) {
        this.disableScroll()
        this.setState({ count: this.state.count   10 })
        rowProjects.scroll(this.state.count, 0)
    } else if ((!this.state.scrollDown) amp;amp; this.state.count > 0) {
        this.setState({ count: this.state.count - 10 })
        rowProjects.scroll(this.state.count, 0)
    }

}
  

Что мне не удается, так это вернуться к нормальной жизни. Когда вы доходите до конца строки, я не могу повторно прокручивать прокрутку или когда я прокручиваю до верха страницы. Он застрял в строке проектов.

Я справился с isSticky этим, удалив disableScroll() и добавив класс с фиксированной позицией, но проблема заключалась в том, что он отскочил. Потому что, когда он находится в середине, я зафиксировал его в середине окна просмотра, поэтому элемент больше не находится в относительном положении, поэтому он отскочил как сбой (например, удаление блока стекового блока) извините за плохой пример: ‘)

Если у вас есть какие-либо идеи, чтобы помочь мне, это было бы очень любезно. Я ломаю голову в течение 3 дней, и я все еще не нашел идеального решения.

Комментарии:

1. morioh.com/p/7c097570ecd9

2. итак, простыми словами, вы хотите, чтобы прокрутка была только горизонтальной, а не вертикальной, верно?

3. о, вы хотите иметь возможность убрать вертикальную прокрутку, когда вы дойдете до строки проектов, вот и все. Ну, тогда вы можете использовать Javascript для этого.

4. Я попробую то, что вы дали мне diedu, с дополнительным кодом. Может работать хорошо.

5. Натан Виджаясекара Да, но не только, он должен уходить вертикально и быть горизонтальным на время строки. Затем, когда строка находится в конце, она должна вернуться к вертикальной прокрутке. Я почти сделал это, но каждый раз с небольшим сбоем или другим

Ответ №1:

Это должно работать нормально.Вы можете выполнить вертикальную прокрутку и использовать значение window.scrollY для перемещения элемента по горизонтали, присвоив ему значение в element.style .слева, тем самым придавая ему эффект горизонтальной прокрутки.Я сделал то же самое, и это сработало

(Смотрите результат во весь экран).

 var content = document.getElementById('content_2');
window.addEventListener('scroll', function() {
  var scrolledY = window.scrollY;
  var scrolledX = window.scrollX;

  if (scrolledY > 625 amp;amp; scrolledY < 3112) {
    content.style.marginTop = 150   'px';
    content.style.position = "fixed";
    content.style.top = scrolledY * 0.001   'px';
    content.style.left = -(scrolledY - 625) * 0.55   'px';

  }
  if (scrolledY <= 625) {
    content.style.position = "initial";

  }
  if (scrolledY >= 3112) {

    content.style.position = "absolute";
    content.style.top = 3112   'px';

  }


});  
 * {
  margin: 0px;
  padding: 0px;
  font-family: 'Arial';
  overflow-x: hidden;
  scroll-behavior: smooth;
}

body {
  min-height: 4400px;
}

.content_1,
.content_2 {
  height: 100vh;
  width: 100vw;
}

.content_1 {
  background-color: black;
  color: white;
}

.content_1 h1 {
  font-size: 200px;
  text-align: center;
}

.content_2 {
  margin-top: 150px;
  top: 625px;
  white-space: nowrap;
  display: flex;
  height: 80vh;
  width: 200vw;
  position: fixed;
  flex-direction: row;
  flex-wrap: nowrap;
}

.content_3 {
  font-size: 20px;
  margin-top: 3050px;
}

.card {
  background-color: red;
  color: white;
  white-space: nowrap;
  text-align: center;
  height: 300px;
  width: 300px;
  margin: 10px 30px 10px 10px;
}  
 <div class="content_1">
  <h1>First Page</h1>
</div>
<div class="content_2" id="content_2">
  <div class="card" style="background-color: #FF7A7A;">Card-1</div>
  <div class="card" style="background-color: #FF3C3C;">Card-2</div>
  <div class="card">Card-3</div>
  <div class="card" style="background-color: #FF3600;">Card-4</div>
  <div class="card" style="background-color: #FF871C;">Card-5</div>
  <div class="card" style="background-color: #FFA91C;">Card-6</div>
  <div class="card" style="background-color: #FFC11D;">Card-7</div>
  <div class="card" style="background-color: #FFF81D;">Card-8</div>
</div>
<div class="content_3">
  <p>Senectus purus, molestie blandit sociis eu leo blandit platea commodo aptent scelerisque cursus. Hac vel himenaeos hendrerit eu pellentesque. Lorem natoque praesent dictum porta, aliquam bibendum laoreet class litora? Class nullam maecenas aliquet.
    Ligula, et enim vel rutrum luctus lorem orci fringilla in erat? Bibendum magnis nec volutpat non netus dignissim. Tempus tempor penatibus nulla egestas semper scelerisque cubilia. Nulla adipiscing per porta consequat et imperdiet posuere magna fringilla
    rhoncus conubia. Sapien proin euismod.
  </p>
  <p>Tempus luctus tempor donec pretium lectus leo facilisis leo, inceptos nostra lorem vel. Orci parturient urna etiam pharetra sit lacus volutpat id sed lacinia. Scelerisque ultrices nisi risus aenean tincidunt, amet arcu tempus id curabitur purus fringilla.
    Eros iaculis vitae vitae rutrum ultricies dolor sociis ante ante ut. Ut nibh primis himenaeos egestas dictumst congue scelerisque!
  </p>
  <p>Blandit sociis quisque ultrices montes tortor. Penatibus risus primis, senectus nam nostra. Egestas, nulla vitae penatibus cursus sed. Luctus, eget dignissim porttitor et curae; accumsan. Accumsan blandit ligula sollicitudin. Ligula mattis ad turpis
    arcu mus laoreet conubia risus accumsan quis lobortis. Nisi sollicitudin penatibus lacus nam justo id commodo sagittis. Leo orci.
  </p>

  <p>Fringilla sociosqu laoreet id, dui lobortis condimentum? Facilisis non, cubilia diam. Egestas aptent ornare et felis morbi senectus molestie, egestas donec himenaeos ultrices himenaeos. Condimentum conubia nisl urna lobortis pharetra adipiscing cras
    eget pellentesque sollicitudin faucibus. Scelerisque lobortis nascetur neque ac quam dignissim fames. Magnis pharetra dignissim nullam sapien eu curabitur, ridiculus dapibus. Aptent tempus nibh eget scelerisque magna ipsum turpis. Taciti nostra morbi
    pharetra montes sagittis posuere mollis.
  </p>
  <p>Taciti tortor phasellus placerat inceptos tristique consectetur accumsan vitae potenti sodales nulla eros. Dapibus scelerisque penatibus nisl accumsan ultricies ridiculus porta. Varius tellus erat laoreet morbi tempor tristique. Sapien, sem morbi libero
    dapibus curabitur. Facilisi habitasse feugiat semper magnis risus id tellus libero semper. Vehicula turpis elit lectus interdum metus ultrices mollis consectetur cubilia.
  </p>
  <p>Senectus purus, molestie blandit sociis eu leo blandit platea commodo aptent scelerisque cursus. Hac vel himenaeos hendrerit eu pellentesque. Lorem natoque praesent dictum porta, aliquam bibendum laoreet class litora? Class nullam maecenas aliquet.
    Ligula, et enim vel rutrum luctus lorem orci fringilla in erat? Bibendum magnis nec volutpat non netus dignissim. Tempus tempor penatibus nulla egestas semper scelerisque cubilia. Nulla adipiscing per porta consequat et imperdiet posuere magna fringilla
    rhoncus conubia. Sapien proin euismod.
  </p>

  <p>Tempus luctus tempor donec pretium lectus leo facilisis leo, inceptos nostra lorem vel. Orci parturient urna etiam pharetra sit lacus volutpat id sed lacinia. Scelerisque ultrices nisi risus aenean tincidunt, amet arcu tempus id curabitur purus fringilla.
    Eros iaculis vitae vitae rutrum ultricies dolor sociis ante ante ut. Ut nibh primis himenaeos egestas dictumst congue scelerisque!
  </p>
  <p>Blandit sociis quisque ultrices montes tortor. Penatibus risus primis, senectus nam nostra. Egestas, nulla vitae penatibus cursus sed. Luctus, eget dignissim porttitor et curae; accumsan. Accumsan blandit ligula sollicitudin. Ligula mattis ad turpis
    arcu mus laoreet conubia risus accumsan quis lobortis. Nisi sollicitudin penatibus lacus nam justo id commodo sagittis. Leo orci.
  </p>
  <p>Fringilla sociosqu laoreet id, dui lobortis condimentum? Facilisis non, cubilia diam. Egestas aptent ornare et felis morbi senectus molestie, egestas donec himenaeos ultrices himenaeos. Condimentum conubia nisl urna lobortis pharetra adipiscing cras
    eget pellentesque sollicitudin faucibus. Scelerisque lobortis nascetur neque ac quam dignissim fames. Magnis pharetra dignissim nullam sapien eu curabitur, ridiculus dapibus. Aptent tempus nibh eget scelerisque magna ipsum turpis. Taciti nostra morbi
    pharetra montes sagittis posuere mollis.
  </p>
  <p>Taciti tortor phasellus placerat inceptos tristique consectetur accumsan vitae potenti sodales nulla eros. Dapibus scelerisque penatibus nisl accumsan ultricies ridiculus porta. Varius tellus erat laoreet morbi tempor tristique. Sapien, sem morbi libero
    dapibus curabitur. Facilisi habitasse feugiat semper magnis risus id tellus libero semper. Vehicula turpis elit lectus interdum metus ultrices mollis consectetur cubilia.
  </p>
</div>  

Комментарии:

1. Спасибо за ваше время. С фиксированной позицией я сделал то же самое, что и у вас, это была моя лучшая попытка. Но, как у вас, это глючит в полноэкранном режиме. Блоки прилипают к верхней части контейнера, потому что он находится в середине экрана. :/

2. @crg вы имеете в виду, что из-за положения: исправлено, блок не сохранил свою исходную верхнюю позицию после прокрутки назад до той же координаты блока. Вот почему я установил некоторые ограничения в УСЛОВИИ IF на основе значения window.scrollY, чтобы положение элемента менялось в момент начала следующего абзаца или окончания первого блока страницы.

3. Да, я записал сбой imgur.com/a/nfpS1NJ . У меня была такая же проблема в моем проекте. Я с нетерпением жду гибкого решения: / Или, может быть, я мог бы сделать несколько хаков с родительским контейнером. Я попробую, и если это не сработает, я использую решение @diedu в комментарии к сообщению.

4. @crg Пришлите мне свой код, чтобы я мог исправить проблему

5. @crg я попробовал свой код в firefox и Chrome, и он работает нормально, и в вашем видео прокрутка начинается с нажатия элемента вверх, чтобы решить эту проблему, вам нужно проверить значение scrollY если вы хотите, чтобы эффект горизонтальной прокрутки начинался и заканчивался, проверьте его с помощью console.log(window.scrollY) в inspect и поместите его в ограничения УСЛОВИЯ IF вместо моего

Ответ №2:

     $(window).scroll(function() {
        var sectionHeight = $(window).height();
        var sectionWidth = $(window).width();
        var section3Width = sectionWidth * 3;
        var totalHeight = sectionHeight * 2
        var totalSection3Width = section3Width * 2
        if ($(document).scrollTop() > totalHeight) {
            //alert("1");
            window.scrollBy(sectionWidth, 0);
            $("body").css("overflow-y", "hidden", "overflow-x", "scroll");
         }
           
    });  
 .section {
display: block;
width: 100%;
height: 100vh;
}
.section1 {
background: red;
}
.section2 {
background: yellow;
}
.section3 {
display: block;
overflow-x: scroll;
overflow-y: hidden;
}
.scroll-y {width: calc(100vw * 3);display: flex;}


.secitem {
display: inline-block;
height: 100vh;
width: 100vw;
}
.secitem1{
background: green;}
.secitem2 {
background: skyblue;
}
.secitem3 {
background: blue;
}  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="section section1"></div>
<div class="section section2"></div>
<div class="section section3">
<div class="scroll-y">
<div class="secitem secitem1"></div>
<div class="secitem secitem2"></div>
<div class="secitem secitem3"></div>
</div>
</div>  

Ответ №3:

другая версия:

 $(window).scroll(function() {
        var sectionHeight = $(window).height();
        var sectionWidth = $(window).width();
        var section3Width = sectionWidth * 3;
        var totalHeight = sectionHeight * 2
        var totalSection3Width = section3Width * 2
        if ($(document).scrollTop() > totalHeight) {
            //alert("1");
          if(window.scrollBy(0, 0)){
            window.scrollBy(sectionWidth, 0);
            $("body").css("overflow-y", "hidden", "overflow-x", "scroll");
          } 
            
         }
           
    });  
 .section {
display: block;
width: 100%;
height: 100vh;
}
.section1 {
background: red;
}
.section2 {
background: yellow;
}
.section3 {
display: block;
overflow-x: scroll;
overflow-y: hidden;
}
.scroll-y {width: calc(100vw * 3);display: flex;}


.secitem {
display: inline-block;
height: 100vh;
width: 100vw;
}
.secitem1{
background: green;}
.secitem2 {
background: skyblue;
}
.secitem3 {
background: blue;
}  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="section section1"></div>
<div class="section section2"></div>
<div class="section section3">
<div class="scroll-y">
<div class="secitem secitem1"></div>
<div class="secitem secitem2"></div>
<div class="secitem secitem3"></div>
  </div>
  
</div>  

Ответ №4:

Чтобы заставить его работать по всему навигатору, я, наконец, сделал это, используя pageYOffset and getBoundingClientRect и другие функции, чтобы определить, где именно находится мой ряд проектов, в X / Y моего окна.

Смотрите полный результат здесь cargouet.com

 export default class ProjectsCards extends Component {
    constructor() {
        super();
        this.handleScroll = this.handleScroll.bind(this);
        this.heightIsSet = false
    }

    componentDidMount() {
        if (window.matchMedia("(max-width: 991px)").matches) return
        window.addEventListener('scroll', this.handleScroll, true)
        setTimeout(() => {
            this.offsetTop = window.pageYOffset   document.querySelector(".projectsContainer").getBoundingClientRect().top;
        }, 2000)
    }

    handleScroll() {
        const rowProjects = document.querySelector(".row.projects"),
            projectsContainer = document.querySelector(".projectsContainer"),
            wrapper = document.querySelector(".projectsWrapper"),
            projectsCard = document.querySelectorAll(".row.projects .pcard"),
            scrolledY = window.scrollY,
            lastCardFromRightSideOfTheScreen = projectsCard[projectsCard.length - 1].getBoundingClientRect().right   100;
            rowProjects.style.willChange = 'transform';

        if ((scrolledY > this.offsetTop amp;amp; lastCardFromRightSideOfTheScreen > rowProjects.offsetWidth) ||
            (projectsContainer.getBoundingClientRect().y > 0 amp;amp; lastCardFromRightSideOfTheScreen <= rowProjects.offsetWidth)) {
            projectsContainer.classList.remove("absolute")
            projectsContainer.classList.add("sticky")
            // Get wrapper height
            if(!this.heightIsSet) this.childConainterFromParent = (this.offsetTop - wrapper.getBoundingClientRect().top) - (this.offsetTop - projectsContainer.getBoundingClientRect().top)
            // Set X scroll speed 
            rowProjects.style.transform = "translateX("   -(scrolledY - this.offsetTop) * 0.55   "px)"
        } else if (lastCardFromRightSideOfTheScreen <= rowProjects.offsetWidth) {
            this.heightIsSet = true
            // Set wrapper height
            wrapper.style.height = window.innerHeight   this.childConainterFromParent   'px'
            projectsContainer.classList.remove("sticky")
            projectsContainer.classList.add("absolute")
        } else {
            if(projectsContainer.classList.contains("absolute") || projectsContainer.classList.contains("sticky")) {
                rowProjects.style.transform = "translateX(0)"
                projectsContainer.classList.remove("sticky")
                projectsContainer.classList.remove("absolute")
            }
        }
    }

    render() {
        return (
            <section id="project" className="d-flex align-items-center">
                <div className="projectsWrapper">
                    <div className="projectsContainer">
                        <div className="row projects">
                            <Project  />
                            <Project  />
                            <Project  />
                            <Project  />
                            <Project  />
                        </div>
                    </div>
                </div>
            </section>
        );
    }
}