- Главная: фото, факты, соцсети, форма связи, анимации - Архитектура: карточки проектов и отдельные страницы (Тихий двор, павильон, «Лофт») - Проекты: Aman's World (скриншоты, описание) и хоумлаб - Меню из config.json, шаблон новых страниц, черновики training/work/fixed - Чистый HTML/CSS/JS без сборки, шрифты и картинки локально Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
21 lines
1.1 KiB
JavaScript
21 lines
1.1 KiB
JavaScript
// Числа в карточках проекта «набегают» от нуля, когда появляются на экране. Без JS и при «уменьшить движение» остаются как есть.
|
|
(function () {
|
|
var nodes = document.querySelectorAll('[data-count]');
|
|
if (!nodes.length || !('IntersectionObserver' in window) || matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
|
var fmt = function (n, dec) { return n.toFixed(dec).replace('.', ','); };
|
|
var run = function (el) {
|
|
var raw = el.getAttribute('data-count'), end = parseFloat(raw), dec = (raw.split('.')[1] || '').length;
|
|
if (isNaN(end)) return;
|
|
var t0 = performance.now(), dur = 900;
|
|
(function step(now) {
|
|
var k = Math.min(1, (now - t0) / dur), e = 1 - Math.pow(1 - k, 3);
|
|
el.textContent = fmt(end * e, dec);
|
|
if (k < 1) requestAnimationFrame(step);
|
|
})(t0);
|
|
};
|
|
var io = new IntersectionObserver(function (items) {
|
|
items.forEach(function (it) { if (it.isIntersecting) { run(it.target); io.unobserve(it.target); } });
|
|
}, { threshold: 0.6 });
|
|
nodes.forEach(function (n) { io.observe(n); });
|
|
})();
|