Search code examples
javascriptjquerymathparallaxmath-functions

Complex mathematical horizontal parallax easing function


I'm currently diving into parallax effects on the web.

Parallax scrolling is a technique in computer graphics and web design, where background images move by the camera slower than foreground images, creating an illusion of depth in a 2D scene and adding to the immersion. ~ Wikipedia

I want to create a little container (could be an image, or any block level element) and move it across the screen horizontally as the user scrolls.

The effect should be scalable across all viewports. Meaning that the hight and the width of the element that the element is moving across should not matter.

When the user has scrolled half of the height of the screen the "moving element" should be in the exact center. Since the user will have scrolled half of the screen the element will be vertically already. We're only worried about horizontally right now.

I've thought about this question for a while and came up with a pretty good idea of how.


  1. Take the hight and the width of the element you want the "moving element" to move across. For example a screen that is 1000px tall and 600px wide.

  2. Divide the width by the height. For example (600px / 1000px = 3/5 = 0.6)

  3. Take the amount of pixels the user scrolled and multiply it by the number we just created. For example (500px * 0.6 = 300px). As you can see this is the exact center.

  4. Move the element across the screen by the amount of pixels just calculated.


This calculation works fine even for every screen size, however it's linear. Meaning that the element will move at the same speed across the screen all the time. Let me show you what I mean.


  1. Let's draw out a screen size. (Let's say 1000 * 500)
  2. Calculate two points for this graph ->

screen factor: (500 / 1000) = 0.5 1. The first point is going to be easy. Let's say we scrolled exactly 0px -> (0.5 * 0) = 0 The "Moving element" will not have moved at all. 2. For the second element we'll take the center. Just for convenience.

The vertical center is at 500px -> (0.5 * 500) = 250 px (Exactly the horizontal center)

  1. Put the results in a graph and draw a line through the points. graph

In the graph above you can see that whenever the user scrolls down the "moving element" will follow the line (the values on the x-axis).

My question

I really hope I described all that well enough to understand. Now on to my question.

What I want to create is a moving element that would go faster on the edge of the screen and slow down a bit in the middle. If we were to draw that out in the same way we just did. (Creating a graph where we can take the amount of pixels scrolled and see where the element should be positioned horizontally) it would look like this:

Hand drawn graph

Sorry for the poor quality of the image but this is the part I'm having problems with.

As you can see in this graph the "moving element" wouldn't be moving all that much in the middle of the graph. (I over did it a bit in my drawing but you get the general idea.)

What I need is a mathematical function that takes three parameters (Screen height, width and the amount of pixels scrolled) and returns the horizontal position of the "moving element".


My idea:

My idea was to position the element in the dead center of the page and then to move it left and right (translations using CSS and JavaScript) based on how far there has been scrolled.

The graph would look something like this:

Graph-3

The (Hand drawn) graph above would be true for a screen that's 1000x600px since the "moving element" translates -300px when no scrolling has been done and 300px when 100% has been scrolled.

However I have no idea on how to create a mathematical function that would be true for every screen size.

To be clear I need a function that "always" starts at Y= (-screen-width/2) and X = 0. It should always cross the point (sreen-height; (screen-width//2)) and the function should be in a form of x^3 (To get the right easing)


I really hope I explained myself well enough and I really hope somebody can help me out here.


Solution

  • Answer from math.stackexchange

    Besides asking my question here I also went ahead and posted this question on math.stackexchange.com. Stackoverflow's mathematical sister site. Somebody there helped me find an answer to my question.

    The function had to be a function that would output the moving-element it's horizontal position in pixels relative to the horizontal center of the page based on the amount of pixels scrolled since the element was first visible. The function would have to be "steeper" on the edges and ease into a short stop in the middle and be usable across every possible screen size. Meaning that the mathematical function would have to be positioned based on two variables, screen height and -width.


    The answer they came up with on math.stackexchange:

    math function

    In this example s-width is the width of the screen in pixels. s-height is the height of the screen in pixels. px-scrolled is the amount of pixels scrolled since the element was first visible.

    The output pos is the moving elements horizontal position in pixels relative to the center of the screen.

    If you put all this math into JavaScript you get the following:

    var pos = ((4*win_width)/(Math.pow(win_height, 3))) * Math.pow(px_since_visible - (win_height/2),3)
    

    There is a working example available on codepen. You can find it here.