2017-03-07 11 views
3

私はDIV(コンテナ要素)を持っています。DIVをビューポートよりも大きくスクロールするのを止めるには?

フェードインとフェードアウト(ユーザーがどの方向にスクロールしているかによって異なります)の要素がいくつかあります。これは問題ありません。

デモの埋め込みコードスニペットをご覧ください。

問題

デモのフェーディングブラック領域に注意してください。私はそれをフェージングしながら(ある距離をスクロールすることによって)これを一番上に保ちたいと思います。

このような要素のフェードインとフェードアウトの間、フェードインまたはフェードアウトが完了するまで、親コンテナ(DIV)が(垂直方向に)移動しないようにしたいと考えています。そして、この部分は私にとって問題を形作るものです。

アップデート2017年11月3日

私はChromeで大丈夫実行しているようだ例(スクロールアップ時に(それがdivを引き上げるために、負のmarginTopを使用してスティックにする)とのコードと正top用を更新しましたdiv(スクロールダウン)押し下げ。しかし、例えばエッジまたはFirefox(スクロールはそれが遅れ落札後scroll -eventが解雇)には非常に「安っぽい」の実行で。私は

    を試してみましたが、何

  • 私はposition: stickyを使ってみました。これはposition: relativeを最初に使用し、次にposition: fixedを使用します。
  • 私は 'position:fixed'を使ってみました。もちろん、親コンテナDIVはビューポートに固執します。しかし、その高さはビューポートの高さよりも大きいので、意図したとおりに動作しません。ユーザーが大きなコンテナの高さの50%までスクロールすると、このscrollTopは 'position:fixed'を使用して失われます。
  • 私は '位置:fixed'を 'scroll'イベントとmarginTop CSSプロパティ(および 'top' CSSプロパティ)と組み合わせて使用​​しようとしました。私はこれで奇妙な結果を得る。また、 'scroll'イベントは、ユーザーが一定量のピクセルをスクロールした後に常に実行されます。だからそれがうまくいくなら、おそらく「遅れた」経験を得るでしょう。
  • jQueryプラグインなどを検索しましたが、それらも「位置:固定」に依存しており、制限もあります。
  • 私はScrollMagicを試してみましたが、同時にGreenSockのTimelineMaxを使ってトゥイーンを実行しました。フェードインとフェードアウトのための1つのトゥイーンとmargin: 'top:position:absolute'と 'position:relative'のスクロールされた距離を補うためにmarginTop(再び)またはtopを再現する1つのトゥイーン
  • 私はちょうどmousewheelのイベントをキャプチャし、programmaticalyをスクロールしようとしました(私はスクロールしないように選択できます)。それはもちろんオプションです。しかし、私は本当にスクロールバーが好きです。プログラムによるスクロールを行うときには、例えば、 'ダブルタップ'ジェスチャー。
  • 私はこれらの事柄の多くのバリエーションをたくさん試しました。

コード(埋め込みスニペット) - 更新2017年11月3日

コードクローム(でないブラウザで安っぽい作品!)

var $window = $(window); 
 
// Element which needs to fade in and out. 
 
var $fadingblack = $("#fadingblack"); 
 
// Parent element of fading element. 
 
var $scrollcontainer = $("#scrollcontainer"); 
 

 
// Last scrollTop-value. 
 
var lastScrollTop = $window.scrollTop(); 
 
var lockForFade = false; 
 

 
$window.on('scroll', 
 
    // Function which is to be called after user scrolls. 
 
    function() { 
 
    // Current scrollTop value. 
 
    var currentScrollTop = $window.scrollTop(); 
 
    // Y-coordinate of element which needs to fade. 
 
    var scrollTopStart = $fadingblack.position().top; 
 
    // Y-coordinate of end of element which needs to fade. 
 
    var scrollTopEndDown = scrollTopStart + $fadingblack.height(); 
 
    var scrollTopEndUp = scrollTopStart - $fadingblack.height(); 
 
    // Has element which needs to fade scrolled into view. 
 

 
    // Does the fading itself. 
 
    function doFade($el, $parent, lastScrollTop, currentScrollTop, scrollTopStart, scrollTopEnd) { 
 
     // Curent opacity for fade; determined by scroll position. 
 
     //var currentOpacity = (currentScrollTop - scrollTopStart)/(scrollTopEnd - scrollTopStart); 
 
     var currentOpacity; 
 

 

 
     // Temporary variables for scrollTop. 
 
     var theTop; 
 
     var fadeCompleted; 
 

 
     function undoPushAndScroll() { 
 
     // Save the amount of pixels the parent element has been pushed down. 
 
     var savedTop = $parent.position().top; 
 
     // Then reset this 'push amount'. 
 
     $parent.css("top", 0); 
 
     // And scroll the pushed down amount of pixels back upwards. 
 
     $window.scrollTop(currentScrollTop - savedTop); 
 
     currentScrollTop -= savedTop; 
 
     } 
 

 
     function undoPullAndScroll() { 
 
     // Save the amount of pixels the parent element has been pulled up. 
 
     var savedTop = parseFloat($parent.css('marginTop')); 
 
     // Then reset this 'pull amount'. 
 
     $parent.css("marginTop", 0); 
 
     // And scroll the pulled up amount of pixels back downwards. 
 
     $window.scrollTop(currentScrollTop - savedTop); 
 
     currentScrollTop -= savedTop; 
 
     } 
 

 
     function undoPullAndDoPush() { 
 
     var savedMarginTop = parseFloat($parent.css('marginTop')); 
 

 
     $parent.css('marginTop', 0); 
 
     $window.scrollTop(currentScrollTop - savedMarginTop); 
 
     currentScrollTop -= savedMarginTop; 
 

 
     // Determine difference between start of fade (Y-value) and current scrollTop (Y-value). 
 
     var theTop = Math.abs(scrollTopStart - currentScrollTop); // + savedMarginTop; 
 
     // Push the parent element down that same difference. 
 
     $parent.css("top", theTop); 
 
     } 
 

 
     function undoPushAndDoPull() { 
 
     // Save the amount of pixels the parent element has been pushed down. 
 
     var savedTop = $parent.position().top; 
 

 
     $parent.css('top', 0); 
 
     $window.scrollTop(currentScrollTop - savedTop); 
 
     currentScrollTop -= savedTop; 
 
     // User has scrolled up. 
 
     // Determine difference between start of fade (Y-value) and current scrollTop (Y-value). 
 
     var theTop = Math.abs(scrollTopStart - currentScrollTop); 
 
     // Pull the parent element up that same difference. 
 
     $parent.css("marginTop", -theTop); 
 
     } 
 

 

 

 
     if (lastScrollTop < currentScrollTop) { 
 
     // User has scrolled down. 
 
     undoPullAndDoPush(); 
 

 
     //currentOpacity = Math.abs(currentScrollTop - scrollTopStart)/$el.height(); 
 

 
     fadePercent = Math.abs(currentScrollTop + $parent.position().top - scrollTopStart)/$el.height(); 
 
     currentOpacity = fadePercent; 
 

 
     // Fade to current opacity immediately. 
 
     $el.fadeTo(0, currentOpacity); 
 

 

 
     // Determine if fade has completed (must scroll at least the height of the fading element). 
 
     fadeCompleted = ($parent.position().top >= $el.height()); 
 
     if (fadeCompleted) { 
 
      // Then immediately set opacity to 1. 
 
      $el.fadeTo(0, 1); 
 
      // Fade has completed. 
 
      undoPushAndScroll(); 
 
      lockForFade = false; 
 
     } 
 
     } else if (lastScrollTop > currentScrollTop) { 
 
     // User has scrolled up. 
 
     undoPushAndDoPull(); 
 

 

 
     fadePercent = Math.abs(currentScrollTop + parseFloat($parent.css('marginTop')) - scrollTopStart)/$el.height(); 
 
     currentOpacity = 1 - fadePercent; 
 
     // Fade to current opacity immediately. 
 
     $el.fadeTo(0, currentOpacity); 
 

 
     // Determine if fade has completed (must scroll at least the height of the fading element). 
 
     fadeCompleted = (-parseFloat($parent.css('marginTop')) >= $el.height()); 
 
     if (fadeCompleted) { 
 
      // Then immediately set opacity to 0. 
 
      $el.fadeTo(0, 0); 
 
      // Fade has completed. 
 
      undoPullAndScroll(); 
 
      lockForFade = false; 
 
     } 
 
     } 
 
    } 
 

 
    if (lastScrollTop < currentScrollTop) { 
 
     // Scrolling down in fade area. 
 
     if (!lockForFade && currentScrollTop >= scrollTopStart && lastScrollTop < scrollTopStart) { 
 
     if (parseFloat($fadingblack.css('opacity')) < 1) { 
 
      lockForFade = true; 
 
     } 
 
     } 
 
     if (lockForFade) { 
 
     doFade(
 
      $fadingblack, 
 
      $scrollcontainer, 
 
      lastScrollTop, 
 
      currentScrollTop, 
 
      scrollTopStart, 
 
      scrollTopEndDown); 
 
     } 
 
    } else if (lastScrollTop > currentScrollTop) { 
 
     // Scrolling up in fade area. 
 
     if (!lockForFade && currentScrollTop <= scrollTopStart && lastScrollTop > scrollTopStart) { 
 
     if (parseFloat($fadingblack.css('opacity')) > 0) { 
 
      lockForFade = true; 
 
     } 
 
     } 
 
     if (lockForFade) { 
 
     console.log('dofade up'); 
 
     doFade(
 
      $fadingblack, 
 
      $scrollcontainer, 
 
      lastScrollTop, 
 
      currentScrollTop, 
 
      scrollTopStart, 
 
      scrollTopEndUp); 
 
     } 
 
    } 
 

 

 
    // Save last scrollTop-value for next scroll-event-call. 
 
    lastScrollTop = $window.scrollTop(); 
 
    });
body { 
 
    background-color: whitesmoke; 
 
} 
 

 
#scrollcontainer { 
 
    position: absolute; 
 
    left: 0px; 
 
    top: 0px; 
 
} 
 

 
.red, 
 
.blue, 
 
.black { 
 
    position: relative; 
 
    width: 900px; 
 
} 
 

 
.red, 
 
.blue { 
 
    height: 300px; 
 
} 
 

 
.black { 
 
    height: 600px; 
 
} 
 

 
.red { 
 
    background-color: red; 
 
} 
 

 
.blue { 
 
    background-color: blue; 
 
} 
 

 
.black { 
 
    background-color: black; 
 
} 
 

 
#fadingblack { 
 
    opacity: 0; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="scrollcontainer"> 
 
    <div class="red">BEGIN</div> 
 
    <div class="blue">Fading black area is ahead...</div> 
 
    <div id="fadingblack" class="black">&nbsp;</div> 
 
    <div class="blue">&nbsp;</div> 
 
    <div class="red">&nbsp;</div> 
 
    <div class="blue">END</div> 
 
</div>

+0

だから、ビューに他のdivをもたらし続け、それは視野にいたら、その後、フェードをスクロール「fadingblack」のdivが固執したい、それはフェージング行うの後は? – Slime

+0

@AmericanSlimeはい、それはまさに私が達成したいものです。 – Wieger

答えて

0

への道は本当におそらくありません - 最初で相対的な位置を使用していますかさえposition: sticky( - 道のより自然な種類で - position: fixedを使用していますdivを防ぐには後で固定位置を固定している場合)、ある時点でスクロールしたくない場合は、ビューポートよりもサイズが大きくなります。

でも、私の質問の目標は(div要素の一部を消すためにスクロールしないでください)私はいくつかのコード行で自分自身に答えることができます。要約すると、divmarginTopを使用して、固定配置を使用するdivの子要素をdivまでプルアップします。

私はこのコードに関連する少なくとも1つの他の質問があるかもしれませんが、スクロールの防止には関係ありません。しかし、それは新しい質問として私が求めることができる他の質問です。

私は今のところ自分の答えを受け入れます。誰かがこの質問に関するより良い、あるいはより自然なアイデアを持っているなら、私は何とか疑問に思っています。私はその答えに喜んで受け入れます。

var $window = $(window); 
 
var $document = $(document); 
 
// Element which needs to fade in and out. 
 
var $fadingblack = $("#fadingblack"); 
 
var $scrolldistract = $("#scrolldistract"); 
 
var $scrollsviascrolldistract = $("#scrollsviascrolldistract"); 
 
// Pulls up the child divs of #scrollsviascrolldistract, under it. 
 
var $puller = $("#puller"); 
 

 

 
// Start of fading area (Y-value). 
 
var scrollTopStart = $fadingblack.position().top; 
 
// And of course the Y-value of the end of the fading area. 
 
var scrollTopEnd = scrollTopStart + $fadingblack.height(); 
 

 
// Maximum scrollTop-value (when scrollbar is at 100%). 
 
var lastScrollTop = $document.height() - $window.height(); 
 

 
// Amount of scrolled pixels (vertically) including amount scrolled while 
 
// the fading element is fading. 
 
var scrollAmountWithFadeAmount = $document.height + $fadingblack.height(); 
 
// Setting height does not quite work for an empty div, 
 
// so we are using some padding. 
 
$scrolldistract.css("paddingTop", scrollAmountWithFadeAmount); 
 
// Percentage of which we have scrolled (1 = 100%). 
 
var currentScrollTopP; 
 
// Current scrollTop value. 
 
var realCurY; 
 

 
$(function() { 
 
    // Off you go code... 
 

 
    function doScrollOrFade() { 
 
    currentScrollTopP = Math.ceil($window.scrollTop()/lastScrollTop * 100)/100; 
 
    realCurY = currentScrollTopP * lastScrollTop; 
 

 
    if (realCurY >= scrollTopStart && realCurY <= scrollTopEnd) { 
 
     // Current realCurY dictates we are in fade area. 
 
     // So scroll the fading area into view at top of browser viewport. 
 
     $puller.css("marginTop", -scrollTopStart); 
 
     // Determine opacity percentage. 
 
     var fadePercent = (realCurY - scrollTopStart)/(scrollTopEnd - scrollTopStart); 
 
     // Fade to current opacity immediately. 
 
     $fadingblack.fadeTo(0, fadePercent); 
 
    } else { 
 
     // We are outside of the fading area and in scroll-mode. 
 
     if (realCurY < scrollTopStart) { 
 
     // We are somewhere before the fading area, so set opacity to 0. 
 
     $fadingblack.fadeTo(0, 0); 
 
     } else { 
 
     // We are somewhere after the fading area, so set opacity to 1. 
 
     $fadingblack.fadeTo(0, 1); 
 
     } 
 

 
     if (realCurY > scrollTopEnd) { 
 
     // We have passed the fading area. So we have an amount 
 
     // of pixels we wasted on the opacity changes. 
 
     // Correct it here. 
 
     $puller.css("marginTop", -realCurY + $fadingblack.height()); 
 
     } else { 
 
     $puller.css("marginTop", -realCurY); 
 
     } 
 
    } 
 
    window.requestAnimationFrame(doScrollOrFade); 
 
    } 
 

 
    window.requestAnimationFrame(doScrollOrFade); 
 

 
    $window.on('resize orientationchange', function(e) { 
 
    // On resize or orientation change recalculate some stuff. 
 
    lastScrollTop = $document.height() - $window.height(); 
 
    scrollAmountWithFadeAmount = $document.height + $fadingblack.height(); 
 
    $scrolldistract.css("paddingTop", scrollAmountWithFadeAmount); 
 
    window.requestAnimationFrame(doScrollOrFade); 
 
    }); 
 
});
body { 
 
    background-color: whitesmoke; 
 
} 
 

 
#scrollsviascrolldistract { 
 
    position: fixed; 
 
    left: 0px; 
 
    top: 0px; 
 
    width: 100%; 
 
} 
 

 
#scrolldistract { 
 
    position: absolute; 
 
    left: 0px; 
 
    top: 0px; 
 
    width: 100%; 
 
    padding-top: 2100px; 
 
    height: 0px; 
 
} 
 

 
#puller { 
 
    position: relative; 
 
    margin-top: 0px; 
 
    left: 0px; 
 
    top: 0px; 
 
} 
 

 
img { 
 
    display: block; 
 
} 
 

 
.black, 
 
.red, 
 
.blue { 
 
    border: solid 1px yellow; 
 
    font-size: 32pt; 
 
    position: relative; 
 
    width: 100%; 
 
    height: 300px; 
 
} 
 

 
.red { 
 
    background-color: red; 
 
} 
 

 
.blue { 
 
    background-color: blue; 
 
} 
 

 
.black { 
 
    background-color: black; 
 
}
<!-- 
 
For mobile support use viewport meta-tag inside <head>: 
 
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=yes"> 
 
--> 
 

 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div id="scrolldistract"></div> 
 

 
<div id="scrollsviascrolldistract"> 
 
    <!-- For pulling up the red, blue and fading area --> 
 
    <div id="puller"></div> 
 
    <div class="red">BEGIN</div> 
 
    <div class="blue">Fading black area is ahead...</div> 
 
    <div id="fadingblack" class="black">&nbsp;</div> 
 
    <div class="blue">&nbsp;</div> 
 
    <div class="red">&nbsp;</div> 
 
    <div class="blue">END</div> 
 
</div>

関連する問題