私は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"> </div>
<div class="blue"> </div>
<div class="red"> </div>
<div class="blue">END</div>
</div>
だから、ビューに他のdivをもたらし続け、それは視野にいたら、その後、フェードをスクロール「fadingblack」のdivが固執したい、それはフェージング行うの後は? – Slime
@AmericanSlimeはい、それはまさに私が達成したいものです。 – Wieger