Display custom toolbar with various tools and settings
by Sharxxy
HTML
<div id="toolbar">
<img src="https://via.placeholder.com/140x35?text=AquaMotion" alt="AquaMotion Logo" id="logo">
<button data-tool="pencil" class="active">✏️ Pencil</button>
<button data-tool="eraser">🩹 Eraser</button>
<button data-tool="line">➖ Line</button>
<button data-tool="rect">⬛ Rect</button>
<button data-tool="circle">⭕ Circle</button>
Color: <input type="color" id="colorPicker" value="#00bfff">
Size: <input type="range" id="brushSize" min="1" max="50" value="5">
<button id="undo">↩️ Undo</button>
<button id="redo">↪️ Redo</button>
<button id="playPause">▶️ Play</button>
FPS: <input type="number" id="fps" value="12" min="1" max="60">
Canvas W: <input type="number" id="canvasWidth" value="800" min="100" max="2000">
H: <input type="number" id="canvasHeight" value="600" min="100" max="2000">
<button id="exportAqua">💾 .Aqua</button>
<button id="exportGIF">🎞 GIF</button>
</div>
<div id="main">
<div id="canvasContainer">
<canvas id="canvas" width="800" height="600"></canvas>
</div>
<div id="sidebar">
<h3>Frames</h3>
<div id="framesList"></div>
<button id="addFrame">+ Add Frame</button>
<button id="dupFrame">Duplicate Frame</button>
<button id="delFrame">Delete Frame</button>
<h3>Audio</h3>
<input type="file" id="audioFile">
Start (s): <input type="number" id="audioStart" value="0" min="0">
Duration (s): <input type="number" id="audioDuration" value="1" min="0.1" step="0.1">
<button id="addAudio">Add to Frame</button>
</div>
</div>
CSS
body{margin:0;font-family:'Segoe UI',sans-serif;background:#031e3e;color:#fff;}
#toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:5px;padding:5px;background:linear-gradient(90deg,#0f2b5b,#1e5288);border-bottom:3px solid #4fc3f7;}
#logo{height:35px;margin-right:10px;}
button{padding:5px 10px;background:rgba(255,255,255,0.1);border:none;color:#fff;border-radius:6px;cursor:pointer;transition:0.2s;}
button.active{background:#4fc3f7;box-shadow:0 0 10px rgba(79,195,247,0.7);}
button:hover{background:rgba(255,255,255,0.2);}
input[type=color],input[type=range],input[type=number],input[type=file]{background:rgba(255,255,255,0.1);color:#fff;border:none;border-radius:4px;padding:3px;}
#main{display:flex;height:calc(100vh - 60px);}
#canvasContainer{flex:3;display:flex;justify-content:center;align-items:center;background:radial-gradient(circle,#07213f,#031e3e);overflow:hidden;border-right:3px solid #4fc3f7;}
canvas{background:radial-gradient(circle,#0c2a50,#031e3e);border:2px solid #4fc3f7;cursor:crosshair;box-shadow:0 0 20px rgba(79,195,247,0.5);}
#sidebar{flex:1;background:linear-gradient(#0c3a6b,#031e3e);padding:10px;display:flex;flex-direction:column;gap:10px;overflow-y:auto;border-left:3px solid #4fc3f7;}
#framesList .frameItem{padding:6px;background:rgba(255,255,255,0.1);border-radius:5px;cursor:pointer;margin-bottom:4px;transition:0.2s;}
#framesList .frameItem.active{background:#4fc3f7;box-shadow:0 0 10px rgba(79,195,247,0.6);}
h3{margin:5px 0;color:#4fc3f7;}
JavaScript
const canvas=document.getElementById('canvas');
const ctx=canvas.getContext('2d');
let currentTool='pencil',brushColor='#00bfff',brushSize=5,drawing=false,startPos=null;
let frames=[{strokes:[],audios:[]}],currentFrame=0,undoStack=[],redoStack=[],fps=12,playInterval=null;
const colorPicker=document.getElementById('colorPicker');
const brushSizeInput=document.getElementById('brushSize');
const fpsInput=document.getElementById('fps');
const canvasWidthInput=document.getElementById('canvasWidth');
const canvasHeightInput=document.getElementById('canvasHeight');
const framesList=document.getElementById('framesList');
const audioFileInput=document.getElementById('audioFile');
const audioStartInput=document.getElementById('audioStart');
const audioDurationInput=document.getElementById('audioDuration');
const addAudioBtn=document.getElementById('addAudio');
// --- Tools ---
document.querySelectorAll('#toolbar button[data-tool]').forEach(btn=>{
btn.onclick=()=>{currentTool=btn.dataset.tool;document.querySelectorAll('#toolbar button[data-tool]').forEach(b=>b.classList.remove('active'));btn.classList.add('active');};
});
colorPicker.onchange=e=>brushColor=e.target.value;
brushSizeInput.oninput=e=>brushSize=parseInt(e.target.value);
canvasWidthInput.onchange=()=>{canvas.width=parseInt(canvasWidthInput.value);redraw();};
canvasHeightInput.onchange=()=>{canvas.height=parseInt(canvasHeightInput.value);redraw();};
// --- Drawing ---
canvas.addEventListener('mousedown',e=>{
drawing=true;
const rect=canvas.getBoundingClientRect();
const x=e.clientX-rect.left,y=e.clientY-rect.top;
startPos={x,y};
if(currentTool==='pencil'||currentTool==='eraser'){
const stroke={type:currentTool,color:brushColor,size:brushSize,points:[{x,y}]};
frames[currentFrame].strokes.push(stroke);
undoStack.push({action:'add',stroke});
redoStack=[];
}
});
canvas.addEventListener('mousemove',e=>{
if(!drawing) return;
const...