eoi / index.html
madansa7's picture
Add 2 files
a8756e2 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Neon Mandala Creator</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
body {
background-color: #0a0a1a;
color: white;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 1rem;
}
canvas {
background-color: #0a0a0a !important;
border: 2px solid #333;
border-radius: 12px;
box-shadow: 0 0 30px rgba(0, 150, 255, 0.2);
max-width: 100%;
height: auto;
display: block;
}
.color {
width: 30px;
height: 30px;
border-radius: 50%;
cursor: pointer;
transition: all 0.3s;
position: relative;
overflow: hidden;
box-shadow: 0 0 5px currentColor;
}
.color::after {
content: '';
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
background: currentColor;
opacity: 0.3;
filter: blur(5px);
z-index: -1;
}
.color:hover {
transform: scale(1.15);
box-shadow: 0 0 15px currentColor;
}
.symmetry-shape {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-radius: 6px;
background-color: #1a1a2e;
border: 1px solid #2a2a4a;
transition: all 0.2s;
color: #6a6a8a;
}
.symmetry-shape:hover, .symmetry-shape.active {
background-color: #3b82f6;
color: white;
transform: scale(1.05);
box-shadow: 0 0 10px rgba(59, 130, 246, 0.5);
}
.tool-btn {
padding: 10px 16px;
border-radius: 8px;
background-color: #1a1a2e;
border: 1px solid #2a2a4a;
cursor: pointer;
transition: all 0.2s;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
color: white !important;
}
.tool-btn:hover {
background-color: #3b82f6;
color: white;
box-shadow: 0 0 10px rgba(59, 130, 246, 0.5);
}
.sidebar {
background-color: #16213e;
border: 1px solid #2a3a6a;
box-shadow: 0 0 20px rgba(0, 100, 255, 0.2);
border-radius: 12px;
}
.title {
color: white;
font-weight: 600;
font-size: 1.5rem;
background: linear-gradient(90deg, #3b82f6, #8b5cf6);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
.section-title {
color: #e2e8f0;
font-weight: 500;
font-size: 1rem;
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 8px;
}
.section-title i {
color: #3b82f6;
}
.back-link {
font-family: 'Arial', sans-serif;
font-weight: bold;
font-size: 1.2rem;
text-decoration: none;
color: #00ffff;
text-shadow: 0 0 5px #00ffff, 0 0 10px #00ffff;
margin-bottom: 20px;
transition: all 0.3s;
display: inline-block;
padding: 5px 15px;
border-radius: 5px;
background: rgba(0, 255, 255, 0.1);
border: 1px solid rgba(0, 255, 255, 0.3);
}
.back-link:hover {
text-shadow: 0 0 10px #00ffff, 0 0 20px #00ffff;
transform: scale(1.05);
background: rgba(0, 255, 255, 0.2);
}
@media (max-width: 768px) {
.flex-col-on-mobile {
flex-direction: column;
}
canvas {
width: 100%;
height: 300px;
}
.sidebar {
width: 100%;
}
.action-buttons {
flex-direction: row !important;
justify-content: space-between;
}
.tool-btn {
width: 48%;
}
}
</style>
</head>
<body>
<a href="https://niftytechfinds.com" class="back-link">
<i class="fas fa-arrow-left"></i> Return to Niftytechfinds
</a>
<div class="flex flex-col md:flex-row gap-6 w-full max-w-6xl flex-col-on-mobile">
<!-- Canvas -->
<div class="flex-1 flex justify-center">
<canvas id="canvas" width="600" height="600"></canvas>
</div>
<!-- Right Sidebar -->
<div class="w-full md:w-80 sidebar p-6 flex flex-col gap-6">
<div class="flex items-center gap-3 mb-4">
<i class="fas fa-magic text-2xl text-blue-400"></i>
<h2 class="title">Neon Mandala Creator</h2>
</div>
<!-- Color Picker -->
<div>
<h3 class="section-title">
<i class="fas fa-palette"></i>
Neon Colors
</h3>
<div class="grid grid-cols-4 gap-3">
<div class="color" style="color: #ff00ff; background-color: #ff00ff;" data-color="#ff00ff" title="Electric Pink"></div>
<div class="color" style="color: #00ffff; background-color: #00ffff;" data-color="#00ffff" title="Cyan Burst"></div>
<div class="color" style="color: #ff5500; background-color: #ff5500;" data-color="#ff5500" title="Neon Orange"></div>
<div class="color" style="color: #55ff00; background-color: #55ff00;" data-color="#55ff00" title="Lime Zap"></div>
<div class="color" style="color: #ff00aa; background-color: #ff00aa;" data-color="#ff00aa" title="Pink Pulse"></div>
<div class="color" style="color: #aa00ff; background-color: #aa00ff;" data-color="#aa00ff" title="Purple Haze"></div>
<div class="color" style="color: #00ffaa; background-color: #00ffaa;" data-color="#00ffaa" title="Mint Flash"></div>
<div class="color" style="color: #ffaa00; background-color: #ffaa00;" data-color="#ffaa00" title="Amber Glow"></div>
<div class="color" style="color: #ff0055; background-color: #ff0055;" data-color="#ff0055" title="Ruby Beam"></div>
<div class="color" style="color: #5500ff; background-color: #5500ff;" data-color="#5500ff" title="Royal Beam"></div>
<div class="color" style="color: #00ff55; background-color: #00ff55;" data-color="#00ff55" title="Emerald Shock"></div>
<div class="color" style="color: #ff55ff; background-color: #ff55ff;" data-color="#ff55ff" title="Magenta Blast"></div>
</div>
<div class="mt-4">
<h3 class="section-title">
<i class="fas fa-eyedropper"></i>
Custom Color
</h3>
<input type="color" id="customColor" value="#ffff00" class="w-full h-10 cursor-pointer rounded-lg border border-[#2a3a6a] bg-[#1a1a2e]">
</div>
</div>
<!-- Brush Size -->
<div>
<h3 class="section-title">
<i class="fas fa-paint-brush"></i>
Brush Size
</h3>
<input type="range" min="1" max="20" value="4" id="brushSize" class="w-full mb-2 accent-[#3b82f6]">
<div class="flex justify-between text-sm text-gray-400">
<span>Small</span>
<span>Large</span>
</div>
</div>
<!-- Symmetry Shapes -->
<div>
<h3 class="section-title">
<i class="fas fa-shapes"></i>
Symmetry
</h3>
<div class="grid grid-cols-3 gap-3">
<div class="symmetry-shape" data-symmetry="4" title="4-fold">
<i class="fas fa-square"></i>
</div>
<div class="symmetry-shape" data-symmetry="6" title="6-fold">
<i class="fas fa-hexagon"></i>
</div>
<div class="symmetry-shape" data-symmetry="8" title="8-fold">
<i class="fas fa-star"></i>
</div>
<div class="symmetry-shape" data-symmetry="12" title="12-fold">
<i class="fas fa-sun"></i>
</div>
<div class="symmetry-shape active" data-symmetry="16" title="16-fold">
<i class="fas fa-infinity"></i>
</div>
<div class="symmetry-shape" data-symmetry="24" title="24-fold">
<i class="fas fa-circle"></i>
</div>
</div>
</div>
<!-- Actions -->
<div class="mt-auto flex flex-col gap-3 action-buttons">
<button onclick="clearCanvas()" class="tool-btn bg-red-600 hover:bg-red-700">
<i class="fas fa-trash-alt"></i>
Clear Canvas
</button>
<button onclick="downloadCanvas()" class="tool-btn bg-blue-600 hover:bg-blue-700">
<i class="fas fa-download"></i>
Save Artwork
</button>
</div>
</div>
</div>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let drawing = false;
let brushSize = 4;
let symmetry = 16; // Default to 16-fold symmetry
let color = '#00ffff';
let prev = { x: 0, y: 0 };
const center = { x: canvas.width / 2, y: canvas.height / 2 };
// Initialize canvas with black background
function initCanvas() {
ctx.fillStyle = '#0a0a0a';
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
// Set canvas size based on device
function resizeCanvas() {
const container = canvas.parentElement;
const size = Math.min(container.clientWidth, container.clientHeight, 600);
canvas.width = size;
canvas.height = size;
center.x = canvas.width / 2;
center.y = canvas.height / 2;
initCanvas();
}
// Initial resize and initialization
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
function drawSymmetric(x, y, px, py) {
const angle = (2 * Math.PI) / symmetry;
const dx = x - center.x;
const dy = y - center.y;
const pdx = px - center.x;
const pdy = py - center.y;
ctx.save();
ctx.translate(center.x, center.y);
for (let i = 0; i < symmetry; i++) {
ctx.rotate(angle);
ctx.beginPath();
ctx.moveTo(pdx, pdy);
ctx.lineTo(dx, dy);
ctx.strokeStyle = color;
ctx.lineWidth = brushSize;
ctx.lineCap = 'round';
ctx.shadowColor = color;
ctx.shadowBlur = brushSize/2;
ctx.stroke();
}
ctx.restore();
}
// Touch support
function getPosition(e) {
if (e.type.includes('touch')) {
const touch = e.touches[0] || e.changedTouches[0];
const rect = canvas.getBoundingClientRect();
return {
x: touch.clientX - rect.left,
y: touch.clientY - rect.top
};
} else {
const rect = canvas.getBoundingClientRect();
return {
x: e.clientX - rect.left,
y: e.clientY - rect.top
};
}
}
function startDrawing(e) {
drawing = true;
prev = getPosition(e);
e.preventDefault(); // Prevent scrolling on touch devices
}
function stopDrawing() {
drawing = false;
}
function draw(e) {
if (!drawing) return;
const pos = getPosition(e);
drawSymmetric(pos.x, pos.y, prev.x, prev.y);
prev = pos;
e.preventDefault(); // Prevent scrolling on touch devices
}
// Mouse events
canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mouseup', stopDrawing);
canvas.addEventListener('mouseleave', stopDrawing);
canvas.addEventListener('mousemove', draw);
// Touch events
canvas.addEventListener('touchstart', startDrawing);
canvas.addEventListener('touchend', stopDrawing);
canvas.addEventListener('touchcancel', stopDrawing);
canvas.addEventListener('touchmove', draw);
// Color selection
document.querySelectorAll('.color').forEach(el => {
el.addEventListener('click', () => {
color = el.getAttribute('data-color');
document.getElementById('customColor').value = color;
// Show selected color feedback
document.querySelectorAll('.color').forEach(c => c.style.transform = 'scale(1)');
el.style.transform = 'scale(1.2)';
});
});
document.getElementById('customColor').addEventListener('input', e => {
color = e.target.value;
// Reset color selection when custom color is chosen
document.querySelectorAll('.color').forEach(c => c.style.transform = 'scale(1)');
});
// Brush size selection
document.getElementById('brushSize').addEventListener('input', e => {
brushSize = e.target.value;
});
// Symmetry selection
document.querySelectorAll('.symmetry-shape').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.symmetry-shape').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
symmetry = parseInt(btn.getAttribute('data-symmetry'));
});
});
function clearCanvas() {
ctx.fillStyle = '#0a0a0a';
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
function downloadCanvas() {
// Create a temporary canvas to ensure black background in download
const tempCanvas = document.createElement('canvas');
tempCanvas.width = canvas.width;
tempCanvas.height = canvas.height;
const tempCtx = tempCanvas.getContext('2d');
// Fill with black background
tempCtx.fillStyle = '#0a0a0a';
tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height);
// Draw the original canvas content
tempCtx.drawImage(canvas, 0, 0);
// Create download link
const link = document.createElement('a');
link.download = 'neon-mandala-' + new Date().toISOString().slice(0, 10) + '.png';
link.href = tempCanvas.toDataURL('image/png');
link.click();
}
// Initialize canvas on load
window.addEventListener('load', initCanvas);
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=madansa7/eoi-global" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>