如何在用户第一次滚动到某个元素时运行自定义函数?

时间:2014-07-16 21:45:15

标签: javascript jquery html css

问题:

我有一个花哨的循环图像轮播需要从特定的第一张幻灯片开始 - 当用户滚动到某个div时。如果用户向上/向下滚动并返回到该div,则不应重新启动。

我现在只能在用户滚动到div时启动它 - 然后当你滚动并返回它时它会被搞砸,我认为这是因为函数再次开始运行。

我想要实现的目标:

  1. 用户滚动到某个div
  2. 花式图像轮播动画功能
  3. 如果用户向上/向下滚动并返回div,则动画功能永远不会再次启动。
  4. 我的(匿名,对不起!)代码:

    http://jsfiddle.net/annablabber/h8pqW/

    HTML

    <p class="scroll_down">Scroll down...</p>
    
    <div class="animation_container">You should get an alert only once here—the first time you scroll to this div.</div>
    

    CSS

    .scroll_down {
      margin-bottom: 1000px;
    }
    
    .animation_container {
      width: 300px;
      height: 200px;
      background-color: red;
      padding: 30px;
      color: white;
      margin-bottom: 1000px;
    }
    

    的jQuery

    // The fancy function for my animations
    function doSomeComplicatedStuff() {
      alert("...and here's where the complicated animations happen!");
    }
    
    // The function to check if div.animation_container is scrolled into view
    function isScrolledIntoView(elem)
    {
      var docViewTop = $(window).scrollTop();
      var docViewBottom = docViewTop + $(window).height();
    
      var elemTop = $(elem).offset().top;
      var elemBottom = elemTop + $(elem).height();
    
    return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
    }
    
    // If div.animation_container is scrolled into view, run the fancy function
    $(window).on('scroll', function() {
      if (isScrolledIntoView('.animation_container')) {
        run_once(function() {
          doSomeComplicatedStuff();
        });
      }
    });
    
    // The function that's supposed to make sure my fancy function will only run ONCE, EVER
    function run_once( callback ) {
      var done = false;
      return function() {
        if ( !done ) {
          done = true;
          return callback.apply( this, arguments );
        }
      };
    } 
    

    由视觉设计师清楚地写的脚本道歉。如果问题在匿名代码中不够明确,请告诉我。

4 个答案:

答案 0 :(得分:3)

done变量移动到全局?

var firstScroll = false;

$(window).on('scroll', function() {
  if (isScrolledIntoView('.animation_container') && !firstScroll) {
      doSomeComplicatedStuff();
  }
});

function doSomeComplicatedStuff() {

    firstScroll = true;        

    // Your code here
}

这样,第一次isScrolledIntoView返回true时,doComplicatedStuff函数会立即翻转停止后续调用的布尔值firstScroll

答案 1 :(得分:1)

你可以有这样的东西

// The fancy function for my animations
var alreadyRun = false;
function doSomeComplicatedStuff() {
    alert("...and here's where the complicated animations happen!");
}

// The function to check if div.animation_container is scrolled into view
function isScrolledIntoView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
}

// If div.animation_container is scrolled into view, run the fancy function
$(window).on('scroll', function() {
  if (isScrolledIntoView('.animation_container') && !alreadyRun) {
      doSomeComplicatedStuff();
      alreadyRun = true;
  }
});

工作jsfiddle

答案 2 :(得分:1)

  1. 将完成的变量放入全局范围。此外,每次调用run_once()时都会一次又一次地重新定义。更好的方法是在该函数中添加第一个参数,以确定运行的是哪个动作(function run_once(identifier,callback) { if(!done[identifier]) { run function and set done[identifier] to true; }
  2. return function()
  3. 中删除run_once()
  4. 请参阅Fiddle

答案 3 :(得分:1)

以下是更新的解决方案:http://jsfiddle.net/h8pqW/2/

基本上,每次满足条件时您都在运行run_once,因此它创建了一个新的done变量。我将run_once调用移到了doSomeComplicatedStuff声明中,将其转换为只运行一次的方法。

// The fancy function for my animations
var doSomeComplicatedStuff = run_once(function () {
    alert("...and here's where the complicated animations happen!");
});

这是一个更高效的替代方案,不需要使用run_once帮助程序:http://jsfiddle.net/h8pqW/3/

在这个例子中,我只要在调用函数时解除绑定scroll事件。这将阻止页面在每次用户滚动时继续尝试运行该功能。

// If div.animation_container is scrolled into view, run the fancy function
$(window).on('scroll', function() {
  if (isScrolledIntoView('.animation_container')) {
    doSomeComplicatedStuff();
    $(window).unbind('scroll');
  }
});