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...