Skip to content

Instantly share code, notes, and snippets.

@aldoyh
Last active July 23, 2025 07:17
Show Gist options
  • Save aldoyh/e0ff558a38e5d16391c63dd379511fd8 to your computer and use it in GitHub Desktop.
Save aldoyh/e0ff558a38e5d16391c63dd379511fd8 to your computer and use it in GitHub Desktop.
محيط الخيال
<div class="spiral-wrapper">
<svg viewBox="0 0 800 800" class="spiral-svg" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<path id="spiralPath" fill="none" />
</defs>
<text font-size="20" fill="white" opacity="1">
<textPath id="spiralText1" href="#spiralPath" startOffset="0%">
محيط من الخيال والحياة والحب • محيط من الخيال والحياة والحب • محيط من الخيال والحياة والحب •
</textPath>
</text>
<text font-size="20" fill="white" opacity="0.5">
<textPath id="spiralText2" href="#spiralPath" startOffset="-3%">
محيط من الخيال والحياة والحب • محيط من الخيال والحياة والحب • محيط من الخيال والحياة والحب •
</textPath>
</text>
<text font-size="20" fill="white" opacity="0.2">
<textPath id="spiralText3" href="#spiralPath" startOffset="-6%">
محيط من الخيال والحياة والحب • محيط من الخيال والحياة والحب • محيط من الخيال والحياة والحب • محيط من الخيال والحياة والحب • محيط من الخيال والحياة والحب • محيط من الخيال والحياة والحب •
</textPath>
</text>
</svg>
</div>
<div class="controls">
<button id="toggleBtn">⏸️ بس دخت!</button>
</div>
const textPath1 = document.getElementById("spiralText1");
const textPath2 = document.getElementById("spiralText2");
const textPath3 = document.getElementById("spiralText3");
const spiralPath = document.getElementById("spiralPath");
const spiralSVG = document.querySelector(".spiral-svg");
const toggleBtn = document.getElementById("toggleBtn");
let isPlaying = true;
let lastTime = null;
let offset = 0;
function generateSpiralPath(cx, cy, a, b, turns, pointsPerTurn = 400) {
let d = `M${cx},${cy}`;
const totalPoints = turns * pointsPerTurn;
for (let i = 0; i < totalPoints; i++) {
const theta = i * (2 * Math.PI / pointsPerTurn);
const r = a + b * theta;
const x = cx + r * Math.cos(theta);
const y = cy + r * Math.sin(theta);
d += ` L${x},${y}`;
}
return d;
}
function centerSpiral() {
const width = window.innerWidth;
const height = window.innerHeight;
const cx = width / 2;
const cy = height / 2;
spiralSVG.setAttribute("viewBox", `0 0 ${width} ${height}`);
const spiralD = generateSpiralPath(cx, cy, 0, 6, 20);
spiralPath.setAttribute("d", spiralD);
}
centerSpiral();
window.addEventListener("resize", centerSpiral);
function animateText(timestamp) {
if (!lastTime) lastTime = timestamp;
const delta = timestamp - lastTime;
lastTime = timestamp;
if (isPlaying) {
offset += delta * 0.0005;
if (offset > 100) offset -= 100;
}
textPath1.setAttribute("startOffset", `${offset}%`);
textPath2.setAttribute("startOffset", `${offset - 2.28}%`);
textPath3.setAttribute("startOffset", `${offset - 4.56}%`);
requestAnimationFrame(animateText);
}
requestAnimationFrame(animateText);
toggleBtn.addEventListener("click", () => {
isPlaying = !isPlaying;
toggleBtn.textContent = isPlaying ? "⏸️ Stop" : "▶️ Play";
});
html, body {
margin: 0; padding: 0; height: 100%;
background: radial-gradient(circle at center, #0f0c29, #302b63, #24243e);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
overflow: hidden;
}
body::before {
content: "";
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
background: url('https://www.transparenttextures.com/patterns/stardust.png');
opacity: 0.15;
pointer-events: none;
z-index: -1;
}
.spiral-wrapper {
width: 100vw;
height: 100vh;
}
.spiral-svg text {
fill: white;
font-weight: 500;
font-size: 22px;
filter:
drop-shadow(0 0 8px #bb88ff)
drop-shadow(0 0 15px #ff77cc);
user-select: none;
letter-spacing: 0.06em;
animation: subtleGlow 3s ease-in-out infinite alternate;
}
@keyframes subtleGlow {
0% {
filter:
drop-shadow(0 0 5px #bb88ff)
drop-shadow(0 0 10px #ff77cc);
}
100% {
filter:
drop-shadow(0 0 10px #d1a0ff)
drop-shadow(0 0 20px #ff99dd);
}
}
.controls {
position: absolute;
display: flex;
bottom: 10%;
gap: 15px;
}
button {
background: linear-gradient(135deg, #8866ff, #ff66bb);
border: none;
border-radius: 30px;
padding: 10px 25px;
font-weight: 600;
color: white;
box-shadow:
0 0 5px #ff66bb,
0 0 5px #8866ff;
cursor: pointer;
transition: box-shadow 0.3s ease, transform 0.3s ease;
user-select: none;
}
button:hover {
box-shadow:
0 0 10px #ff88cc,
0 0 20px #aa77ff;
transform: scale(1.1);
}
button:active {
transform: scale(1.75);
box-shadow:
0 0 8px #cc55aa,
0 0 15px #7755cc;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment