AeThex-Engine-Core/assets/logo-designer.html

576 lines
18 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AeThex Logo Designer - Interactive</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, system-ui, sans-serif;
background: #111827;
color: #F9FAFB;
padding: 1rem;
overflow-x: hidden;
}
.container {
max-width: 1400px;
margin: 0 auto;
display: grid;
grid-template-columns: 300px 1fr 300px;
gap: 1rem;
height: calc(100vh - 2rem);
}
.panel {
background: rgba(31, 41, 55, 0.8);
border: 1px solid rgba(139, 92, 246, 0.2);
border-radius: 8px;
padding: 1rem;
overflow-y: auto;
}
h1 {
font-size: 1.5rem;
margin-bottom: 1rem;
background: linear-gradient(135deg, #8B5CF6, #06B6D4);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
h2 {
font-size: 1rem;
color: #06B6D4;
margin: 1.5rem 0 0.75rem;
border-bottom: 1px solid rgba(6, 182, 212, 0.3);
padding-bottom: 0.5rem;
}
.canvas-wrapper {
background: #1F2937;
border: 2px solid rgba(139, 92, 246, 0.3);
border-radius: 8px;
position: relative;
display: flex;
flex-direction: column;
}
canvas {
width: 100%;
height: 100%;
cursor: crosshair;
}
.control-group {
margin-bottom: 1rem;
}
label {
display: block;
color: #9CA3AF;
font-size: 0.875rem;
margin-bottom: 0.25rem;
}
input[type="range"] {
width: 100%;
height: 4px;
background: rgba(139, 92, 246, 0.2);
outline: none;
border-radius: 2px;
}
input[type="range"]::-webkit-slider-thumb {
appearance: none;
width: 16px;
height: 16px;
background: #8B5CF6;
cursor: pointer;
border-radius: 50%;
}
input[type="color"] {
width: 100%;
height: 40px;
border: 1px solid rgba(139, 92, 246, 0.3);
border-radius: 4px;
background: transparent;
cursor: pointer;
}
select {
width: 100%;
padding: 0.5rem;
background: rgba(139, 92, 246, 0.1);
border: 1px solid rgba(139, 92, 246, 0.3);
color: #F9FAFB;
border-radius: 4px;
font-size: 0.875rem;
}
button {
width: 100%;
padding: 0.75rem;
background: linear-gradient(135deg, #8B5CF6, #7C3AED);
border: none;
color: white;
border-radius: 6px;
font-weight: 600;
cursor: pointer;
margin-bottom: 0.5rem;
transition: all 0.2s;
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(139, 92, 246, 0.4);
}
button.secondary {
background: rgba(6, 182, 212, 0.2);
border: 1px solid rgba(6, 182, 212, 0.3);
}
.value-display {
float: right;
color: #06B6D4;
font-weight: 600;
}
.preset-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 0.5rem;
margin-top: 0.5rem;
}
.preset-btn {
padding: 0.5rem;
font-size: 0.75rem;
}
.toggle {
display: flex;
gap: 0.5rem;
margin-top: 0.5rem;
}
.toggle button {
flex: 1;
padding: 0.5rem;
font-size: 0.75rem;
}
.toggle button.active {
background: linear-gradient(135deg, #06B6D4, #0891B2);
}
#coordinates {
position: absolute;
top: 0.5rem;
right: 0.5rem;
background: rgba(0, 0, 0, 0.7);
padding: 0.5rem;
border-radius: 4px;
font-family: monospace;
font-size: 0.75rem;
color: #22D3EE;
}
.export-info {
background: rgba(6, 182, 212, 0.1);
border: 1px solid rgba(6, 182, 212, 0.2);
border-radius: 4px;
padding: 0.75rem;
font-size: 0.75rem;
color: #9CA3AF;
margin-top: 1rem;
}
.shape-buttons {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 0.5rem;
margin-top: 0.5rem;
}
.shape-btn {
padding: 0.5rem;
font-size: 0.75rem;
aspect-ratio: 1;
display: flex;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
<div class="container">
<!-- Left Panel - Tools -->
<div class="panel">
<h1>🎨 Logo Designer</h1>
<h2>Shape Tools</h2>
<div class="shape-buttons">
<button class="shape-btn" onclick="setTool('circle')">⭕ Circle</button>
<button class="shape-btn" onclick="setTool('line')">📏 Line</button>
<button class="shape-btn" onclick="setTool('triangle')">🔺 Triangle</button>
<button class="shape-btn" onclick="setTool('square')">⬛ Square</button>
<button class="shape-btn" onclick="setTool('hexagon')">⬡ Hex</button>
<button class="shape-btn" onclick="setTool('star')">⭐ Star</button>
</div>
<h2>Colors</h2>
<div class="control-group">
<label>Fill Color</label>
<input type="color" id="fillColor" value="#8B5CF6" onchange="updateSettings()">
</div>
<div class="control-group">
<label>Stroke Color</label>
<input type="color" id="strokeColor" value="#06B6D4" onchange="updateSettings()">
</div>
<h2>Style</h2>
<div class="control-group">
<label>Stroke Width <span class="value-display" id="strokeWidthVal">3</span></label>
<input type="range" id="strokeWidth" min="0" max="20" value="3" oninput="updateSlider(this, 'strokeWidthVal')">
</div>
<div class="control-group">
<label>Opacity <span class="value-display" id="opacityVal">100%</span></label>
<input type="range" id="opacity" min="0" max="100" value="100" oninput="updateSlider(this, 'opacityVal', '%')">
</div>
<h2>Grid</h2>
<div class="toggle">
<button id="gridBtn" class="active" onclick="toggleGrid()">Show Grid</button>
<button id="snapBtn" class="active" onclick="toggleSnap()">Snap to Grid</button>
</div>
<div class="control-group">
<label>Grid Size <span class="value-display" id="gridSizeVal">20</span></label>
<input type="range" id="gridSize" min="5" max="50" value="20" oninput="updateSlider(this, 'gridSizeVal'); redraw()">
</div>
</div>
<!-- Center Panel - Canvas -->
<div class="panel">
<div class="canvas-wrapper">
<canvas id="canvas" width="800" height="800"></canvas>
<div id="coordinates">X: 0, Y: 0</div>
</div>
<div class="toggle" style="margin-top: 1rem;">
<button onclick="undo()">↶ Undo</button>
<button onclick="clearCanvas()">🗑️ Clear</button>
<button onclick="redraw()">🔄 Redraw</button>
</div>
</div>
<!-- Right Panel - Presets & Export -->
<div class="panel">
<h1>⚡ Quick Actions</h1>
<h2>Logo Presets</h2>
<div class="preset-grid">
<button class="preset-btn" onclick="drawPreset('letterA')">Letter A</button>
<button class="preset-btn" onclick="drawPreset('hexNet')">Hex Network</button>
<button class="preset-btn" onclick="drawPreset('triangle')">Triangle</button>
<button class="preset-btn" onclick="drawPreset('circles')">Circles</button>
<button class="preset-btn" onclick="drawPreset('infinity')">Infinity</button>
<button class="preset-btn" onclick="drawPreset('nodes')">Nodes</button>
</div>
<h2>Export Options</h2>
<button onclick="exportSVG()">💾 Export as SVG</button>
<button onclick="exportPNG()" class="secondary">📸 Export as PNG</button>
<button onclick="copyToClipboard()" class="secondary">📋 Copy SVG Code</button>
<h2>Export Sizes</h2>
<div class="preset-grid">
<button class="preset-btn" onclick="exportPNG(512)">512×512</button>
<button class="preset-btn" onclick="exportPNG(256)">256×256</button>
<button class="preset-btn" onclick="exportPNG(128)">128×128</button>
<button class="preset-btn" onclick="exportPNG(64)">64×64</button>
</div>
<div class="export-info">
<strong>💡 Tips:</strong><br>
• Click and drag to draw shapes<br>
• Grid snapping helps alignment<br>
• Presets are editable after drawing<br>
• SVG is scalable, PNG for icons
</div>
<h2>SVG Code</h2>
<textarea id="svgOutput" rows="10" style="width: 100%; background: rgba(0,0,0,0.3); border: 1px solid rgba(139,92,246,0.3); color: #D1D5DB; padding: 0.5rem; border-radius: 4px; font-family: monospace; font-size: 0.75rem;"></textarea>
</div>
</div>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
let shapes = [];
let currentTool = 'circle';
let isDrawing = false;
let startX, startY;
let showGrid = true;
let snapToGrid = true;
const settings = {
fillColor: '#8B5CF6',
strokeColor: '#06B6D4',
strokeWidth: 3,
opacity: 1,
gridSize: 20
};
function updateSettings() {
settings.fillColor = document.getElementById('fillColor').value;
settings.strokeColor = document.getElementById('strokeColor').value;
settings.strokeWidth = parseInt(document.getElementById('strokeWidth').value);
settings.opacity = parseInt(document.getElementById('opacity').value) / 100;
settings.gridSize = parseInt(document.getElementById('gridSize').value);
}
function updateSlider(slider, displayId, suffix = '') {
document.getElementById(displayId).textContent = slider.value + suffix;
updateSettings();
}
function setTool(tool) {
currentTool = tool;
}
function toggleGrid() {
showGrid = !showGrid;
document.getElementById('gridBtn').classList.toggle('active');
redraw();
}
function toggleSnap() {
snapToGrid = !snapToGrid;
document.getElementById('snapBtn').classList.toggle('active');
}
function snap(coord) {
if (!snapToGrid) return coord;
return Math.round(coord / settings.gridSize) * settings.gridSize;
}
function drawGrid() {
if (!showGrid) return;
ctx.strokeStyle = 'rgba(6, 182, 212, 0.1)';
ctx.lineWidth = 0.5;
for (let x = 0; x <= canvas.width; x += settings.gridSize) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas.height);
ctx.stroke();
}
for (let y = 0; y <= canvas.height; y += settings.gridSize) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(canvas.width, y);
ctx.stroke();
}
// Center lines
ctx.strokeStyle = 'rgba(34, 211, 238, 0.3)';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(canvas.width / 2, 0);
ctx.lineTo(canvas.width / 2, canvas.height);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0, canvas.height / 2);
ctx.lineTo(canvas.width, canvas.height / 2);
ctx.stroke();
}
function drawShape(shape) {
ctx.globalAlpha = shape.opacity;
ctx.fillStyle = shape.fillColor;
ctx.strokeStyle = shape.strokeColor;
ctx.lineWidth = shape.strokeWidth;
switch(shape.type) {
case 'circle':
ctx.beginPath();
ctx.arc(shape.x, shape.y, shape.radius, 0, Math.PI * 2);
if (shape.fillColor !== 'transparent') ctx.fill();
if (shape.strokeWidth > 0) ctx.stroke();
break;
case 'line':
ctx.beginPath();
ctx.moveTo(shape.x1, shape.y1);
ctx.lineTo(shape.x2, shape.y2);
ctx.stroke();
break;
case 'triangle':
ctx.beginPath();
ctx.moveTo(shape.x, shape.y);
ctx.lineTo(shape.x - shape.size/2, shape.y + shape.size);
ctx.lineTo(shape.x + shape.size/2, shape.y + shape.size);
ctx.closePath();
if (shape.fillColor !== 'transparent') ctx.fill();
if (shape.strokeWidth > 0) ctx.stroke();
break;
}
ctx.globalAlpha = 1;
}
function redraw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawGrid();
shapes.forEach(drawShape);
generateSVG();
}
function clearCanvas() {
shapes = [];
redraw();
}
function undo() {
shapes.pop();
redraw();
}
canvas.addEventListener('mousedown', (e) => {
const rect = canvas.getBoundingClientRect();
startX = snap((e.clientX - rect.left) * (canvas.width / rect.width));
startY = snap((e.clientY - rect.top) * (canvas.height / rect.height));
isDrawing = true;
});
canvas.addEventListener('mousemove', (e) => {
const rect = canvas.getBoundingClientRect();
const x = Math.round((e.clientX - rect.left) * (canvas.width / rect.width));
const y = Math.round((e.clientY - rect.top) * (canvas.height / rect.height));
document.getElementById('coordinates').textContent = `X: ${x}, Y: ${y}`;
});
canvas.addEventListener('mouseup', (e) => {
if (!isDrawing) return;
isDrawing = false;
const rect = canvas.getBoundingClientRect();
const endX = snap((e.clientX - rect.left) * (canvas.width / rect.width));
const endY = snap((e.clientY - rect.top) * (canvas.height / rect.height));
const shape = {
...settings,
type: currentTool
};
if (currentTool === 'circle') {
const radius = Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2));
shape.x = startX;
shape.y = startY;
shape.radius = radius;
} else if (currentTool === 'line') {
shape.x1 = startX;
shape.y1 = startY;
shape.x2 = endX;
shape.y2 = endY;
} else if (currentTool === 'triangle') {
shape.x = startX;
shape.y = startY;
shape.size = Math.abs(endY - startY);
}
shapes.push(shape);
redraw();
});
function drawPreset(preset) {
clearCanvas();
const cx = canvas.width / 2;
const cy = canvas.height / 2;
if (preset === 'letterA') {
// Perfect A
shapes.push(
{type: 'line', x1: cx, y1: cy-100, x2: cx-70, y2: cy+100, strokeColor: settings' #8B5CF6', strokeWidth: 20, opacity: 1, fillColor: 'transparent'},
{type: 'line', x1: cx, y1: cy-100, x2: cx+70, y2: cy+100, strokeColor: '#8B5CF6', strokeWidth: 20, opacity: 1, fillColor: 'transparent'},
{type: 'line', x1: cx-40, y1: cy+10, x2: cx+40, y2: cy+10, strokeColor: '#06B6D4', strokeWidth: 8, opacity: 1, fillColor: 'transparent'},
{type: 'circle', x: cx-40, y: cy+10, radius: 6, fillColor: '#22D3EE', strokeWidth: 0, opacity: 1},
{type: 'circle', x: cx+40, y: cy+10, radius: 6, fillColor: '#22D3EE', strokeWidth: 0, opacity: 1}
);
} else if (preset === 'triangle') {
shapes.push(
{type: 'triangle', x: cx, y: cy-80, size: 160, fillColor: 'transparent', strokeColor: '#8B5CF6', strokeWidth: 6, opacity: 1},
{type: 'line', x1: cx-50, y1: cy+20, x2: cx+50, y2: cy+20, strokeColor: '#06B6D4', strokeWidth: 6, opacity: 1, fillColor: 'transparent'},
{type: 'circle', x: cx-50, y: cy+20, radius: 8, fillColor: '#22D3EE', strokeWidth: 0, opacity: 1},
{type: 'circle', x: cx+50, y: cy+20, radius: 8, fillColor: '#22D3EE', strokeWidth: 0, opacity: 1}
);
}
redraw();
}
function generateSVG() {
let svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" width="200" height="200">\n`;
shapes.forEach(shape => {
if (shape.type === 'circle') {
svg += ` <circle cx="${shape.x}" cy="${shape.y}" r="${shape.radius}" fill="${shape.fillColor}" stroke="${shape.strokeColor}" stroke-width="${shape.strokeWidth}" opacity="${shape.opacity}"/>\n`;
} else if (shape.type === 'line') {
svg += ` <line x1="${shape.x1}" y1="${shape.y1}" x2="${shape.x2}" y2="${shape.y2}" stroke="${shape.strokeColor}" stroke-width="${shape.strokeWidth}" opacity="${shape.opacity}"/>\n`;
}
});
svg += `</svg>`;
document.getElementById('svgOutput').value = svg;
return svg;
}
function exportSVG() {
const svg = generateSVG();
const blob = new Blob([svg], {type: 'image/svg+xml'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'aethex-logo.svg';
a.click();
}
function exportPNG(size = 512) {
const tempCanvas = document.createElement('canvas');
tempCanvas.width = size;
tempCanvas.height = size;
const tempCtx = tempCanvas.getContext('2d');
const scale = size / canvas.width;
tempCtx.scale(scale, scale);
shapes.forEach(shape => drawShape.call({ctx: tempCtx}, shape));
tempCanvas.toBlob(blob => {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `aethex-logo-${size}.png`;
a.click();
});
}
function copyToClipboard() {
const svg = document.getElementById('svgOutput').value;
navigator.clipboard.writeText(svg);
alert('SVG code copied to clipboard!');
}
// Initialize
redraw();
</script>
</body>
</html>