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>