page-perso-chokbar/type.html
2025-11-29 13:05:50 +01:00

104 lines
No EOL
2.1 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Typewriter Upward Swing</title>
<style>
body {
font-family: monospace;
padding: 40px;
font-size: 2rem;
overflow-x: hidden;
}
#typewriter {
position: relative;
display: inline-block;
white-space: pre;
line-height: 1.4;
}
#text {
position: relative;
}
#typebar {
position: absolute;
width: 40px;
height: 800px; /* long typebar */
transform-origin: bottom center;
opacity: 0;
transition:
transform 0.12s ease-out,
opacity 0.15s ease-out;
pointer-events: none;
}
</style>
</head>
<body>
<div id="typewriter">
<span id="text"></span>
<svg id="typebar" viewBox="0 0 20 500">
<rect x="7" y="0" width="6" height="500" fill="#333"/>
</svg>
</div>
<script>
const fullText = "Typed text";
const textEl = document.getElementById("text");
const typebar = document.getElementById("typebar");
const container = document.getElementById("typewriter");
let i = 0;
function nextChar() {
if (i >= fullText.length) return;
// Measure character position
const range = document.createRange();
range.setStart(textEl.firstChild, i);
range.setEnd(textEl.firstChild, i + 1);
const charRect = range.getBoundingClientRect();
const containerRect = container.getBoundingClientRect();
// Random downward rest angle between 20° and 60°
const restAngle = 20 + Math.random() * 40;
// Position typebar's pivot slightly below the text
typebar.style.left = (charRect.left - containerRect.left) + "px";
typebar.style.top = (charRect.top - containerRect.top + 20) + "px";
// Set initial REST POSITION
typebar.style.transform = `rotate(${restAngle}deg)`;
// FADE IN before swing
// STRIKE
requestAnimationFrame(() => {
typebar.style.transform = `rotate(0deg)`;
typebar.style.opacity = 1;
// Add next character
textEl.textContent += fullText[i];
// Retract + FADE OUT
setTimeout(() => {
typebar.style.transform = `rotate(${restAngle}deg)`;
typebar.style.opacity = 0;
}, 120);
});
i++;
setTimeout(nextChar, 300);
}
nextChar();
</script>
</body>
</html>