57 lines
2.4 KiB
JavaScript
57 lines
2.4 KiB
JavaScript
/* about.js : interactions propres à la page « Qui suis-je »
|
|
- terminal : la commande se tape lettre par lettre, puis les lignes de la fiche apparaissent
|
|
- portrait : légère inclinaison 3D qui suit la souris
|
|
- parcours : la ligne de la frise se remplit selon le scroll
|
|
Mode capture ?ybstatic=1 : tout est affiché d'emblée. */
|
|
(function () {
|
|
const STATIC = document.documentElement.classList.contains('yb-static');
|
|
const TOUCH = matchMedia('(pointer: coarse)').matches;
|
|
|
|
/* Terminal tapé */
|
|
const term = document.querySelector('[data-type]');
|
|
if (term) {
|
|
const cmd = term.querySelector('[data-type-cmd]'), rows = [...term.querySelectorAll('[data-type-row]')];
|
|
const full = cmd ? cmd.textContent : '';
|
|
if (STATIC) rows.forEach(r => r.classList.add('is-typed'));
|
|
else {
|
|
if (cmd) cmd.textContent = '';
|
|
const io = new IntersectionObserver(es => es.forEach(en => {
|
|
if (!en.isIntersecting) return;
|
|
io.disconnect();
|
|
let i = 0;
|
|
const type = () => {
|
|
if (cmd && i <= full.length) { cmd.textContent = full.slice(0, i++); return setTimeout(type, 45 + Math.random() * 40); }
|
|
rows.forEach((r, k) => setTimeout(() => r.classList.add('is-typed'), 180 + k * 160));
|
|
};
|
|
setTimeout(type, 300);
|
|
}), { threshold: 0.45 });
|
|
io.observe(term);
|
|
}
|
|
}
|
|
|
|
/* Portrait incliné à la souris */
|
|
const frame = document.querySelector('[data-tilt]');
|
|
if (frame && !STATIC && !TOUCH) {
|
|
const fig = frame.parentElement;
|
|
fig.addEventListener('mousemove', e => {
|
|
const r = frame.getBoundingClientRect();
|
|
const x = (e.clientX - r.left) / r.width - 0.5, y = (e.clientY - r.top) / r.height - 0.5;
|
|
frame.style.setProperty('--ry', (x * 10).toFixed(2) + 'deg');
|
|
frame.style.setProperty('--rx', (-y * 10).toFixed(2) + 'deg');
|
|
});
|
|
fig.addEventListener('mouseleave', () => { frame.style.setProperty('--ry', '0deg'); frame.style.setProperty('--rx', '0deg'); });
|
|
}
|
|
|
|
/* Frise du parcours */
|
|
const tl = document.querySelector('[data-timeline]');
|
|
if (tl && !STATIC) {
|
|
const fill = tl.querySelector('.qs-tl__fill');
|
|
const tick = () => {
|
|
const r = tl.getBoundingClientRect();
|
|
const p = Math.max(0, Math.min(1, (innerHeight * 0.6 - r.top) / r.height));
|
|
fill.style.height = (p * 100).toFixed(1) + '%';
|
|
requestAnimationFrame(tick);
|
|
};
|
|
requestAnimationFrame(tick);
|
|
}
|
|
})();
|