DrawTool / index.html
namelessai's picture
Update index.html
c317bf2 verified
Raw
History Blame Contribute Delete
5.89 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Tailwind CSS (Play CDN) -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- FontAwesome -->
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css"
/>
<!-- Fabric.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/6.6.4/fabric.min.js"></script>
<!-- fabric-brushes addon -->
<script src="https://cdn.jsdelivr.net/gh/av01d/fabric-brushes@1.0/dist/fabric.brushes.min.js"></script>
</head>
<body class="h-screen flex bg-gray-100">
<!-- Layers Panel -->
<aside class="w-64 bg-white border-r p-4 flex flex-col">
<h2 class="text-xl font-semibold mb-4">Layers</h2>
<div id="layers" class="flex-1 overflow-auto space-y-2"></div>
<button id="add-layer"
class="mt-4 flex items-center justify-center px-3 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
<i class="fa fa-plus mr-2"></i>Add Layer
</button>
</aside>
<!-- Main Canvas Area -->
<main class="flex-1 flex flex-col">
<!-- Brush Toolbar -->
<div class="p-4 bg-white border-b flex space-x-4">
<button class="brush-btn" data-brush="pencil" title="Pencil">
<i class="fa fa-pencil-alt fa-lg"></i>
</button>
<button class="brush-btn" data-brush="chalk" title="Chalk">
<i class="fa fa-chalkboard fa-lg"></i>
</button>
<button class="brush-btn" data-brush="paint" title="Paint">
<i class="fa fa-paint-brush fa-lg"></i>
</button>
<button class="brush-btn" data-brush="splatter" title="Splatter">
<i class="fa fa-spray-can fa-lg"></i>
</button>
</div>
<!-- Canvas Stack -->
<div id="canvas-wrapper" class="relative flex-1 bg-white"></div>
</main>
<!-- Script -->
<script>
const layersContainer = document.getElementById('layers');
const addLayerBtn = document.getElementById('add-layer');
const canvasWrapper = document.getElementById('canvas-wrapper');
let layers = [], current = -1;
// Create a new layer
function addLayer(name='Layer') {
const id = Date.now().toString();
// Create <canvas>
const c = document.createElement('canvas');
c.id = 'canvas-' + id;
c.width = canvasWrapper.clientWidth;
c.height = canvasWrapper.clientHeight;
c.classList.add('absolute','top-0','left-0');
canvasWrapper.appendChild(c);
// Init Fabric canvas
const fc = new fabric.Canvas(c.id, {
isDrawingMode: true,
backgroundColor: 'transparent'
});
fc.freeDrawingBrush = new fabric.PencilBrush(fc); // default :contentReference[oaicite:5]{index=5}
layers.push({ id, name, el: c, fc });
selectLayer(layers.length - 1);
updateLayersUI();
}
// Refresh the layers panel
function updateLayersUI() {
layersContainer.innerHTML = '';
layers.forEach((ly, i) => {
const div = document.createElement('div');
div.className = [
'flex items-center justify-between p-2 rounded',
i===current ? 'bg-blue-100' : 'hover:bg-gray-100 cursor-pointer'
].join(' ');
div.innerHTML = `
<span>${ly.name}</span>
<div class="space-x-1">
<button onclick="moveLayer(${i},-1)"><i class="fa fa-arrow-up"></i></button>
<button onclick="moveLayer(${i},+1)"><i class="fa fa-arrow-down"></i></button>
<button onclick="removeLayer(${i})"><i class="fa fa-trash"></i></button>
</div>`;
div.addEventListener('click',()=>selectLayer(i));
layersContainer.appendChild(div);
});
// Stack canvases by index
layers.forEach((ly,i)=> {
ly.el.style.zIndex = i;
});
if(current>=0) layers[current].el.style.zIndex = layers.length;
}
// Select a layer
function selectLayer(i) {
current = i;
layers.forEach((ly,idx)=>{
ly.fc.selection = (idx===i);
});
updateLayersUI();
}
// Remove a layer
function removeLayer(i) {
canvasWrapper.removeChild(layers[i].el);
layers.splice(i,1);
if(current >= layers.length) current = layers.length -1;
updateLayersUI();
}
// Move layer up/down
function moveLayer(i, dir) {
const j = i + dir;
if(j<0||j>=layers.length) return;
[layers[i], layers[j]] = [layers[j], layers[i]];
if(current === i) current = j;
else if(current === j) current = i;
updateLayersUI();
}
// Change brush type
document.querySelectorAll('.brush-btn').forEach(btn=>{
btn.addEventListener('click',()=>{
if(current<0) return;
const f = layers[current].fc;
switch(btn.dataset.brush) {
case 'pencil':
f.freeDrawingBrush = new fabric.PencilBrush(f); break;
case 'chalk':
f.freeDrawingBrush = new fabric.SketchyBrush(f,{
width: 10, color:'#222', opacity:0.6
}); break; // Sketchy for chalk :contentReference[oaicite:6]{index=6}
case 'paint':
f.freeDrawingBrush = new fabric.RibbonBrush(f,{
width: 20, color:'#c00', opacity:0.8
}); break; // Ribbon for paint drips :contentReference[oaicite:7]{index=7}
case 'splatter':
f.freeDrawingBrush = new fabric.SpraypaintBrush(f,{
width: 30, color:'#008', opacity:0.7
}); break; // Spraypaint for splatter :contentReference[oaicite:8]{index=8}
}
});
});
// Init with one layer
window.addEventListener('DOMContentLoaded',()=> addLayer('Layer 1'));
addLayerBtn.addEventListener('click',()=>addLayer(`Layer ${layers.length+1}`));
</script>
</body>
</html>