Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Как узнать сколько пользователь прокрутил пикселей без прокрутки страницы (https://javascript.ru/forum/events/51685-kak-uznat-skolko-polzovatel-prokrutil-pikselejj-bez-prokrutki-stranicy.html)

Andrew K 15.11.2014 17:34

Как узнать сколько пользователь прокрутил пикселей без прокрутки страницы
 
Здравствуйте. Мне нужно реализовать следующий эффект. Когда пользователь докручивает до определенного места страницы запускается анимация. Если пользователь прокручивает дальше, то анимация проигрывается вперед, если крутит назад, то анимация проигрывается назад. Скорость анимации определяется скоростью прокрутки мыши. При этом страница не должна прокручиваться.

Чтобы реализовать такое поведение я помещаю прозрачный див с абсолютным позиционированием над блоком с анимацией. В стилях дива стоит overflow : auto. В этот див вставлен другой див заведомо большего размера, который и будет прокручиваться при прокрутке страницы. При этом сама страница будет стоять на месте. В зависимости от уже прокрученной области анимация идет вперед или назад:
<!doctype html>
<html lang="ru">
<head>
    <style type="text/css">
        .animation-div{
            height: 600px;
            background-color: #ffff00;
        }
        .orange{
            background-color: orange;
        }
        .red{
            background-color: red;
        }

        .hidden-div{
            position: absolute;
            top: 400px;
            left: 0;
            width: 100%;
            height: 600px;
            overflow: auto;
            opacity: .0;
            background-color: blue;

        }
        .hidden-div div{
            height: 1200px;
            width: 60%;
        }
    </style>

</head>
<body>
<div class="hidden-div test2">
    <div></div>
</div>

<div style="height: 400px; background-color: ghostwhite"></div>

<div class="animation-div">
    Див где будет происходить анимация. Но текст нельзя выделить.
    <a href="#">На ссылку нельзя нажать.</a>
</div>

<div style="height: 400px; background-color: ghostwhite"></div>


<script type="text/javascript">

    var hiddenDiv = document.getElementsByClassName('hidden-div')[0],
        animationDiv = document.getElementsByClassName('animation-div')[0],
        counter = 0;

    hiddenDiv.onscroll = function(){
        counter = hiddenDiv.scrollTop
        console.log(counter);

        if(counter > 0 && counter < 200) animationDiv.className = 'animation-div';
        if(counter > 200 && counter < 400) animationDiv.className = 'animation-div orange';
        if(counter > 400 && counter < 600) animationDiv.className = 'animation-div red';
    }
</script>
</body>
</html>


Проблема в том, что на элементы, которые накрывает прозрачный див, нельзя нажать или выделить. Как можно реализовать аналогичное поведение, но без использования накрывающего прозрачного дива. Или же с ним, но чтобы с элементами можно было взаимодействовать.

danik.js 15.11.2014 17:53

Событие scroll - прокрутка страницы. Прокрутка может быть вызвана не только колесиком мыши, но и выделением, кликом по колесику, клавишами клавиатуры, touch - действиями и тд и тп.


Тебе по ходу нужно другое событие - wheel - прокрутка колесика мыши (для тачпадов тоже оно вызывается, но для touch-устройств нужно слушать touch/pointer события). Притом, его можно отменить и страница не будет прокручена.


С wheel гемор. Для старых браузеров нужно юзать устаревшие события - mousewheel и DOMMouseScroll. Выдают они тоже разные значения. По сути кроссбраузерно и кроссплатформенно нельзя узнать как сильно крутанули колесико.


Для jQuery есть плагин, избавляющий от геморроя. Может есть и vanilla js плагин.

danik.js 15.11.2014 17:55

Цитата:

Сообщение от Andrew K
getElementsByClassName

Кстати не работает в IE8, хотя можно заменить на querySelector(), который работает.

Andrew K 15.11.2014 19:56

Про событие wheel забыл. Спасибо, что напомнили. Вот такой код получился:
<!doctype html>
<html lang="ru">
<head>
    <style type="text/css">
        .animation-div{
            height: 600px;
            background-color: #ffff00;
        }
        .orange{
            background-color: orange;
        }
        .red{
            background-color: red;
        }
    </style>

</head>
<body>

<div style="height: 400px; background-color: ghostwhite"></div>

<div class="animation-div">
    Див где будет происходить анимация. <a href="#">Ссылка</a>
</div>

<div style="height: 400px; background-color: ghostwhite"></div>


<script type="text/javascript">
    var totalWheel = 0,
        animationDiv = document.getElementsByClassName('animation-div')[0]

    window.onwheel = function(e){
        var delta = e.deltaY;
        totalWheel += delta // Сколько всего прокрутили

        if(totalWheel > 400 && totalWheel < 700){
            window.onscroll = function(e) {
                window.scrollTo(0, 400)
            }

            if(totalWheel > 400 && totalWheel < 500) animationDiv.className = 'animation-div';
            if(totalWheel > 500 && totalWheel < 600) animationDiv.className = 'animation-div orange';
            if(totalWheel > 600 && totalWheel < 700) animationDiv.className = 'animation-div red';

        }else{
            window.onscroll = null; // Обнуление предыдущего обработчика события onscroll
        }
    }
</script>
</body>
</html>


Почему-то событие scroll нельзя отменить. Этот код не работает:
window.onscroll = function(e) {
        e.preventDefault()
    }


Поэтому я прокручивал страницу до определенного значения:
window.onscroll = function(e) {
                window.scrollTo(0, 400)
            }

Andrew K 15.11.2014 19:57

Цитата:

Сообщение от danik.js (Сообщение 341039)
Кстати не работает в IE8, хотя можно заменить на querySelector(), который работает.

Я хочу понять общий ход написания сценария, поэтому над кроссбраузерностью пока не думал.

Andrew K 15.11.2014 20:12

Цитата:

Сообщение от danik.js (Сообщение 341038)
Может есть и vanilla js плагин.

Оценил ваш искрометный юмор.

danik.js 15.11.2014 20:20

Цитата:

Сообщение от Andrew K
Оценил ваш искрометный юмор.

Нет тут никакого юмора )
Цитата:

Сообщение от Andrew K
Почему-то событие scroll нельзя отменить. Этот код не работает:

И не должен. Событие происходит постфактум и отменить его уже нельзя.

Не понимаю чего хочешь добиться. Добавляй атрибут run в тег [ HTML ], чтоб можно было запустить:
<body></body>

Andrew K 15.11.2014 20:32

Цитата:

Сообщение от danik.js (Сообщение 341060)
Нет тут никакого юмора )
Не понимаю чего хочешь добиться. Добавляй атрибут run в тег [ HTML ], чтоб можно было запустить:
<body></body>

Что вы имели в виду? Что запустить?

Andrew K 16.11.2014 11:41

Мой предыдущий код содержал ошибки и на работал, если пользователь прокручивал страницу с помощью ползунка. Вот этот работает лучше:
<!doctype html>
<html lang="ru">
<head>
    <style type="text/css">
        .animation-div{
            height: 300px;
            background-color: #ffff00;
        }
        .orange{
            background-color: orange;
        }
        .red{
            background-color: red;
        }
    </style>
</head>
<body>

<div style="height: 300px; background-color: ghostwhite"></div>
<div class="animation-div">Див где будет происходить анимация.</div>
<div style="height: 600px; background-color: ghostwhite"></div>

<script type="text/javascript">

    var animationDiv = document.getElementsByClassName('animation-div')[0],
        count = 0;

    function wheelMove(e){
        if(document.body.scrollTop > 300 && document.body.scrollTop < 350){
            var delta = e.deltaY
            count += delta

            if(count < 1) count = 0
            if(count > 299) count = 300

            if(count > 0 && count < 300){
                e.preventDefault()
            }

            if(count > 0 && count < 100) animationDiv.className = 'animation-div';
            if(count > 100 && count < 200) animationDiv.className = 'animation-div orange';
            if(count > 200 && count < 300) animationDiv.className = 'animation-div red';
        }

    }

    animationDiv.onwheel = wheelMove;


    // Если пользователь прокручивает стараницу не мышкой, а использует ползунок, тогда в зависимости от прокрученной страницы показывается или первый кадр или последний.
    function onscrollAmimation(){
        var currentTop = document.body.scrollTop
        console.log(currentTop);

        if(currentTop < 300){
            animationDiv.className = 'animation-div';
        }else if(currentTop > 350){
            animationDiv.className = 'animation-div red';
        }
    }

    window.onscroll = onscrollAmimation

</script>
</body>
</html>

рони 16.11.2014 11:51

Цитата:

Сообщение от Andrew K
Что вы имели в виду?

[HTML run]


Часовой пояс GMT +3, время: 23:19.