Загрузка...

Интерактивный заголовок NFT с генеративным фоном из частиц. Отображает метаданные и цену. Анимирован с помощью JS и Tailwind.
<div
style="background-color: #000000; color: #ffffff; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; height: 100vh; width: 100%; overflow: hidden; position: relative; display: flex; flex-direction: column; justify-content: space-between; padding: 40px; cursor: crosshair;">
<script src="https://cdn.tailwindcss.com"></script>
<canvas id="generative-canvas" class="absolute top-0 left-0 w-full h-full z-0"></canvas>
<div class="relative z-10 pointer-events-none h-full flex flex-col justify-between">
<header class="flex justify-between items-start pointer-events-auto">
<div class="text-[14px] font-bold tracking-tighter uppercase">Collective / Series 01</div>
<div class="text-[12px] opacity-70 font-mono tracking-widest">0x99A...F244</div>
</header>
<footer class="flex flex-col lg:flex-row items-start lg:items-end justify-between pointer-events-auto gap-10">
<div class="flex flex-col">
<div class="text-[14px] font-normal flex items-center gap-2">
<span class="opacity-50">—</span> Ethereal Mesh
</div>
<div class="text-[80px] lg:text-[120px] font-bold leading-[0.9] tracking-tighter -ml-1">#88</div>
</div>
<div class="max-w-[280px] pb-3">
<p class="text-[11px] leading-relaxed opacity-90">
A study of organic movement within digital constraints.
This iteration captures the ephemeral state of matter
transitioning through a structured void.
<br><br>
<span class="font-bold">Artist: Neo_Kinetics</span>
</p>
</div>
<div class="flex items-center gap-10 lg:gap-16 pb-4">
<div class="flex gap-10 text-[12px]">
<div class="flex items-center gap-2">
<span class="text-zinc-500">hash:</span>
<span class="font-medium">v0-9172</span>
</div>
<div class="flex items-center gap-2">
<span class="text-zinc-500">status:</span>
<span class="font-medium">Live</span>
</div>
</div>
<button class="w-[50px] h-[50px] border border-white rounded-full flex items-center justify-center text-[10px] font-bold transition-all duration-300 hover:bg-white hover:text-black hover:scale-110">
0.5 ETH
</button>
</div>
</footer>
</div>
<script>
(function() {
const canvas = document.getElementById('generative-canvas');
const ctx = canvas.getContext('2d');
let width, height, particles = [];
const particleCount = 3000;
let mouse = { x: null, y: null };
function resize() {
width = window.innerWidth;
height = window.innerHeight;
canvas.width = width * window.devicePixelRatio;
canvas.height = height * window.devicePixelRatio;
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
initParticles();
}
class Particle {
constructor() { this.reset(); }
reset() {
const angle = Math.random() * Math.PI * 2;
const radius = Math.random() * (Math.min(width, height) * 0.3);
this.x = width / 2 + Math.cos(angle) * radius;
this.y = height / 2 + Math.sin(angle) * radius;
this.vx = (Math.random() - 0.5) * 0.4;
this.vy = (Math.random() - 0.5) * 0.4;
this.baseX = this.x;
this.baseY = this.y;
this.density = (Math.random() * 25) + 2;
this.size = Math.random() * 1.2 + 0.3;
}
update() {
let dx = mouse.x - this.x;
let dy = mouse.y - this.y;
let distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 200) {
let force = (200 - distance) / 200;
this.x -= (dx / distance) * force * this.density;
this.y -= (dy / distance) * force * this.density;
} else {
this.x += (this.baseX - this.x) * 0.05;
this.y += (this.baseY - this.y) * 0.05;
}
this.x += this.vx;
this.y += this.vy;
}
draw() {
ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
}
}
function initParticles() {
particles = [];
for (let i = 0; i < particleCount; i++) {
let p = new Particle();
p.y += (i % 2 === 0) ? -120 : 120;
p.baseY = p.y;
particles.push(p);
}
}
window.addEventListener('mousemove', (e) => { mouse.x = e.clientX; mouse.y = e.clientY; });
window.addEventListener('resize', resize);
function animate() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.15)';
ctx.fillRect(0, 0, width, height);
particles.forEach(p => { p.update(); p.draw(); });
requestAnimationFrame(animate);
}
resize();
animate();
})();
</script>
</div>