我有一个DIV(容器元素)。
这是我想淡入和淡出的一些元素(取决于用户滚动的方向)。这没问题。
请参阅嵌入式代码段以进行演示。
注意演示中的黑色区域;我希望在褪色的同时将它保持在顶部(通过滚动一段距离)。
在这些元素的淡入和淡出期间,我希望保持父容器(DIV)不移动(垂直)直到淡入或淡出完成。而这部分对我来说就是一个问题。
我已经使用一个似乎在Chrome中运行正常的示例更新了我的代码(使用负marginTop
来提升div
(向上滚动时)和正top
用于按下div
(当向下滚动时)。但是在例如Edge或Firefox中运行非常“糟糕”(scroll
- 滚动后触发的事件使其滞后)。
position: sticky
。这首先使用position: relative
,然后使用position: fixed
,因此它不能完全按我的意愿使用。在非Chrome(!)
的浏览器中,代码很糟糕
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>
答案 0 :(得分:0)
可能没有办法真正 - 以更自然的方式 - 阻止div
使用position: fixed
- 甚至position: sticky
(其中稍后使用相对定位和以后它固定定位时 - 并且当你希望它在某个点时滚动时,它的大小比视口大。
仍然是我的问题的目标(停止滚动以淡化一些div
元素)我可以用一些代码行回答自己。总结:使用marginTop
的{{1}}来提取使用固定定位的div
的一些div
子元素。
我确实至少有一个与此代码相关的问题(可能是两个)(但不是防止滚动)。但这也是我可以提出的其他问题。
我现在接受我自己的回答。如果有人对这个问题有更好或更“自然”的想法 - 我有点怀疑 - 我会高兴地改变我对这个答案的接受。
div
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;
}