简体   繁体   English

动态设置滚动坐标并从这些坐标更改具有200px滚动公差的DOM元素

[英]Dynamically set scroll coordinates & change DOM element with 200px scroll tolerance from these coordinates

I've got a single page site with two div modules that expand when clicked. 我有一个页面网站,其中包含两个div模块,这些模块在单击时会扩展。

The first is at the top, in the Hero section and with the current code works as desired. 第一个位于“英雄”部分的顶部,并且当前代码可根据需要工作。 The second is much further down the page in another section. 第二个部分在另一部分的页面下方。 Currently this second module closes as soon as the scroll takes place. 当前,第二个模块在滚动发生后立即关闭。

What I need to do is get the documents scroll coordinates when the div is clicked. 我需要做的是单击div时获取文档滚动坐标。 Then once the user scrolls 200px up or down the div closes back up. 然后,一旦用户向上或向下滚动200像素, div就会重新关闭。 Regardless of where it (the div ) is on the site. 不管它在站点上什么位置div

All the questions I found here and elsewhere only refer to setting the scroll tolerance relative to the window position on page load. 我在这里和其他地方找到的所有问题仅涉及设置页面加载时相对于窗口位置的滚动公差。 But for me that's no goon. 但是对我而言,这不是成功。 This site is responsive, and as it changes the initial positions of the div 's will / can be unknown. 该站点具有响应能力,并且随着它的更改, div的初始位置将会/可能是未知的。 I need someway of dynamically storing the viewports scroll position when the div 's are clicked and assigning the 200px tolerance then. 我需要某种方式来在单击div时动态存储视口滚动位置,然后分配200px的公差。

I hope that makes sense. 我希望这是有道理的。 I've been at this for like 12+hrs now. 我已经在这里待了12个多小时了。 SOS :) SOS :)

Here's the Fiddle 这是小提琴

If you don't want to go over to Fiddle , Here's the requisite code 如果您不想转到Fiddle这里是必需的代码

HTML: HTML:

<body>
  <section id="hero">
    <div>
      <div class="module-cta hero-cta">
        <a class="module-cta__button"><!-- Fallback location -->
          <span class="module-cta__text">PRESS ME</span>
        </a>
        <div class="module-cta__open">
          <div class="module-cta__open-inner">
            <div class="hero-cta__contact-points">
              <div class="phone">
                <div class="hero-cta_contact_logo">
                  <span><!-- phone.svg" --></span>
                </div><!-- .service-logo -->
                <div class="contact_trigger">
                  <a>Scroll down to 200px to see</a>
                </div><!-- .contact_trigger -->
              </div><!-- .phone -->
              <div class="email">
                <div class="hero-cta_contact_logo">
                  <span><!-- email.svg --></span>
                </div><!-- .service-logo -->
                <div class="contact_trigger">
                  <a>this div fold back up</a>
                </div><!-- .contact_trigger -->
              </div><!-- .email -->
            </div><!-- .hero-cta__contact-points -->
            <button class="module-cta__close module-cta__cancel"><i class="icon"><span></span></i></button>
          </div><!-- .hero-cta__open-inner -->
        </div><!-- .hero-cta__open -->
      </div><!-- .hero-cta -->
    </div>
  </section>
  <section class="spacer"></section>
  <section id="service_area">
    <div class="area_input">
      <div class="module-cta area-cta wow fadeInUp" id="form_module">
        <a class="module-cta__button area-cta__button">
          <span class="module-cta__text area-cta__text">NOW PRESS ME</span>
        </a>
        <div class="module-cta__open area-cta__open">
          <div class="module-cta__open-inner area-cta__open-inner">
            <div class="area-cta__search">
              <form class="postcode_form" id="postcode_form" name="postcode_form" action="#">
                <input type="number" id="your_postcode" class="your_postcode" name="postcode" placeholder="3???">
                <button type="button" class="area-btn"><span></span></button>
                <a class="call-now">##########</a>
              </form>
            </div><!-- .area-cta__search -->
            <button class="module-cta__close module-cta__cancel"><i class="icon"><span></span></i></button>
          </div><!-- .area-cta__open-inner -->
        </div><!-- .area-cta__open -->
      </div><!-- .area-cta -->
    </div><!-- .area_input -->
  </section>
  <section class="spacer"></section>
</body>

Script: I'm sure a lot of this can be cleaned up and shrunk, but for now I'm just trying to get it all going. 脚本: 我敢肯定,其中很多可以清理和缩小,但现在我只是想让一切顺利。

// opens & closes modules by clicking module name
$('.module-cta__button').on('click', function(){
  if($(this).parent().hasClass('hero-cta')){
    $(this).parent().toggleClass('module-cta--active');
  } else {
    if($(this).parent().hasClass('area-cta')){
      $(this).parent().toggleClass('module-cta--active');
    }
  }
});

// closes modules with .module-cta__close btn
$('.module-cta__close').on('click', function(){
  if($(this).closest('div .module-cta').hasClass('module-cta--active')){
    $(this).closest('div .module-cta').removeClass('module-cta--active');
  }
});

// closes modules on scroll.
// * works but doesn't apply scroll tolerance of 200px for #area
$(window).scroll(function(){
  var currentPos = $(window).scrollTop();
  var module = $('div .module-cta');
  if(module.hasClass('module-cta--active') && module.position().top <= currentPos+200){
    $('div .module-cta--active').removeClass('module-cta--active');
  }
});


// closes modules when escape key is pressed
$(window).keydown(function(escape){
  var key = escape.which;
  if(key == 27){
    $('div .module-cta--active').removeClass('module-cta--active');
  }
});

see Fiddle for css 看到小提琴css

  • Thanks for any help or useful suggestions in advanced. 感谢您提供的任何帮助或有用的建议。

So I've put together a script that will potentially help you. 因此,我整理了一个可能会对您有所帮助的脚本。

I've done some basic testing on it, but if you come across any problems make a comment. 我已经对其进行了一些基本测试,但是如果您遇到任何问题,请发表评论。

// Generate offsets and return them as an object
function generateOffsets($element, tolerance)
{
  var offsets = $element.offset(),
      offsetTop = offsets.top;

  return {
    scrollPos: offsetTop,
    toleranceTop: offsetTop - tolerance,
    toleranceBottom: offsetTop + tolerance
  };
}

// Run a callback when the user leaves the scroll tolerance of a set of elements
function closeOnScroll($elements, tolerance, callback)
{
  $elements.each(function() {
    var $element = $(this),
        offsets = generateOffsets($element, tolerance),
        resizeEvent;

    // On resize, regenerate the offsets so they stay up to date
    $(window).on('resize', function(e) {
      resizeEvent = e;
      offsets = generateOffsets($element, tolerance);
    });

    // On scroll check if we've left the tolerance area, if so run the event and unbind
    $(window).on('scroll', function(e) {
      var windowPos = $(this).scrollTop();

      if (windowPos < offsets.toleranceTop || windowPos > offsets.toleranceBottom) {
        callback($element);
        $(this).unbind(e);
        $(this).unbind(resizeEvent);
      }
    }); 
  });
}

// Example: Apply the event to a set of elements
$('.btn').click(function() {
  closeOnScroll($('div .module-cta'), 200, function($element) {
    $element.removeClass('module-cta--active');
  });
});

The thing to remember with thie script is that it needs to be applied EVERY time the user clicks your button. 该脚本要记住的一点是,每当用户单击您的按钮时,都需要应用该脚本。 You may say, WHY WOULD YOU DO THAT - but it actually has some serious performance implications. 您可能会说, 为什么要这么做-但实际上会对性能产生严重影响。

The events rely on both scroll and resize, both of which are very slow, especially if not debounced like in this script. 这些事件都依赖于滚动和调整大小,这两者都很慢,特别是如果未像本脚本中那样进行反跳的话。 However, what I do in the script is unbind the events once it has occured. 但是,我在脚本中执行的操作是在事件发生后取消绑定事件。 Otherwise, the resize and scroll would keep happening for each and every one of your buttons until the end of time. 否则,调整和滚动将一直持续到每个按钮,直到时间结束。 By 'unbinding' the event, you ensure long running performance of your page. 通过“解除绑定”事件,可以确保页面的长期运行性能。

Wouldn't want to ruin those pretty animations would we? 我们不想破坏那些漂亮的动画吗?

I've put together a much smaller and simpler demonstration, just to show you what variables you need to accomplish this. 我整理了一个更小,更简单的演示,只是为了向您展示完成此操作所需的变量。 Essentially, when a div is clicked, capture the current document scroll position using $(document).scrollTop() . 本质上,单击div时,使用$(document).scrollTop()捕获当前文档滚动位置。 Also store a refference to the current div that has been clicked. 还存储对已单击的当前div的引用。

When scrolling, check the difference between the current scroll and the new scroll, and using your clicked div reference, shrink the div when the difference is 200 or greater. 滚动时,检查当前滚动和新滚动之间的差异,并使用单击的div引用,当差异大于或等于200时缩小div。 JS fiddle below; JS在下面摆弄;

https://jsfiddle.net/jLqu4pas/ https://jsfiddle.net/jLqu4pas/

Code from Fiddle; 来自Fiddle的代码;

var currentScroll;
var lastClickedDiv;

$('section').click(function(){
  $(this).css({'height' : '400'})
  currentScroll = $(document).scrollTop();
  lastClickedDiv = $(this);

  console.log(currentScroll);
})

$(window).scroll(function(){
  if($(document).scrollTop() > currentScroll + 200){
    lastClickedDiv.css({'height' : 0})
  }
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM