June 2, 2023

Печатающийся текст

Видеоинструкция:

Блочок, в котором будет генерироваться текст

<div class="text">
</div>

Примерные стили

<style type="text/css">
@import url('https://fonts.googleapis.com/css2?family=Montserrat&display=swap');
.container {
  height: 100%;
  width: 100%;
  justify-content: center;
  align-items: center;
  display: flex;
}
.text {
  font-weight: 100;
  font-size: 14px;
  color: #FFF;
  font-family: 'Montserrat', sans-serif;
}
.dud {
  color: #757575;
}

</style>

Скрипт (вставлять в самый конец)

<script>
const phrases = [
    ['СЕЛ МЕДВЕДЬ В МАШИНУ',
        'А ТАМ АРМЯНЕ В НАРДЫ ИГРАЮТ',
],
  ['НАДЕЛ МУЖИК ШЛЯПУ',
  'А ОНА ЕМУ КАК РАЗ',
  ]
];
class TextScramble {
    constructor(el,phrases) {
        this.el = el;
        this.chars = '!<>-_\\/[]{}—=+*^?#________';
        this.update = this.update.bind(this);
        this.phrases = phrases;
        this.counter = 0;
        this.next();
    }
    setText(newText) {
        const oldText = this.el.innerText;
        const length = Math.max(oldText.length, newText.length);
        const promise = new Promise(resolve => this.resolve = resolve);
        this.queue = [];
        for (let i = 0; i < length; i++) {
            const from = oldText[i] || '';
            const to = newText[i] || '';
            const start = Math.floor(Math.random() * 40);
            const end = start + Math.floor(Math.random() * 40);
            this.queue.push({ from, to, start, end });
        }
        cancelAnimationFrame(this.frameRequest);
        this.frame = 0;
        this.update();
        return promise;
    }
    update() {
        let output = '';
        let complete = 0;
        for (let i = 0, n = this.queue.length; i < n; i++) {
            let { from, to, start, end, char } = this.queue[i];
            if (this.frame >= end) {
                complete++;
                output += to;
            } else if (this.frame >= start) {
                if (!char || Math.random() < 0.28) {
                    char = this.randomChar();
                    this.queue[i].char = char;
                }
                output += `<span class="dud">${char}</span>`;
            } else {
                output += from;
            }
        }
        this.el.innerHTML = output;
        if (complete === this.queue.length) {
            this.resolve();
        } else {
            this.frameRequest = requestAnimationFrame(this.update);
            this.frame++;
        }
    }
    randomChar() {
        return this.chars[Math.floor(Math.random() * this.chars.length)];
    }
next(){
let self = this;
    this.setText(this.phrases[this.counter]).then(() => {
        setTimeout(()=>{
            self.next()
        },800);
    });
    this.counter = (this.counter + 1) % this.phrases.length;
}
}


    const $printingTextElements = document.querySelectorAll('.text');
    for (let i=0;i<$printingTextElements.length;i++) {
        const fx = new TextScramble($printingTextElements[i],phrases[i]);

    }

</script>