Ускорение перекоса css () с помощью колеса мыши в анимации js

#javascript #css #animation #css-animations

#javascript #css #Анимация #css-анимации

Вопрос:

Вчера я просматривал Интернет и нашел этот замечательный веб-сайт:https://durimel.io/nel . Просто посмотрите, как перечислены его работы… бесконечный список, в котором работает даже перекос при прокрутке мышью.

Мне нравится эта штука! Итак, я начал думать о том, как это можно было бы сделать, и начал немного экспериментировать самостоятельно. Я хочу прояснить, что моей целью не является копирование работы Лайонела… Я просто хочу научиться и понять, как создать такую фантастическую анимацию! (И, возможно, использовать некоторые похожие концепции в будущем 😊)

Теперь к моему вопросу: если вы посмотрите на мой код, я думаю, что мой список (более или менее) движется вправо. Оно бесконечно, оно прокручивается быстрее или медленнее в зависимости от того, сколько раз используется колесо мыши. Что касается этого, все должно быть в порядке 😜

Но функция skew() ведет себя некорректно. Чего мне здесь не хватает? У него нет реального / хорошего ускорения, поскольку он не искажается меньше при одном прокручивании или больше при более длинных прокрутках. Кроме того, если вы пытаетесь последовательно прокручивать вверх и вниз, это запаздывает и сотрясается. Как я могу решить эту проблему?

Вот мой код на данный момент. И, пожалуйста, не спрашивайте меня, почему я использовал такие странные числа или вычисления… Я не знаю, я просто играл с ними 😂

 <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>TEST</title>
    <style>
        body {
            overflow: hidden;
        }

        ul {
            list-style: none;
        }

        li {
            display: inline;
            padding: 30px;
            font-size: 90pt;
            font-weight: bold;
            border: solid 1px red;

            position: absolute;
            white-space: nowrap;
            transform-origin: 50% 100%;
        }
    </style>
</head>
<body>
<ul>
    <li>bla bla</li>
    <li>adsf</li>
    <li>234 777</li>
    <li>jhgj</li>
    <li>shsh hshs</li>
    <li>looool</li>
    <li>gaga</li>
</ul>

<script>
    let a = document.getElementsByTagName('li');
    let ticking = false;
    let trans3d = 0;
    let listEnd = 0;
    let listStart = 0;

    window.onload = function () {
        let pos = 0;
        for (let i = 0; i < a.length; i  ) {
            let prev = (i > 0) ? a[i - 1].offsetWidth   20 : 0;
            pos  = prev;
            a[i].style.left = pos   "px";

            if (pos >= listEnd) {
                listEnd = pos   a[i].offsetWidth   20;
            }
            if (pos <= listStart) {
                listStart = pos;
            }
        }
    }

    function changeListPos(item, moveToEnd) {
        if (moveToEnd) {
            item.style.left = listEnd   "px";
            listEnd  = item.offsetWidth   20;
            listStart  = item.offsetWidth   20;
        } else {
            listStart -= item.offsetWidth   20;
            listEnd -= item.offsetWidth   20;
            item.style.left = listStart   "px";
        }
    }

    function scrollContent(scroll_pos) {
        let qtyScroll = 40;
        let easeOutSine = function (t, b, c, d) {
            return c * Math.sin(t / d * (Math.PI / 2))   b;
        };

        for (let i = 0; i < qtyScroll; i  ) {
            (function (x) {
                setTimeout(function () {
                    trans3d  = easeOutSine(x, ((qtyScroll - x)) / 14, 0.05, qtyScroll) * (scroll_pos / Math.abs(scroll_pos));
                    let skew = easeOutSine(x, ((qtyScroll - x)) / 6, 0.05, qtyScroll) * (scroll_pos / Math.abs(scroll_pos));
                    console.log(skew);

                    for (let j = 0; j < a.length; j  ) {
                        let prev = (j == 0) ? a[a.length - 1] : a[j - 1]
                        let curr = a[j];

                        if (scroll_pos < 0 amp;amp; curr.getBoundingClientRect().x < -(prev.getBoundingClientRect().width / 4) amp;amp; parseInt(prev.style.left) < parseInt(curr.style.left)) {
                            changeListPos(prev, true);
                        } else if (scroll_pos > 0 amp;amp; curr.getBoundingClientRect().x >= -(prev.getBoundingClientRect().width / 4) amp;amp; parseInt(prev.style.left) > parseInt(curr.style.left)) {
                            changeListPos(prev, false);
                        }

                        curr.style.transform = "skew("   skew   "deg) translate3d("   trans3d   "px, 0px, 0px)";
                    }
                }, 55 * (x / 3));
            })(i);
        }
    }

    (function (window, document) {

        let prefix = "", _addEventListener, support;

        // detect event model
        if (window.addEventListener) {
            _addEventListener = "addEventListener";
        } else {
            _addEventListener = "attachEvent";
            prefix = "on";
        }

        // detect available wheel event
        support = "onwheel" in document.createElement("div") ? "wheel" : // Modern browsers support "wheel"
            document.onmousewheel !== undefined ? "mousewheel" : // Webkit and IE support at least "mousewheel"
                "DOMMouseScroll"; // let's assume that remaining browsers are older Firefox

        window.addWheelListener = function (elem, callback, useCapture) {
            _addWheelListener(elem, support, callback, useCapture);

            // handle MozMousePixelScroll in older Firefox
            if (support == "DOMMouseScroll") {
                _addWheelListener(elem, "MozMousePixelScroll", callback, useCapture);
            }
        };

        function _addWheelListener(elem, eventName, callback, useCapture) {
            elem[_addEventListener](prefix   eventName, support == "wheel" ? callback : function (originalEvent) {
                !originalEvent amp;amp; (originalEvent = window.event);

                // create a normalized event object
                var event = {
                    // keep a ref to the original event object
                    originalEvent: originalEvent,
                    target: originalEvent.target || originalEvent.srcElement,
                    type: "wheel",
                    deltaMode: originalEvent.type == "MozMousePixelScroll" ? 0 : 1,
                    deltaX: 0,
                    deltaY: 0,
                    deltaZ: 0,
                    preventDefault: function () {
                        originalEvent.preventDefault ?
                            originalEvent.preventDefault() :
                            originalEvent.returnValue = false;
                    }
                };

                // calculate deltaY (and deltaX) according to the event
                if (support == "mousewheel") {
                    event.deltaY = -1 / 40 * originalEvent.wheelDelta;
                    // Webkit also support wheelDeltaX
                    originalEvent.wheelDeltaX amp;amp; (event.deltaX = -1 / 40 * originalEvent.wheelDeltaX);
                } else {
                    event.deltaY = originalEvent.deltaY || originalEvent.detail;
                }

                // it's time to fire the callback
                return callback(event);

            }, useCapture || false);
        }

    })(window, document);

    addWheelListener(window, function (e) {
        if (!ticking) {
            window.requestAnimationFrame(function () {
                scrollContent(e.deltaY);
                ticking = false;
            });

            ticking = true;
        }
    });
</script>
</body>
</html>
  

Ответ №1:

Если вы добавите задержку перехода на skew для li элементов, перекосом будет чувствовать себя немного более «реалистичным»

transition: skew 1.5s;

В вашем блоке стилей:

     <style>
        body {
            overflow: hidden;
        }

        ul {
            list-style: none;
        }

        li {
            display: inline;
            padding: 30px;
            font-size: 90pt;
            font-weight: bold;
            border: solid 1px red;

            position: absolute;
            white-space: nowrap;
            transform-origin: 50% 100%;
            transition: skew 1.5s;
        }
    </style>
  

Если вы хотите изменить угол перекоса, просто измените код, в котором skew переменная инициируется внутри scrollContent() функции:

 let skew = easeOutSine(x, ((qtyScroll - x)) / 6, 0.1, qtyScroll) * (scroll_pos / Math.abs(scroll_pos));
  

Вы можете, например, изменить / 6 на / 3 , чтобы получить больше skew . Если вы сделаете это, вы можете вместо этого увеличить transition: skew до 2 или 3 секунд.