JSFiddle - React, Tailwind, and code Playground
HTML
<div style="margin-bottom:1000px">top div, scroll down</div>
<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>
JavaScript 1.7
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);