Sat
Sat

Reputation: 170

How to make JavaScript do something every X amount of pixels scrolled

So this is somewhat of a math problem that I'd like to solve using JavaScript. I'm creating a fixed canvas on a website that outputs a different image based on every X amount of pixels scrolled from a particular .offset().top from the top of the window. I 'could' explicitly map a new image to a particular position but I've got a lot of images and it would behoove me to create a function that can handle this process multiple times until particular end point. I'm sort of stuck on how to express this and was wondering if anyone could steer me in the right direction.

EDIT

After consider @Richard Hamilton answer below I've been able to somewhat successfully implement his solution to my own project. It's a little verbose, but here's what I have...

// Preload Images
var totalImages = 203
var images = new Array()
for (var i = 1; i <= totalImages; i++) {

    var filename = 'img_'
    if (i < 10) filename += '00'
    if (i > 9 && i < 100) filename += '0'
    filename += i + '.jpg'

    var img = new Image
    img.src = '/images/temp/' + filename

    images.push(img)
}

//  Set initial frame index
var currentLocation = 0

// Canvas Context
var canv = document.getElementById('canvas')
var context = canv.getContext('2d')
$(canv)
    .width(768)
    .height(432)

// Frame Starting Location
var currentLocation = 0

// Determin the breakpoint increment to fit inside the context
var contextHeight = $('.about--context').height() - 200
var frameHeight = contextHeight / totalImages

// Set first breakpoint
var breakpoint = 63

// Get top of context in relation to window
var contextPos = $('.about--context').offset().top - $(window).scrollTop()

// Set where to start scrubbing through frames
var scrubStart = 62

// Initial scroll direction
var lastScrollTop = 0,
    st,
    direction

// Output the scroll direction as up or down
function detectDirection() {

    st = window.pageYOffset;
    if (st > lastScrollTop) {
        direction = "down"
    } else {
        direction = "up"
    }
    lastScrollTop = st
    return direction

}

window.addEventListener('scroll', function() {

    var dir = detectDirection()

    var contextPos = $('.about--context').offset().top - $(window).scrollTop()
    var contextHeight = $('.about--context').height()
    var frameHeight = contextHeight / totalImages

    if (contextPos <= breakpoint && dir === 'down') {
        breakpoint -= frameHeight
        currentLocation++
        context.drawImage(images[currentLocation], 0, 0, 768, 432)
        console.log('Breakpoint = ' + breakpoint + ', index = ' + currentLocation)
    }
    if (contextPos > breakpoint && dir === 'up') {
        breakpoint += frameHeight
        currentLocation--
        context.drawImage(images[currentLocation], 0, 0, 768, 432)
        console.log('Breakpoint = ' + breakpoint + ', index = ' + currentLocation)
    }

})

This mostly works, but there seems to be a discrepancy between how the frames change during scroll between a mouse wheel and a trackpad. The trackpad is much more sensitive and can get the breakpoint increment correctly, but the mouse wheel ends up scrolling through the section much quicker without correctly keeping up with the proper frame rate, so I never end up reach the final frame by the end of the section. Other than that the frames are moving correctly when scrolling up and down.

Upvotes: 3

Views: 2105

Answers (1)

Richard Hamilton
Richard Hamilton

Reputation: 26444

Let's say you have an image tag. If you have a lot of different image files, it would be a good idea to store them in array. This is a hard coded example, but shows the general structure.

var image = document.getElementById("myImage");
var sources = ["image1.png", "image2.png", "image3.png", "image4.png"];

var i = 0;
var breakpoint = 100;                           // Change to whatever you like

window.addEventListener("scroll", function() {
    var scrollDown = document.body.scrollTop;
    if (scrollDown >= breakpoint) {
       img.setAttribute(src, sources[i]);
       breakpoint += 100;                       //Change to whatever you like
       i++;
    }
}

You could also have something like this included

 var windowHeight = window.innerHeight;
 var scrollBottom = document.body.clientHeight - document.body.scrollTop;
 if (scrollBottom === windowHeight) {
     // Do something
 }

First set a breakpoint variable equal to the number of pixels you want to scroll. For an example, I chose 100 because it's a nice round number. You then attach an event listener on the window object, to detect if a user is scrolling.

The scrollTop function represents how far the top of the screen is from the top of the window. If that value is higher than the breakpoint, that's when we call our code. We then increment this by 100.

Upvotes: 4

Related Questions