[英]How to stop DIV larger than viewport from scrolling?
我有一个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>
可能没有办法真正 - 以一种更自然的方式 - 防止使用position: fixed
的div
position: fixed
- 甚至position: sticky
(它首先使用相对定位, 然后在固定定位时使用相对定位) - 并且具有更大的您希望它在特定点滚动时的大小比视口大。
仍然,我的问题的目标(停止滚动淡出一些div
元素)我可以用一些代码行回答自己。 总结:使用div
marginTop
来拉出使用固定定位的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; }
<!-- 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"> </div> <div class="blue"> </div> <div class="red"> </div> <div class="blue">END</div> </div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.