0

window.scrollTo() を呼び出してページがレンダリングされたら、ページを特定の要素までスクロールしたいという問題があります。しかし、うまくいきません。制限はありますか?

var step = Math.round(distance / 25); // distance is Stop-start
  var leapY = stopY > startY ? startY + step : startY - step;
    var timer = 0;
    if (stopY > startY) {
        for (var i = startY; i < stopY; i += step) {
            setTimeout(window.scrollTo(0,leapY), timer * speed);
            leapY += step;
            if (leapY > stopY) 
                leapY = stopY;
            timer++;
        }            
    }
4

1 に答える 1

3

この行:

setTimeout(window.scrollTo(0,leapY), timer * speed);

window.scrollTo は、すぐに呼び出してその戻り値を に渡します。setTimeoutちょうどすぐに呼び出しfoo(bar())てその戻り値を に渡します。bar foo

関数を渡す必要があります。

setTimeout(function() { window.scrollTo(0,leapY); }, timer * speed);

しかし、それだけでは十分ではありません。なぜなら、関数は定義されたときではなく、実行leapYされたときの値をそのまま見るため、それらはすべて の最後の値を使用してしまうからです。したがって、ビルダー関数が必要です。leapY

setTimeout(buildScroller(leapY), timer * speed);

function buildScroller(y) {
    return function() { window.scrollTo(0,y); };
}

ループでは、引数leapYとして渡すビルダーを呼び出し、(ではなく) 引数を閉じる関数を返します。その引数は変更されないため、それが構築する関数は正しい値を使用します。yleapY


実例| ライブソース

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Scrolling On Load In Loop</title>
  <style>
    div {
      height: 200px;
    }
  </style>
</head>
<body>
  <div>Scrolls to each of the first four followingdivs at intervals of one second</div>
  <div>0x100</div>
  <div>0x200</div>
  <div>0x300</div>
  <div>0x400</div>
  <div>0x500</div>
  <div>0x600</div>
  <div>0x700</div>
  <div>0x800</div>
  <div>0x900</div>
  <div>0x1000</div>
  <div>0x1100</div>
  <div>0x1200</div>
  <div>0x1300</div>
  <div>0x1400</div>
  <script>
    (function() {
      var leapY;

      for (leapY = 1; leapY <= 4; ++leapY) {
        setTimeout(buildScroller(leapY * 200), leapY * 1000);
      }

      function buildScroller(y) {
          return function() { window.scrollTo(0,y); };
      }
    })();
  </script>
</body>
</html>
于 2013-07-04T07:18:28.613 に答える