簡體   English   中英

如何從滾動中阻止DIV大於視口?

[英]How to stop DIV larger than viewport from scrolling?

我有一個DIV(容器元素)。

其中有一些我希望淡入和淡出的元素(取決於用戶滾動的方向)。 這沒問題。

有關演示,請參閱嵌入式代碼段。

問題

注意演示中淡化的黑色區域; 我希望在褪色的同時將它保持在頂部(通過滾動一段距離)。

在這些元素的淡入和淡出期間,我希望保持父容器(DIV)不移動(垂直)直到淡入或淡出完成。 而這部分對我來說是一個問題。

更新11-03-2017

我已經用一個例子更新了我的代碼,它似乎在Chrome中運行正常(使用負marginTop來提升div (向上滾動時)和正向top用於向下推div (向下滾動時)。但是在運行時非常例如Edge或Firefox中的“糟糕”( scroll后觸發的事件使其落后)。

我試過了什么

  • 我嘗試過使用position: sticky 這使用position: relative第一,然后position: fixed所以它不是我想要的。
  • 我嘗試過使用'position:fixed'。 當然,父容器DIV確實粘在視口上。 但是,因為它的高度大於視口的高度,所以它不能按照我的預期方式工作,例如,如果用戶滾動到大容器高度的50%,則使用“position:fixed”將此scrollTop丟失。
  • 我嘗試將'position:fixed'與'scroll'事件和marginTop CSS-property(以及'top'CSS屬性)結合使用。 我得到了奇怪的結果。 此外,在用戶滾動一定量的像素之后總是執行“滾動”事件。 因此,如果它能夠工作,那么可能會遇到“滯后”的經歷。
  • 我已經搜索了jQuery插件等,但它們也依賴於“position:fixed”,因此也受到限制。
  • 我嘗試過ScrollMagic並使用GreenSock的TimelineMax同時執行補間。 例如淡入淡出和淡出的一個補間和一個補間利用marginTop(再次)或頂部的補間以補償'position:absolute'和'position:relative'的滾動距離。
  • 我試過捕獲鼠標滾輪事件然后滾動programmaticaly(所以我可以選擇不滾動)。 這當然是一種選擇。 但我真的很喜歡滾動條。 移動體驗滯后,因為當編程滾動時,人們無法使用例如“雙擊”手勢。
  • 我嘗試了很多東西,並嘗試了很多變化。

代碼(嵌入代碼段) - 已更新11-03-2017

在非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">&nbsp;</div> <div class="blue">&nbsp;</div> <div class="red">&nbsp;</div> <div class="blue">END</div> </div> 

可能沒有辦法真正 - 以一種更自然的方式 - 防止使用position: fixeddiv 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">&nbsp;</div> <div class="blue">&nbsp;</div> <div class="red">&nbsp;</div> <div class="blue">END</div> </div> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM