【问题标题】:How can I combine multiple scroll event listeners into one?如何将多个滚动事件侦听器合并为一个?
【发布时间】:2020-05-26 12:39:13
【问题描述】:

我有以下功能,可以在图像进入视口后缩小图像。现在它附加了与元素一样多的事件侦听器。出于性能原因,我想将它们组合成一个事件侦听器,用于所有元素,但我不知道如何。这是我的代码:

HTML

<div class="image-wrapper"> 
    <div class="image-container elem-1">
        <div class="zoom-images">
            <img class="zoom" src="test" alt="test">
        </div>
    </div>
    <div class="image-container elem-2">
        <div class="zoom-images">
            <img class="zoom" src="test" alt="test">
        </div>
    </div>
    <div class="image-container elem-3">
        <div class="zoom-images">
            <img class="zoom" src="test" alt="test">
        </div>
    </div>
</div>

JAVASCRIPT

$('.zoom').each(function() {
    var el = $(this);
    var inViewport = false;
    var isZooming = false;
    originY = 0;
    window.addEventListener('scroll', throttle(zoomImage, 250), {passive: true});
    function zoomImage() {
        originY = $(window).scrollTop();
        if (el.isInViewport()) {
            if (!inViewport) {
                inViewport = true; 
            }
        } else {
            if (inViewport) {
                inViewport = false;
            }
        }   
        if (inViewport) {
            if (!isZooming) {
                window.requestAnimationFrame(function () {
                    el.addClass('is-zooming');
                });
                isZooming = true;
            }
        } else {
            if (isZooming) {
                window.requestAnimationFrame(function () {
                    el.removeClass('is-zooming');
                });
                isZooming = false;
            }
        }
    };
    $.fn.isInViewport = function() {
        var elementTop = $(this).offset().top;
        var elementBottom = elementTop + $(this).outerHeight();
        var viewportTop = $(window).scrollTop();
        var viewportBottom = viewportTop + $(window).height();
        return elementBottom > viewportTop && elementTop < viewportBottom;
    };
});

任何帮助将不胜感激!非常感谢!

【问题讨论】:

  • grouping event lestener 假设它们都具有相同的父级,并且您的代码不会显示它们是否为一个父级。 stackoverflow.com/help/how-to-ask
  • 很抱歉,我现在添加了 HTML 以便更好地了解情况。谢谢!
  • 您可以轻松地将$.fn.isInViewport 移出each。但是throttle 是在哪里定义的?问题是el 的关闭。
  • 我正在使用 lodash 油门功能。我认为这与问题无关,所以我没有在这里发布。
  • 您可能正在寻找Intersection Observer API。根本不需要注册滚动事件:-)

标签: javascript performance scroll event-listener


【解决方案1】:

将侦听器附加到容器感兴趣的事物并且事件将“冒泡”到它们。 (事件调用会告诉你哪个对象是目标。)

【讨论】:

  • 您能否提供一个简短的例子来说明您的意思?我不确定代码会是什么样子。谢谢!
【解决方案2】:

我找到了解决方案。对于任何有兴趣的人,我是这样解决的:

window.addEventListener('scroll', throttle(check_if_in_view, 220), {
    capture: true,
    passive: true
});
var $animation_elements = $('.zoom-images');
var $window = $(window);
function check_if_in_view() {
    var window_height = $window.height();
    var window_top_position = $window.scrollTop();
    var window_bottom_position = (window_top_position + window_height);
    $.each($animation_elements, function() {
        var $element = $(this);
        var $zoom = $(this).children('img.zoom');
        var element_height = $element.outerHeight();
        var element_top_position = $element.offset().top;
        var element_bottom_position = (element_top_position + element_height);
        if ((element_bottom_position >= window_top_position) &&
            (element_top_position <= window_bottom_position)) {
            requestAnimationFrame( function() {
                $zoom.addClass('is-zooming');
            });
        } else {
            requestAnimationFrame( function() {
                $zoom.removeClass('is-zooming');
            });
        }
    });
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-01
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多