<div id="container">
  <div class="center">
    <h1 class="el-st">Javascript text fx.</h1>
    <span class="scroll">Scroll to shuffle</span>
  </div>
</div>
/**********************************************
*** GENERAL
**********************************************/



:root {
    --position: 0;
}

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

body, html {
    width:100%;
    height:100%;
    font-family: 'Share Tech Mono', monospace;
}

#container {
    height: 1000vh;
    background: #000;
}

.center {
    text-align: center;
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50% , -50%);
}

.el-st {
    color: #eee;
    font-size: 30px;
    font-weight:bold;
    letter-spacing: 4px;
}

.el-sp.is-changing {
    animation: changing 0.1s infinite;
}

.el-sp {
    transition: all 0.1s;
    text-shadow: 0 0 10px #008f11;
    position: relative;
    will-change: transform, opacity;
}

.el-sp:after {
    content:attr(data-txt);
    color:#eee;
    position: absolute;
    top: 0;
    left:0;
    opacity:0;
    will-change: transform, opacity;
}

.el-sp.is-changing:after {
    animation: changingAfter 0.4s infinite alternate;
}

.scroll {
    margin-top: 40px;
    color:#008f11;
    display: inline-block;
    padding-bottom: 3px; 
    padding-right: 40px;
    position: relative;
}

.scroll:after {
    content:'';
    position: absolute;
    left: calc(100% - 35px);
    top: 0;
    animation: dots 2s infinite;
}

@keyframes changing {
    0% {opacity:1;}
    50% {opacity:0.5;}
    100% {opacity:1;}
}

@keyframes changingAfter {
    0% {opacity:0.3;transform:translateX(10px) scaleX(2)}
    50% {opacity:0;transform:translateX(0) scaleX(2)}
    100% {opacity:0.3;transform:translateX(-10px) scaleX(2)}
}

@keyframes dots {
    0% {content:''}
    25% {content:'.'}
    50% {content:'..'}
    75% {content:'...'}
}




var stringRandom = (function() {

    var data = {
        isScrolling : false,
        repeat : 0,
        target : [],
        letters : '*+-/@_$[%£!XO1&>',
        originalStrings : '',
        singleLetters : []
    }

    Array.prototype.shuffle = function() {
        var input = this;
         
        for (var i = input.length-1; i >=0; i--) {
         
            var randomIndex = Math.floor(Math.random()*(i+1)); 
            var itemAtIndex = input[randomIndex]; 
             
            input[randomIndex] = input[i]; 
            input[i] = itemAtIndex;
        }
        return input;
    }

    function checkLength(x) {
        return Array.from(document.querySelectorAll(x)).length > 0;
    }

    function addListener(evt, fx) {
        window.addEventListener(evt, fx);    
    }

    function changeLetter(letter) {
        if(letter.textContent != ' ') {
            letter.classList.add('is-changing');
            letter.style.animationDuration = Math.random().toFixed(2) + 's';
            
            var newChar = data.letters.substr( Math.random() * data.letters.length, 1);

            letter.textContent = newChar;
            letter.setAttribute('data-txt', newChar);
        }
    }

    function resetLetter(letter, value) {
            letter.classList.remove('is-changing');
            letter.textContent = value;
            letter.setAttribute('data-txt', value);
    }


    // divide le singole lettere delle stringhe e le wrappa in span
    function divideLetters() {

        data.target.forEach( (element, index) => {
            
            var text = element.textContent;
            var textDivided = '';

            data.originalStrings = text;

            for(var i = 0; i < text.length; i++) {
                textDivided += `<span class="el-sp el-st-${index}-span-${i}" data-txt="${text.substr(i, 1)}">${text.substr(i, 1)}</span>`;
            }

            element.innerHTML = textDivided;
        }); 
        data.singleLetters = document.querySelectorAll('.el-sp');
    }

    // changes letters
    function changeLetters() {
        if(data.isScrolling) {
            data.singleLetters.forEach(function(el, index){
                changeLetter(el);
            });
        }

        setTimeout(changeLetters, 10);
    }

    // reset to initial letters
    function resetLetters() {

        var randomArray = [];  
        for(var i = 0; i < data.singleLetters.length;i++) {
            randomArray.push(i);
        }

        randomArray.shuffle();

        randomArray.forEach(function(el, index){

            setTimeout(function(){
                resetLetter(data.singleLetters[el], data.originalStrings.substring(el, el + 1));
            }, (index * 20 * (Math.random() * 5))).toFixed(2);
                
        });
    }

    // event listener sullo scroll
    function updateScrollState() {
        clearTimeout(delay);
        data.isScrolling = true;
        
        var delay = setTimeout(function() {
            data.isScrolling = false;
            resetLetters();
        }, 300);
    };

    return {
        init: function(selector){

            // controllo che ci siano stringhe su cui agire
            if(checkLength(selector)) {

                // salvo le stringhe
                data.target = Array.from(document.querySelectorAll(selector));
                
                // divido le singole stringhe in lettere
                divideLetters();

                // lancio la funzione che si ripete
                changeLetters();

                // aggiungo il listener allo scroll
                addListener('scroll', updateScrollState);

            }
        }
    }

})();

stringRandom.init('.el-st');
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.