-1

i'm trying to run a function called txtAnim when the element .txt-anim enters to the viewport and want to use getBoundingClientRect or intersection observer

Is that possible? I didn't get it working

(I have the animation working but i want it fired when it enters to the viewport)

function txtAnim(speed){

    jQuery('.txt-anim').css("opacity", "1");

    var skills = jQuery('.txt-anim p').contents().filter(function() {
        return this.nodeType === 3; // only immediate text in div, not in span
    }).map(function() {
        var txt = "<span class='letter'>" + jQuery(this).text().split("").join("</span><span class='letter'>") + "</span>";
        // console.log(txt);
        jQuery(this).replaceWith(txt);
    });

    var i = 0;
    var span = jQuery('.txt-anim').find('span');

    jQuery(".txt-anim p").empty();

    typeWriter();
    function typeWriter() {
        if (i < span.length) {
            jQuery('.txt-anim p').append(span[i]) ;
            i++;
            setTimeout(typeWriter, speed);
        }else{
            console.log("text animation ended");
            jQuery('.home-page-cities-mobile').css("opacity", "1");
            jQuery('.flecha-home').css("opacity", "1");
        }
    }

}    
//Intersection Observer
const textAnim = document.querySelector('.txt-anim');
let options = {
  root: textAnim,
  rootMargin: "0px",
  threshold: 1.0
};

let observer = new IntersectionObserver(txtAnim(20), options);

observer.observe(textAnim);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="logo-message txt-anim">
                <p>
                    <span class="letter">L</span>
                    <span class="letter">i</span>
                    <span class="letter">q</span>
                    <span class="letter">u</span>
                    <span class="letter">i</span>
                    <span class="letter">d</span>
                    <span class="letter empty"> </span>
                    <span class="letter">i</span>
                    <span class="letter">d</span>
                    <span class="letter">e</span>
                    <span class="letter">a</span>
                    <span class="letter">s</span>
                    <span class="letter empty"> </span>
                    <span class="letter">t</span>
                    <span class="letter">o</span>
                    <span class="letter empty"> </span>
                    <span class="letter">g</span>
                    <span class="letter">e</span>
                    <span class="letter">t</span>
                    <span class="letter empty"> </span>
                    <span class="letter">a</span>
                    <span class="letter">n</span>
                    <span class="letter">y</span>
                    <span class="letter">w</span>
                    <span class="letter">h</span>
                    <span class="letter">e</span>
                    <span class="letter">r</span>
                    <span class="letter">e</span>
                </p>
            </div>

Can anyone help? I've tried with intersection observer beucase i thought it would be easier

Vander
  • 79
  • 9
  • 1
    Post your code. – Mitya Dec 23 '20 at 10:30
  • 1
    It may be possible, but without a [mcve] in your question we can't know or help. – evolutionxbox Dec 23 '20 at 10:34
  • @mitya done! Code posted – Vander Dec 23 '20 at 10:36
  • @evolutionxbox done! Code posted – Vander Dec 23 '20 at 10:36
  • @Vander that's a good first step, but it's not a complete demo. When we run it there are errors. What is the actual problem you're trying to solve? – evolutionxbox Dec 23 '20 at 10:42
  • @evolutionxbox Done, sorry man – Vander Dec 23 '20 at 10:46
  • 1
    What is `txtAnim(20)` supposed to do? – evolutionxbox Dec 23 '20 at 10:52
  • @evolutionxbox it animates the text, the 20 is the speed, you can see it if you run the code, so i want this function to be fired then the text enters to the viewport – Vander Dec 23 '20 at 10:53
  • `IntersectionObserver` requires the first argument to be a callback, but `txtAnim` is being called so the observer is being given `undefined`. – evolutionxbox Dec 23 '20 at 10:56
  • @evolutionxbox what should i do? i did not understand – Vander Dec 23 '20 at 11:01
  • https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API says that doing `new IntersectionObserver(txtAnim(20), ...` won't work as the first argument needs to be a callable function. `txtAnim(20)` returns undefined which is not a callable function. --- Try `new IntersectionObserver( () => txtAnim(20), ...` instead? – evolutionxbox Dec 23 '20 at 11:06
  • @evolutionxbox Nope, that didnt work... Don't know why it returns undefined or how cn i make it a callable function – Vander Dec 23 '20 at 11:10
  • @Vander saying it didn't work isn't helpful. Please show an example. Besides, that's likely not the only problem here --- As for why the function returns undefined, see https://stackoverflow.com/questions/17337064/does-every-javascript-function-have-to-return-a-value – evolutionxbox Dec 23 '20 at 11:12

1 Answers1

3

OK, so there's a couple problems with the way you're using intersection observer here.

First, your root is wrong. You're using the same element for root as you're trying to observe, which means you're asking the question, When does this element intersect with itself? which is obviously not a very useful question.

If you want it to show when you've scrolled to it in the viewport, you actually don't need to specify a root at all.

Secondly, you're not checking the thing you really need to check: the isIntersecting property. When the intersection observer callback fires, the first argument is an array of entries, and each entry has an isIntersecting property which can be true or false.

I've made this jsfiddle that maybe comes close to doing what you want.

https://jsfiddle.net/xapjz2fe/

As you can see, i've also added in a check to make sure the function txtAnim doesn't run itself more than once -- without that check, if you scrolled to the element, then scrolled away and scrolled back, txtAnim would run a second time and it would mess everything up.

let txtAnimStarted = false;
function txtAnim(speed){
        if (txtAnimStarted) return;
    txtAnimStarted = true;
        console.log('starting txtAnim');
    jQuery('.txt-anim').css("opacity", "1");

    var skills = jQuery('.txt-anim p').contents().filter(function() {
        return this.nodeType === 3; // only immediate text in div, not in span
    }).map(function() {
        var txt = "<span class='letter'>" + jQuery(this).text().split("").join("</span><span class='letter'>") + "</span>";
        // console.log(txt);
        jQuery(this).replaceWith(txt);
    });

    var i = 0;
    var span = jQuery('.txt-anim').find('span');

    jQuery(".txt-anim p").empty();

    typeWriter();
    function typeWriter() {
        if (i < span.length) {
            jQuery('.txt-anim p').append(span[i]) ;
            i++;
            setTimeout(typeWriter, speed);
        }else{
            console.log("text animation ended");
            jQuery('.home-page-cities-mobile').css("opacity", "1");
            jQuery('.flecha-home').css("opacity", "1");
        }
    }

}    
//Intersection Observer
const textAnim = document.querySelector('.txt-anim');
let options = {
  rootMargin: "0px",
  threshold: 1.0
};

let observer = new IntersectionObserver((entries) => {
    const entry = entries[0];
  if (entry.isIntersecting) txtAnim(20);
}, options);

observer.observe(textAnim);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div style="margin-bottom:1000px">top div, scroll down</div>

<div class="logo-message txt-anim" style="padding-bottom:20px">
  <p>
    <span class="letter">L</span>
    <span class="letter">i</span>
    <span class="letter">q</span>
    <span class="letter">u</span>
    <span class="letter">i</span>
    <span class="letter">d</span>
    <span class="letter empty"> </span>
    <span class="letter">i</span>
    <span class="letter">d</span>
    <span class="letter">e</span>
    <span class="letter">a</span>
    <span class="letter">s</span>
    <span class="letter empty"> </span>
    <span class="letter">t</span>
    <span class="letter">o</span>
    <span class="letter empty"> </span>
    <span class="letter">g</span>
    <span class="letter">e</span>
    <span class="letter">t</span>
    <span class="letter empty"> </span>
    <span class="letter">a</span>
    <span class="letter">n</span>
    <span class="letter">y</span>
    <span class="letter">w</span>
    <span class="letter">h</span>
    <span class="letter">e</span>
    <span class="letter">r</span>
    <span class="letter">e</span>
  </p>
</div>

My indentation of the javascript got ruined copying over from jsfiddle, sorry about that

TKoL
  • 13,158
  • 3
  • 39
  • 73
  • 2
    Good answer, nicely demonstrated. – evolutionxbox Dec 23 '20 at 11:13
  • 1
    That was really helpful man :) Really appreciated and well explained. It was hard for me to understand the intersection observer docs and why my code wasn't running. Many Many many thanks – Vander Dec 23 '20 at 11:20