| <!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"> |
| |
| <div class="flex-1 flex justify-center"> |
| <canvas id="canvas" width="600" height="600"></canvas> |
| </div> |
|
|
| |
| <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> |
| |
| |
| <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> |
|
|
| |
| <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> |
|
|
| |
| <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> |
|
|
| |
| <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; |
| let color = '#00ffff'; |
| let prev = { x: 0, y: 0 }; |
| |
| const center = { x: canvas.width / 2, y: canvas.height / 2 }; |
| |
| |
| function initCanvas() { |
| ctx.fillStyle = '#0a0a0a'; |
| ctx.fillRect(0, 0, canvas.width, canvas.height); |
| } |
| |
| |
| 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(); |
| } |
| |
| |
| 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(); |
| } |
| |
| |
| 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(); |
| } |
| |
| 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(); |
| } |
| |
| |
| canvas.addEventListener('mousedown', startDrawing); |
| canvas.addEventListener('mouseup', stopDrawing); |
| canvas.addEventListener('mouseleave', stopDrawing); |
| canvas.addEventListener('mousemove', draw); |
| |
| |
| canvas.addEventListener('touchstart', startDrawing); |
| canvas.addEventListener('touchend', stopDrawing); |
| canvas.addEventListener('touchcancel', stopDrawing); |
| canvas.addEventListener('touchmove', draw); |
| |
| |
| document.querySelectorAll('.color').forEach(el => { |
| el.addEventListener('click', () => { |
| color = el.getAttribute('data-color'); |
| document.getElementById('customColor').value = color; |
| |
| 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; |
| |
| document.querySelectorAll('.color').forEach(c => c.style.transform = 'scale(1)'); |
| }); |
| |
| |
| document.getElementById('brushSize').addEventListener('input', e => { |
| brushSize = e.target.value; |
| }); |
| |
| |
| 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() { |
| |
| const tempCanvas = document.createElement('canvas'); |
| tempCanvas.width = canvas.width; |
| tempCanvas.height = canvas.height; |
| const tempCtx = tempCanvas.getContext('2d'); |
| |
| |
| tempCtx.fillStyle = '#0a0a0a'; |
| tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height); |
| |
| |
| tempCtx.drawImage(canvas, 0, 0); |
| |
| |
| const link = document.createElement('a'); |
| link.download = 'neon-mandala-' + new Date().toISOString().slice(0, 10) + '.png'; |
| link.href = tempCanvas.toDataURL('image/png'); |
| link.click(); |
| } |
| |
| |
| 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> |