计算图像的位置以跟随滚动

问题描述 投票:11回答:3

当用户滚动页面并在其底部有一个箭头时,我想在屏幕上从页面顶部到底部绘制一条线。我不想使用固定位置,以便它始终在同一个位置,我希望它通过确定页面长度等来指示它们在页面上的位置。

我有以下代码可以解决问题。这个问题是当我在中途向下滚动后,箭头从页面底部消失。

我尝试过这段代码的不同变体但没有效果。有人可以帮忙吗?

//Draw dotted line on scroll - works to certain extent but scrolls off page
    $( window ).scroll(function() {
        if ( $.windowScrollTop() > 10 ) {
            var pos = $.windowScrollTop();
            var scrollHeight = $(window).innerHeight();
            var element = $('#dashes');
            $( '#line' ).css( 'height', pos - scrollHeight / 4 );
            $( '#arrow' ).css( 'top', pos - scrollHeight / 4 );
        } else {
            $( '#line' ).css( 'height', '6px' );
            $( '#arrow' ).css( 'top', '-150px' );
        }
    });

//also tried the below

    $(window).on("scroll", function() {
        var scrollHeight = $(document).height();
        var scrollPosition = $(window).height() + $(window).scrollTop();
        if ((scrollHeight - scrollPosition) / scrollHeight === 0) {
            // when scroll to bottom of the page
            alert('bottom');
        } else {
                $( '#line' ).css( 'height', $(window).scrollTop() );
                $( '#arrow' ).css( 'top', $(window).scrollTop() );      
        }
    });
javascript jquery css scroll
3个回答
7
投票

我们在这里要做的是将文档高度反映到窗口高度的元素中。所以实际的可滚动文档高度将是

    var actualScrollHeight = $(document).height() - $(window).height();
    /* This is the distance we actually scroll */

而我们的#line将有一个最大可能的高度

    var lineMaxHeight = $(window).height() - topMargin - bottomMargin - arrowHeight;
    /* #arrow is inside #line but we positioned it outside it's height */

不反映#line元素高度的滚动进度我们需要做的是

    var lineHeight = $(document).scrollTop() / actualScrollHeight * lineMaxHeight;
    /* Super Easy, isn't it? */

最终结果:

你不需要同时定位#line#arrow。将#arrow固定在#line的底部,然后只需改变#line的高度即可。我添加了topMarginbottomMargin功能,使屏幕调整更加自定义。

$(function(){
  var topMargin = 15, bottomMargin = 5;
  var arrowHeight = $('#arrow').height();
  var $lineElement = $('#line');
  $lineElement.height(topMargin);
  $(window).scroll(function() {
    var winHeight = $(window).height();
    var actualScrollHeight = $(document).height() - winHeight;
    var lineMaxHeight = winHeight - topMargin - bottomMargin - arrowHeight;
    var scrollTop = $(document).scrollTop();
    var lineHeight = scrollTop / actualScrollHeight * lineMaxHeight;
    $lineElement.height(topMargin + lineHeight);
  });
});
#logo {
  width: 80px;
  background-color: #53befd;
  padding: 20px;
}

#line {
  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAMCAYAAABBV8wuAAAAFklEQVR42mNgoB74OEXzPzY8sBLUAwB6PmBV1D+CIAAAAABJRU5ErkJggg==);
  position: fixed;
  top: 0px;
  right: 19px;
  z-index: 20;
  width: 3px;
}

#arrow {
  background-color: #f28323;
  height: 40px;
  width: 40px;
  position: absolute;
  bottom: -40px;
  left: -18px;
  border-radius: 20px;
  color: white;
  text-align: center;
  font-size: 32px;
  line-height: 35px;
  padding-top: 3px;
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="logo">LOGO </div>
<p>  Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p>  Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p>  Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p>  Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p>  Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p>  Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p>  Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p>  Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p>  Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p><p>  Page content go here<br /> and here<br /> and here<br /> and here<br /> and here</p>
<div id="line"><div id="arrow">V</div></div>

3
投票

你的方法看起来像是在过度思考它。我看到一个HTML progress元素转为180度视觉。然后,当用户滚动时,用JS动态设置它的value属性,该线基本上看起来像是动画下来的。

// PROGRESS INDICATOR
// Calculate height of main object and the window, set max attr of progress accordingly
var winHeight = $(window).height(),
    sectionHeight = $('#line').height(),
    progressBar = $('progress'),
    max,
    value;

// Set the maximum scrollable area
max = sectionHeight - winHeight;
progressBar.attr('max', sectionHeight);

// Set value attr of progress, changes as user scrolls
$(document).on('scroll', function(){
  value = $(window).scrollTop();
  progressBar.attr('value', value);
});

progress元素的CSS看起来像这样,你将栏放在页面上作为一个固定的元素,并使其动画,以便用上面的JS逐步覆盖更多的页面。

CSS示例:

progress {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  background-color: transparent;
  border: none; //firefox fix
  color: green;
  height: 2.5rem;
  margin-top: 20vw;
  position: fixed;
  top: 8rem;
  width: 100vh;

  @media (min-width: 768px) and (max-width: 1200px) {
    display: block;
    transform: rotate(90deg) translateY(1800%);
  }

  @media (min-width: 1200px) {
    display: block;
    transform: rotate(90deg) translateY(1200%); // matches content shift to smaller column
  }
}

如果你想看看是否在野外工作,我建造了this on one of my client sites(仅适用于大约1000px及更高,所以要确保你的窗户足够宽)。


3
投票

使用较少的代码,这是一个更简单的解决方案:

$(function() {
  $(window).scroll(function() {
    var p = ($('body').height() - $(window).height()) / ($(window).height() - 43);
    var scrollTop = $(document).scrollTop() / p;
    $(':root').css('--scroll-top', scrollTop + 43 + "px");
  });
});
:root {
  --scroll-top: 43px;
}

#logo {
  width: 80px;
  background-color: #53befd;
  padding: 20px;
}

.content {
  height: 210vh;
  background: red;
  margin-right: 50px;
}

#line:before {
  content: "V";
  background-color: #f28323;
  height: 40px;
  width: 40px;
  display: inline-block;
  position: absolute;
  right: 0;
  bottom: 0;
  border-radius: 20px;
  color: white;
  text-align: center;
  font-size: 32px;
  line-height: 35px;
  padding-top: 3px;
  cursor: pointer;
}

#line {
  position: fixed;
  top: 0;
  right: 0;
  height: var(--scroll-top);
  width: 40px;
  background: linear-gradient(to bottom, #f28323 50%, transparent 50%) 50% 0/3px 12px repeat-y;
}
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<div id="logo">LOGO </div>
<div class="content"></div>

<div id="line"></div>
© www.soinside.com 2019 - 2024. All rights reserved.