AW-Flow — Scramble
Буквы собираются из случайных символов слева направо — технологичный акцент для заголовков.
- Запуск
- при появлении в экране
- Параметров
- 7
- Телефоны
- свои настройки
- Код
- HTML-блок
Готовый код
Это тот же код, что сейчас работает в превью: значения подставлены из конструктора, внешние библиотеки не нужны.
<!-- AW-Flow — Scramble · класс элемента: awf-text-scramble -->
<style>
.awf-text-scramble {
--awf-duration: 600ms;
--awf-stagger: 30ms;
--awf-delay: 0ms;
--awf-noise: #7c5cff;
}
.awf-text-scramble:not(.awf-ready) { opacity: 0; }
.awf-text-scramble .awf-w { display: inline-block; white-space: nowrap; }
.awf-text-scramble .awf-p { display: inline-block; text-align: center; opacity: 0; }
.awf-text-scramble .awf-p.awf-on { opacity: 1; }
.awf-text-scramble .awf-p.awf-noise { color: var(--awf-noise); }
/* уважение к настройке «уменьшить движение» */
@media (prefers-reduced-motion: reduce) {
.awf-text-scramble, .awf-text-scramble .awf-p { opacity: 1 !important; }
}
</style>
<script>
(function () {
var CLS = 'awf-text-scramble';
var reduce = window.matchMedia && matchMedia('(prefers-reduced-motion: reduce)').matches;
function split(el, mode) {
var root = el.querySelector('.tn-atom') || el;
var parts = [];
(function walk(node) {
[].slice.call(node.childNodes).forEach(function (n) {
if (n.nodeType === 1) { if (n.tagName !== 'BR') walk(n); return; }
if (n.nodeType !== 3 || !n.textContent.trim()) return;
var frag = document.createDocumentFragment();
n.textContent.split(/(\s+)/).forEach(function (chunk) {
if (!chunk) return;
if (/^\s+$/.test(chunk)) { frag.appendChild(document.createTextNode(chunk)); return; }
var w = document.createElement('span');
w.className = 'awf-w';
if (mode === 'chars') {
Array.from(chunk).forEach(function (ch) {
var c = document.createElement('span');
c.className = 'awf-p'; c.textContent = ch; c._ch = ch;
w.appendChild(c); parts.push(c);
});
} else if (mode === 'mask') {
var inner = document.createElement('span');
inner.className = 'awf-p'; inner.textContent = chunk;
w.appendChild(inner); parts.push(inner);
} else {
w.className += ' awf-p'; w.textContent = chunk; parts.push(w);
}
frag.appendChild(w);
});
node.replaceChild(frag, n);
});
})(root);
parts.forEach(function (p, i) { p.style.setProperty('--i', i); });
return parts;
}
function num(el, name) { return parseFloat(getComputedStyle(el).getPropertyValue(name)) || 0; }
var SET = "!<>-_/[]{}=+*^?#%&";
function rnd() { return SET.charAt(Math.floor(Math.random() * SET.length)); }
// фиксируем ширину букв, чтобы строка не «прыгала» во время перебора
function measure(el) {
el._parts.forEach(function (p) { p.style.width = ''; });
el._parts.forEach(function (p) { p.style.width = p.getBoundingClientRect().width + 'px'; });
}
function prepare(el) {
el._parts = split(el, 'chars');
measure(el);
var t;
window.addEventListener('resize', function () { clearTimeout(t); t = setTimeout(function () { if (!el._raf) measure(el); }, 150); });
}
function play(el) {
el.classList.add('awf-in');
var parts = el._parts;
if (reduce) { parts.forEach(function (p) { p.classList.add('awf-on'); }); return; }
var dur = num(el, '--awf-duration'), step = num(el, '--awf-stagger'), delay = num(el, '--awf-delay');
var start = performance.now(), last = 0;
cancelAnimationFrame(el._raf);
(function tick(now) {
var t = now - start, done = true, swap = now - last > 50;
if (swap) last = now;
parts.forEach(function (p, i) {
var s = delay + i * step;
if (t < s) { done = false; return; }
if (t < s + dur) {
done = false;
p.classList.add('awf-on', 'awf-noise');
if (swap) p.textContent = rnd();
return;
}
if (p.classList.contains('awf-noise')) { p.classList.remove('awf-noise'); p.textContent = p._ch; }
p.classList.add('awf-on');
});
el._raf = done ? 0 : requestAnimationFrame(tick);
})(start);
}
function stop(el) {
// мгновенный сброс в начальное состояние, без обратной анимации
el.classList.add('awf-off');
el.classList.remove('awf-in');
cancelAnimationFrame(el._raf); el._raf = 0;
el._parts.forEach(function (p) { p.classList.remove('awf-on', 'awf-noise'); p.textContent = p._ch; });
void el.offsetWidth;
el.classList.remove('awf-off');
}
function init() {
var els = [].slice.call(document.querySelectorAll('.' + CLS)).filter(function (el) {
if (el.getAttribute('data-awf')) return false;
el.setAttribute('data-awf', '1');
prepare(el);
el.classList.add('awf-ready');
return true;
});
if (reduce) { els.forEach(play); return; }
if (!('IntersectionObserver' in window)) { els.forEach(play); return; }
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (e) {
if (e.isIntersecting) { play(e.target); io.unobserve(e.target); }
});
}, { threshold: 0.2 });
els.forEach(function (el) { io.observe(el); });
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);
else init();
})();
</script>Вставляется в HTML-блок на той же странице, где элемент с классом.
Как добавить в Tilda
Эффект работает на опубликованной странице и в режиме предпросмотра — в самом редакторе Tilda скрипты не выполняются.
- Назначьте класс элементу. В Zero Block кликните правой кнопкой по нужному элементу — текстовому и выберите пункт добавления CSS-класса (Add CSS class name). Впишите
awf-text-scramble— без точки. Класс ставится на сам элемент, не на весь артборд. - Добавьте HTML-блок. На этой же странице добавьте блок T123 «HTML-код» (проще всего найти поиском в библиотеке блоков) или элемент HTML внутри Zero Block.
- Вставьте код. Скопируйте код целиком и вставьте в этот HTML-блок, сохраните и опубликуйте страницу.
- Меняете настройки? Сначала удалите старый код этого эффекта, затем вставьте новый и снова опубликуйте страницу.
- Разные настройки — разные классы. Для второго варианта на той же странице задайте в конструкторе другой класс, например
awf-text-scramble-2, и вставьте его код отдельно.
Ещё в разделе «Текст»Весь каталог