Загрузка...

Генеративное арт-полотно с нейронной сеткой, интерактивное, с анимацией и управлением. Tailwind CSS.
<div id="art-project-root"
style="background-color: #E6E6E6; color: #111111; font-family: 'Helvetica Neue', Arial, sans-serif; height: 100vh; width: 100vw; overflow: hidden; display: flex; flex-direction: column; justify-content: space-between; position: relative;">
<script src="https://cdn.tailwindcss.com"></script>
<style>
.star-shape {
clip-path: polygon(50% 0%, 55% 45%, 100% 50%, 55% 55%, 50% 100%, 45% 55%, 0% 50%, 45% 45%);
animation: breathe 4s infinite ease-in-out;
}
.clover-icon div {
border-radius: 50%;
}
@keyframes breathe {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
}
</style>
<header class="flex justify-between items-center px-10 py-8 w-full z-10">
<h1 class="text-xl font-normal uppercase tracking-tighter">NEURAL-GRID_V2</h1>
<div class="text-xl font-normal">ID: 712 / 999</div>
</header>
<!-- Decorative Markers -->
<div class="absolute pointer-events-none font-mono text-[10px]" style="top: 15%; left: 10%;">PX-01</div>
<div class="absolute pointer-events-none font-mono text-[10px]" style="top: 25%; right: 25%;">VX-05</div>
<div class="absolute pointer-events-none font-mono text-[10px]" style="bottom: 25%; left: 30%;">KZ-09</div>
<div class="star-shape absolute pointer-events-none bg-[#111] w-10 h-10" style="top: 18%; left: 18%;"></div>
<div class="absolute pointer-events-none bg-[#111] rounded-full w-2 h-2" style="top: 10%; left: 15%;"></div>
<div class="absolute pointer-events-none bg-[#111] rounded-full w-2 h-2" style="bottom: 30%; right: 15%;"></div>
<div class="star-shape absolute pointer-events-none bg-[#111] w-[60px] h-[60px]" style="bottom: 35%; right: 20%;">
</div>
<div class="absolute bottom-[120px] left-10 w-[100px] h-[50px] bg-[#111] rounded-t-full z-0"></div>
<div class="absolute top-[20%] right-[10%] w-20 h-20 bg-[#111] rounded-bl-full z-0"></div>
<main class="flex-grow relative flex justify-center items-center overflow-hidden">
<canvas id="art-canvas" class="mix-blend-multiply w-[60vh] h-[60vh]"></canvas>
</main>
<footer class="w-full border-t border-[#111] grid grid-cols-4 h-[120px]">
<div class="p-6 border-r border-[#111] flex flex-col justify-between">
<p class="text-xs leading-relaxed max-w-[90%]">
Dynamic architecture of synthesized artifacts. A study on digital entropy and the geometric precision of chaos
theory.
</p>
<span class="font-mono text-[10px] uppercase tracking-wider">SEED: 0x7a...d3e1</span>
</div>
<div class="border-r border-[#111]">
<button class="w-full h-full flex items-center justify-center transition-all hover:bg-[#111] hover:text-[#E6E6E6]" onclick="regenerateArt()">
<div class="star-shape w-6 h-6 bg-current border border-[#111]"></div>
</button>
</div>
<div class="border-r border-[#111]">
<button class="w-full h-full flex items-center justify-center transition-all hover:bg-[#111] hover:text-[#E6E6E6]" onclick="toggleAnimation()">
<div class="clover-icon grid grid-cols-2 gap-[2px] w-6 h-6">
<div class="bg-current w-full h-full"></div><div class="bg-current w-full h-full"></div>
<div class="bg-current w-full h-full"></div><div class="bg-current w-full h-full"></div>
</div>
</button>
</div>
<div class="p-6 flex flex-col justify-between">
<div class="font-mono text-[10px] uppercase tracking-wider">COST: 15.5 SOL</div>
<button class="font-bold text-lg uppercase flex justify-between items-end hover:underline">
<span>COLLECT ARTIFACT</span>
<span>→</span>
</button>
</div>
</footer>
<script>
(function() {
const canvas = document.getElementById('art-canvas');
const ctx = canvas.getContext('2d');
let width, height, animationId, isAnimating = true;
let rows = 45, cols = 45, grid = [];
function resize() {
const dpr = window.devicePixelRatio || 1;
const rect = canvas.getBoundingClientRect();
canvas.width = rect.width * dpr;
canvas.height = rect.height * dpr;
ctx.scale(dpr, dpr);
width = rect.width;
height = rect.height;
initGrid();
}
class Cell {
constructor(x, y, w, h) {
this.x = x; this.y = y; this.w = w; this.h = h;
this.angle = Math.random() * Math.PI * 2;
this.offset = 0;
this.type = Math.random() > 0.85 ? 'solid' : 'wire';
}
update(time) {
this.angle += Math.cos(time + this.y * 0.01) * 0.015;
if (Math.random() > 0.995) this.offset = (Math.random() - 0.5) * 40;
else this.offset *= 0.92;
}
draw(ctx) {
ctx.save();
ctx.translate(this.x + this.w/2 + this.offset, this.y + this.h/2);
ctx.rotate(this.angle);
ctx.strokeStyle = '#111';
ctx.fillStyle = '#111';
ctx.beginPath();
if (this.type === 'wire') {
ctx.ellipse(0, 0, this.w/2, this.h/10, 0, 0, Math.PI*2);
ctx.stroke();
ctx.moveTo(0, -this.h/2); ctx.lineTo(0, this.h/2); ctx.stroke();
} else {
ctx.fillRect(-this.w/2, -this.h/10, this.w, this.h/5);
}
ctx.restore();
}
}
function initGrid() {
grid = [];
const cellW = width / cols;
const cellH = height / rows;
for (let y = 0; y < rows; y++) {
for (let x = 0; x < cols; x++) {
const dist = Math.sqrt(Math.pow((x*cellW) - width/2, 2) + Math.pow((y*cellH) - height/2, 2));
if (dist < width * 0.42) grid.push(new Cell(x * cellW, y * cellH, cellW, cellH));
}
}
}
function animate(time) {
if (!isAnimating) return;
ctx.clearRect(0, 0, width, height);
ctx.strokeStyle = 'rgba(17, 17, 17, 0.08)';
ctx.beginPath(); ctx.arc(width/2, height/2, width*0.4, 0, Math.PI*2); ctx.stroke();
grid.forEach(cell => { cell.update(time * 0.001); cell.draw(ctx); });
animationId = requestAnimationFrame(animate);
}
window.regenerateArt = () => { initGrid(); };
window.toggleAnimation = () => { isAnimating = !isAnimating; if (isAnimating) animate(performance.now()); };
window.addEventListener('resize', resize);
resize();
animate(performance.now());
})();
</script>
</div>