最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - calculate positioning of image to follow scroller - Stack Overflow

programmeradmin1浏览0评论

I want to draw a line on screen from the top of the page to the bottom when the user scrolls the page and have an arrow at the bottom of it. I don't want to use fixed position so that its always in the same spot, I want it to indicate where they are on the page by determining the page length etc.

I have the following code that works to a point. The problem with this is the arrow disappears off the bottom of the page when I scroll just after half way down.

I have tried different variations of this code but none work. Can anyone help?

//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() );      
        }
    });

I want to draw a line on screen from the top of the page to the bottom when the user scrolls the page and have an arrow at the bottom of it. I don't want to use fixed position so that its always in the same spot, I want it to indicate where they are on the page by determining the page length etc.

I have the following code that works to a point. The problem with this is the arrow disappears off the bottom of the page when I scroll just after half way down.

I have tried different variations of this code but none work. Can anyone help?

//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() );      
        }
    });
Share Improve this question edited Mar 1, 2018 at 16:34 TylerH 21.1k77 gold badges79 silver badges112 bronze badges asked Feb 27, 2018 at 12:54 LeeTeeLeeTee 6,60118 gold badges85 silver badges142 bronze badges 3
  • 1 Check this. stackoverflow./questions/35111425/… – sagar43 Commented Feb 27, 2018 at 12:56
  • Ok so this uses $(this).offset(); but not sure how to apply that to my code – LeeTee Commented Feb 27, 2018 at 13:24
  • 1 Can you post your markup/css or create a simplified example so we can play around with it – Huangism Commented Mar 1, 2018 at 16:37
Add a ment  | 

3 Answers 3

Reset to default 7 +50

What we are trying to do here is reflect the document height into an element of window height. So the actual scrollable document height will be

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

And our #line will have a maximum possible height of

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

No to reflect the scroll progress in #line elements height what we need to do is

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

The Final Result:

You don't need to position both the #line and #arrow. Fix the #arrow at the bottom of #line and then just changing the height of #line works just fine. I added the topMargin and bottomMargin feature making screen adjustment more customizing.

$(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./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>

Your approaches look like you're overthinking it. I'm seeing an HTML progress element turned 180 degrees for the visual. Then, set it's value attribute dynamically with JS as the user scrolls and the line will essentially look like it's animating down.

// 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);
});

CSS for the progress element would look something like this, where you place the bar as a fixed element on the page and animate it to cover progressively more of the page with the JS above.

CSS example:

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
  }
}

I built this on one of my client sites if you want to see if working in the wild (only works at about 1000px and higher so make sure your window is wide enough).

Here is an easier solution with less code:

$(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./jquery-3.3.1.min.js"></script>
<div id="logo">LOGO </div>
<div class="content"></div>

<div id="line"></div>

发布评论

评论列表(0)

  1. 暂无评论