|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>Configure X</title> |
|
|
<style> |
|
|
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap'); |
|
|
|
|
|
:root { |
|
|
--primary-color: #00ffff; |
|
|
--secondary-color: #ff00ff; |
|
|
} |
|
|
|
|
|
* { |
|
|
margin: 0; |
|
|
padding: 0; |
|
|
box-sizing: border-box; |
|
|
} |
|
|
|
|
|
body { |
|
|
font-family: 'Orbitron', sans-serif; |
|
|
background-color: #000; |
|
|
color: #fff; |
|
|
overflow: hidden; |
|
|
display: flex; |
|
|
justify-content: center; |
|
|
align-items: center; |
|
|
height: 100vh; |
|
|
} |
|
|
|
|
|
#canvas-background { |
|
|
position: fixed; |
|
|
top: 0; |
|
|
left: 0; |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
z-index: 0; |
|
|
} |
|
|
|
|
|
.container { |
|
|
text-align: center; |
|
|
position: relative; |
|
|
z-index: 2; |
|
|
} |
|
|
|
|
|
h1 { |
|
|
font-size: 5rem; |
|
|
margin-bottom: 1rem; |
|
|
text-transform: uppercase; |
|
|
letter-spacing: 10px; |
|
|
position: relative; |
|
|
display: inline-block; |
|
|
} |
|
|
|
|
|
.glitch { |
|
|
position: relative; |
|
|
} |
|
|
|
|
|
.glitch::before, |
|
|
.glitch::after { |
|
|
content: attr(data-text); |
|
|
position: absolute; |
|
|
top: 0; |
|
|
left: 0; |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
background: black; |
|
|
} |
|
|
|
|
|
.glitch::before { |
|
|
left: 2px; |
|
|
text-shadow: -2px 0 var(--primary-color); |
|
|
clip: rect(24px, 550px, 90px, 0); |
|
|
animation: glitch-anim-2 3s infinite linear alternate-reverse; |
|
|
} |
|
|
|
|
|
.glitch::after { |
|
|
left: -2px; |
|
|
text-shadow: -2px 0 var(--secondary-color); |
|
|
clip: rect(85px, 550px, 140px, 0); |
|
|
animation: glitch-anim 2.5s infinite linear alternate-reverse; |
|
|
} |
|
|
|
|
|
@keyframes glitch-anim { |
|
|
0% { |
|
|
clip: rect(95px, 9999px, 59px, 0); |
|
|
} |
|
|
20% { |
|
|
clip: rect(30px, 9999px, 77px, 0); |
|
|
} |
|
|
40% { |
|
|
clip: rect(16px, 9999px, 6px, 0); |
|
|
} |
|
|
60% { |
|
|
clip: rect(52px, 9999px, 29px, 0); |
|
|
} |
|
|
80% { |
|
|
clip: rect(97px, 9999px, 75px, 0); |
|
|
} |
|
|
100% { |
|
|
clip: rect(63px, 9999px, 81px, 0); |
|
|
} |
|
|
} |
|
|
|
|
|
@keyframes glitch-anim-2 { |
|
|
0% { |
|
|
clip: rect(56px, 9999px, 98px, 0); |
|
|
} |
|
|
20% { |
|
|
clip: rect(74px, 9999px, 3px, 0); |
|
|
} |
|
|
40% { |
|
|
clip: rect(11px, 9999px, 49px, 0); |
|
|
} |
|
|
60% { |
|
|
clip: rect(85px, 9999px, 20px, 0); |
|
|
} |
|
|
80% { |
|
|
clip: rect(35px, 9999px, 93px, 0); |
|
|
} |
|
|
100% { |
|
|
clip: rect(68px, 9999px, 42px, 0); |
|
|
} |
|
|
} |
|
|
|
|
|
.tagline { |
|
|
font-size: 1.6rem; |
|
|
margin-bottom: 3rem; |
|
|
|
|
|
text-shadow: 0 0 15px var(--primary-color); |
|
|
} |
|
|
|
|
|
.links { |
|
|
display: flex; |
|
|
justify-content: center; |
|
|
gap: 30px; |
|
|
} |
|
|
|
|
|
.link { |
|
|
position: relative; |
|
|
text-decoration: none; |
|
|
color: #fff; |
|
|
font-weight: bold; |
|
|
font-size: 1.2rem; |
|
|
padding: 15px 30px; |
|
|
overflow: hidden; |
|
|
transition: 0.5s; |
|
|
letter-spacing: 4px; |
|
|
-webkit-box-reflect: below 1px linear-gradient(transparent, #0005); |
|
|
} |
|
|
|
|
|
.link:hover { |
|
|
background: var(--primary-color); |
|
|
color: #000; |
|
|
box-shadow: 0 0 30px var(--primary-color); |
|
|
transition-delay: 0.5s; |
|
|
} |
|
|
|
|
|
.link span { |
|
|
position: absolute; |
|
|
display: block; |
|
|
} |
|
|
|
|
|
.link span:nth-child(1) { |
|
|
top: 0; |
|
|
left: -100%; |
|
|
width: 100%; |
|
|
height: 2px; |
|
|
background: linear-gradient(90deg, transparent, var(--primary-color)); |
|
|
} |
|
|
|
|
|
.link:hover span:nth-child(1) { |
|
|
left: 100%; |
|
|
transition: 0.5s; |
|
|
} |
|
|
|
|
|
.link span:nth-child(2) { |
|
|
top: -100%; |
|
|
right: 0; |
|
|
width: 2px; |
|
|
height: 100%; |
|
|
background: linear-gradient(180deg, transparent, var(--primary-color)); |
|
|
} |
|
|
|
|
|
.link:hover span:nth-child(2) { |
|
|
top: 100%; |
|
|
transition: 0.5s; |
|
|
transition-delay: 0.125s; |
|
|
} |
|
|
|
|
|
.link span:nth-child(3) { |
|
|
bottom: 0; |
|
|
right: -100%; |
|
|
width: 100%; |
|
|
height: 2px; |
|
|
background: linear-gradient(270deg, transparent, var(--primary-color)); |
|
|
} |
|
|
|
|
|
.link:hover span:nth-child(3) { |
|
|
right: 100%; |
|
|
transition: 0.5s; |
|
|
transition-delay: 0.25s; |
|
|
} |
|
|
|
|
|
.link span:nth-child(4) { |
|
|
bottom: -100%; |
|
|
left: 0; |
|
|
width: 2px; |
|
|
height: 100%; |
|
|
background: linear-gradient(360deg, transparent, var(--primary-color)); |
|
|
} |
|
|
|
|
|
.link:hover span:nth-child(4) { |
|
|
bottom: 100%; |
|
|
transition: 0.5s; |
|
|
transition-delay: 0.375s; |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
<canvas id="canvas-background"></canvas> |
|
|
<div class="container"> |
|
|
<h1 class="glitch" data-text="Configure X">Configure X</h1> |
|
|
<p class="tagline">Open Group Foundation</p> |
|
|
<div class="links"> |
|
|
<a href="#about" class="link"> |
|
|
<span></span> |
|
|
<span></span> |
|
|
<span></span> |
|
|
<span></span> |
|
|
About |
|
|
</a> |
|
|
<a href="#projects" class="link"> |
|
|
<span></span> |
|
|
<span></span> |
|
|
<span></span> |
|
|
<span></span> |
|
|
Projects |
|
|
</a> |
|
|
<a href="#join" class="link"> |
|
|
<span></span> |
|
|
<span></span> |
|
|
<span></span> |
|
|
<span></span> |
|
|
Join |
|
|
</a> |
|
|
</div> |
|
|
</div> |
|
|
<script> |
|
|
|
|
|
const canvas = document.getElementById('canvas-background'); |
|
|
const ctx = canvas.getContext('2d'); |
|
|
canvas.width = window.innerWidth; |
|
|
canvas.height = window.innerHeight; |
|
|
|
|
|
|
|
|
class Particle { |
|
|
constructor(x, y) { |
|
|
this.x = x; |
|
|
this.y = y; |
|
|
this.size = Math.random() * 1 + 1; |
|
|
this.baseSize = this.size; |
|
|
this.speedX = Math.random() * 2 - 1; |
|
|
this.speedY = Math.random() * 2 - 1; |
|
|
} |
|
|
|
|
|
update() { |
|
|
this.x += this.speedX; |
|
|
this.y += this.speedY; |
|
|
|
|
|
|
|
|
if (this.x < 0 || this.x > canvas.width) this.speedX *= -1; |
|
|
if (this.y < 0 || this.y > canvas.height) this.speedY *= -1; |
|
|
|
|
|
|
|
|
this.size = this.baseSize + Math.sin(Date.now() * 0.01) * 0.5; |
|
|
} |
|
|
|
|
|
draw() { |
|
|
ctx.fillStyle = 'rgba(0, 255, 255, 0.7)'; |
|
|
ctx.beginPath(); |
|
|
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2); |
|
|
ctx.fill(); |
|
|
} |
|
|
} |
|
|
|
|
|
let particleArray = []; |
|
|
let mouse = { |
|
|
x: null, |
|
|
y: null, |
|
|
radius: 150 |
|
|
} |
|
|
|
|
|
window.addEventListener('mousemove', function(event) { |
|
|
mouse.x = event.x; |
|
|
mouse.y = event.y; |
|
|
}); |
|
|
|
|
|
function init() { |
|
|
particleArray = []; |
|
|
for (let i = 0; i < 100; i++) { |
|
|
let x = Math.random() * canvas.width; |
|
|
let y = Math.random() * canvas.height; |
|
|
particleArray.push(new Particle(x, y)); |
|
|
} |
|
|
} |
|
|
|
|
|
function animate() { |
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height); |
|
|
for (let i = 0; i < particleArray.length; i++) { |
|
|
particleArray[i].update(); |
|
|
particleArray[i].draw(); |
|
|
} |
|
|
connect(); |
|
|
requestAnimationFrame(animate); |
|
|
} |
|
|
|
|
|
function connect() { |
|
|
let opacityValue = 1; |
|
|
for (let a = 0; a < particleArray.length; a++) { |
|
|
for (let b = a; b < particleArray.length; b++) { |
|
|
let dx = particleArray[a].x - particleArray[b].x; |
|
|
let dy = particleArray[a].y - particleArray[b].y; |
|
|
let distance = Math.sqrt(dx * dx + dy * dy); |
|
|
|
|
|
if (distance < 100) { |
|
|
opacityValue = 1 - (distance / 100); |
|
|
ctx.strokeStyle = `rgba(0, 255, 255, ${opacityValue})`; |
|
|
ctx.lineWidth = 1; |
|
|
ctx.beginPath(); |
|
|
ctx.moveTo(particleArray[a].x, particleArray[a].y); |
|
|
ctx.lineTo(particleArray[b].x, particleArray[b].y); |
|
|
ctx.stroke(); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (mouse.x !== null && mouse.y !== null) { |
|
|
for (let i = 0; i < particleArray.length; i++) { |
|
|
let dx = mouse.x - particleArray[i].x; |
|
|
let dy = mouse.y - particleArray[i].y; |
|
|
let distance = Math.sqrt(dx * dx + dy * dy); |
|
|
|
|
|
if (distance < mouse.radius) { |
|
|
opacityValue = 1 - (distance / mouse.radius); |
|
|
ctx.strokeStyle = `rgba(0, 255, 255, ${opacityValue})`; |
|
|
ctx.lineWidth = 1; |
|
|
ctx.beginPath(); |
|
|
ctx.moveTo(mouse.x, mouse.y); |
|
|
ctx.lineTo(particleArray[i].x, particleArray[i].y); |
|
|
ctx.stroke(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
window.addEventListener('resize', function() { |
|
|
canvas.width = window.innerWidth; |
|
|
canvas.height = window.innerHeight; |
|
|
init(); |
|
|
}); |
|
|
|
|
|
init(); |
|
|
animate(); |
|
|
|
|
|
|
|
|
function glitchEffect() { |
|
|
const glitch = document.querySelector('.glitch'); |
|
|
const glitchText = glitch.textContent; |
|
|
|
|
|
setInterval(() => { |
|
|
const glitchChars = '!<>-_\\/[]{}—=+*^?#________'; |
|
|
let newText = ''; |
|
|
for(let i = 0; i < glitchText.length; i++) { |
|
|
if(Math.random() > 0.9) { |
|
|
newText += glitchChars[Math.floor(Math.random() * glitchChars.length)]; |
|
|
} else { |
|
|
newText += glitchText[i]; |
|
|
} |
|
|
} |
|
|
glitch.setAttribute('data-text', newText); |
|
|
|
|
|
setTimeout(() => { |
|
|
glitch.setAttribute('data-text', glitchText); |
|
|
}, 50); |
|
|
}, 2000); |
|
|
} |
|
|
|
|
|
glitchEffect(); |
|
|
</script> |
|
|
</body> |
|
|
</html> |