001
001

Reputation: 2059

JavaScript - Get Scrolling Value and Convert it to Animate Element

Basic info:

I have 4 sections, each section height = 100vh.
And a function that prints True to the console when reaching a half section height before section2, till section2 bottom reaches the top of the page (which means scrolling over it).

What I'm trying to achieve:

Animate an element with jQuery this way:
x will start as 1 and ends at 2, vice versa, in 10 steps, each step is 0.1

if (true) {
    $(element).css({
        transform: "scale(x)",
    }, 500, 'easeInOutSine');
}
else {
    $(element).css({
        transform: "scale(x)",
    }, 500, 'easeInOutSine');
}

So I have to convert the height of scrolling (number) from the start to the end, into a 10 step, every 1/10 of scrolling it adds 0.1.

In math, it looks like this (without the other half of section1):

var section = $(".section2");
var section_height = section.height();
var one_of_ten = section_height / 10;
var count = 0;
var x = 1;

while(x <= 2){
    count = 0;
    while(count <= one_of_ten){
        count++;
    }
    x+=0.1;
}

It prints to the console the numbers from 1 to 2 in 10 steps.

The problem:

How can I get the height of the scrolling part and check for every 1/10 step to add 0.1 to x?

My Code:

function check_onscroll(){
    var section = $(".section2");
    var sectionHeight = section.height();
    var sectionTop = section.offset().top;    
    $(window).scroll(function () {
        var scrollFromTop = $(window).scrollTop();
        if (sectionTop - ($(window).height() / 2) <= scrollFromTop
            && scrollFromTop <= sectionTop + section.height()){
                console.log("True");
        }   
    });
}

check_onscroll();
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html {
    scroll-behavior: smooth;
}

body {
    height: auto;
}

.section {
    height: 100vh;
    display: flex; 
    justify-content: center;
    align-items: center;
}

.section1  {
    background-color: red;
}
.section2  {
    background-color: yellow;
}
.section3  {
    background-color: green;
}
.section4  {
    background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="section section1">
    <h2>Section 1</h2>
</div>
<div class="section section2">
    <h2>Section 2</h2>
</div>
<div class="section section3">
    <h2>Section 3</h2>
</div>
<div class="section section4">
    <h2>Section 4</h2>
</div>

Upvotes: 3

Views: 586

Answers (2)

A Haworth
A Haworth

Reputation: 36624

I'm not sure what it is that you want to scale, so this snippet scales the h2 element depending on how much of its section is in view. If less than 50% is in view then it's still at scale 1. For each 10th of the remaining (i.e. half) section it increases the scale.

We use intersectionObserver to do this for us as it will tell us the ratio of the section that is in view.

First we create an intersectionObserver, telling it to observe when an element is 50% within the viewport and then every 1/10th of the remainder thereafter.

Then we ask the observer to observe each section.

When a section is observed coming into the viewport by 50% or 55% or 60% ... up to .. 100% then we scale its h2 element by 1 plus this amount (i.e. between 0 and 1).

If you console.log the ratios in the observer callback function you will see that they are not always exactly 0.1 or 0.2 etc but they are fractions which show how much of the half element is actually in view. Using these values rather than calculating an x+ 0.1 gives a more accurate picture of how much scrolling has been done so the results are smoother.

(note, there didn't seem to be much of a use for jquery in this snippet so it has been dropped)

let callback = (entries, observer) => {
//taken from MDN documentation:
  entries.forEach(entry => {
    // Each entry describes an intersection change for one observed
    // target element:
    //   entry.boundingClientRect
    //   entry.intersectionRatio
    //   entry.intersectionRect
    //   entry.isIntersecting
    //   entry.rootBounds
    //   entry.target
    //   entry.time
    entry.target.querySelector('h2').style.transform = 'scale(' + (1+entry.intersectionRatio) + ')'; 
  });
};
let options = {
  threshold: [ 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00]
}

let observer = new IntersectionObserver(callback, options);
const sections = document.querySelectorAll('.section');
sections.forEach(section => { observer.observe(section, options);});
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html {
    scroll-behavior: smooth;
}

body {
    height: auto;
}

.section {
    height: 100vh;
    display: flex; 
    justify-content: center;
    align-items: center;
}

.section1  {
    background-color: red;
}
.section2  {
    background-color: yellow;
}
.section3  {
    background-color: green;
}
.section4  {
    background-color: blue;
}
<div class="section section1">
    <h2>Section 1</h2>
</div>
<div class="section section2">
    <h2>Section 2</h2>
</div>
<div class="section section3">
    <h2>Section 3</h2>
</div>
<div class="section section4">
    <h2>Section 4</h2>
</div>

Upvotes: 2

caiovisk
caiovisk

Reputation: 3819

You can listen the scroll event and get the current scrollTop() to see where the user scroll are at. Then do the math.

Something like the below:

var section = $(".section2");
var sectionHeight = section.height();
var sectionTop = section.offset().top;   
    
function check_onscroll(){
    
    var scrollFromTop = $(window).scrollTop();
    if (sectionTop - ($(window).height() / 2) <= scrollFromTop
        && scrollFromTop <= sectionTop + section.height()){
          curHalfPosition = scrollFromTop - (sectionTop / 2);
          curPace = (sectionHeight / 2) / 10;
          scale = parseInt(curHalfPosition / curPace);
          scale_section (section, scale);
    }   

}

function scale_section(element, scale)
{
  scale = (10 + scale) / 10;
  if (scale > 2 && scale < 1) return;
      $(element[0]).css({
          transform: "scale("+scale+")",
      }, 500, 'easeInOutSine');

}

$(window).scroll(check_onscroll);
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html {
    scroll-behavior: smooth;
}

body {
    height: auto;
}

.section {
    height: 100vh;
    display: flex; 
    justify-content: center;
    align-items: center;
}

.section1  {
    background-color: red;
}
.section2  {
    background-color: yellow;
}
.section3  {
    background-color: green;
}
.section4  {
    background-color: blue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="section section1">
    <h2>Section 1</h2>
</div>
<div class="section section2">
    <h2>Section 2</h2>
</div>
<div class="section section3">
    <h2>Section 3</h2>
</div>
<div class="section section4">
    <h2>Section 4</h2>
</div>

Upvotes: 0

Related Questions