namelessai commited on
Commit
c317bf2
·
verified ·
1 Parent(s): 91bc898

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +145 -214
index.html CHANGED
@@ -1,231 +1,162 @@
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Artisan Canvas - Advanced Drawing Tool</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
- <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.0/fabric.min.js"></script>
 
 
 
 
 
 
10
  </head>
11
- <body class="bg-slate-100 h-screen flex">
12
- <!-- Tools Panel -->
13
- <div class="w-64 bg-slate-800 p-4 flex flex-col gap-4">
14
- <div class="text-white mb-4">
15
- <h1 class="text-xl font-bold">Artisan Canvas</h1>
16
- <p class="text-sm text-slate-400">Advanced Drawing Tool</p>
17
- </div>
18
-
19
- <!-- Brush Selection -->
20
- <div class="space-y-2">
21
- <label class="text-white text-sm">Brushes</label>
22
- <div class="grid grid-cols-2 gap-2">
23
- <button onclick="setBrush('pencil')" class="tool-btn">
24
- <i class="fas fa-pencil"></i>
25
- </button>
26
- <button onclick="setBrush('chalk')" class="tool-btn">
27
- <i class="fas fa-chalkboard"></i>
28
- </button>
29
- <button onclick="setBrush('paint')" class="tool-btn">
30
- <i class="fas fa-paint-brush"></i>
31
- </button>
32
- <button onclick="setBrush('splatter')" class="tool-btn">
33
- <i class="fas fa-spray-can"></i>
34
- </button>
35
- </div>
36
- </div>
37
-
38
- <!-- Color Picker -->
39
- <div class="space-y-2">
40
- <label class="text-white text-sm">Color</label>
41
- <input type="color" id="colorPicker"
42
- class="w-full h-10 rounded cursor-pointer">
43
- </div>
44
-
45
- <!-- Brush Size -->
46
- <div class="space-y-2">
47
- <label class="text-white text-sm">Size</label>
48
- <input type="range" id="brushSize" min="1" max="100" value="10"
49
- class="w-full range-sm">
50
- </div>
51
-
52
- <!-- Tools -->
53
- <div class="space-y-2">
54
- <label class="text-white text-sm">Tools</label>
55
- <div class="grid grid-cols-2 gap-2">
56
- <button onclick="toggleEraser()" class="tool-btn">
57
- <i class="fas fa-eraser"></i>
58
- </button>
59
- <button onclick="clearCanvas()" class="tool-btn">
60
- <i class="fas fa-trash"></i>
61
- </button>
62
- </div>
63
- </div>
64
- </div>
65
-
66
- <!-- Main Canvas -->
67
- <div class="flex-1 p-4 relative">
68
- <canvas id="mainCanvas" class="bg-white rounded-lg shadow-xl"></canvas>
69
  </div>
70
 
71
- <!-- Layers Panel -->
72
- <div class="w-64 bg-slate-800 p-4 flex flex-col gap-2">
73
- <div class="text-white mb-2">
74
- <h2 class="text-lg font-semibold">Layers</h2>
75
- </div>
76
- <div id="layerList" class="space-y-2 flex-1 overflow-y-auto">
77
- <!-- Layers will be dynamically added here -->
78
- </div>
79
- <button onclick="addLayer()"
80
- class="mt-4 bg-slate-700 text-white p-2 rounded hover:bg-slate-600">
81
- <i class="fas fa-plus mr-2"></i>New Layer
82
- </button>
83
- </div>
84
-
85
- <script>
86
- let canvas;
87
- let currentBrush = 'pencil';
88
- let isErasing = false;
89
- let layers = [];
90
- let activeLayer = null;
91
-
92
- // Initialize canvas
93
- function initCanvas() {
94
- canvas = new fabric.Canvas('mainCanvas', {
95
  isDrawingMode: true,
96
- width: 800,
97
- height: 600
98
- });
99
- setBrush('pencil');
100
- addLayer(); // Create initial layer
101
- }
102
 
103
- // Brush configurations
104
- function setBrush(type) {
105
- currentBrush = type;
106
- canvas.freeDrawingBrush = new fabric[`${type.charAt(0).toUpperCase() + type.slice(1)}Brush`](canvas);
107
-
108
- switch(type) {
109
- case 'chalk':
110
- canvas.freeDrawingBrush.width = 10;
111
- canvas.freeDrawingBrush.color = document.getElementById('colorPicker').value;
112
- canvas.freeDrawingBrush.shadow = new fabric.Shadow({
113
- blur: 5,
114
- offsetX: 2,
115
- offsetY: 2,
116
- color: 'rgba(0,0,0,0.3)'
117
- });
118
- break;
119
-
120
- case 'paint':
121
- canvas.freeDrawingBrush.width = 20;
122
- canvas.freeDrawingBrush.color = document.getElementById('colorPicker').value;
123
- canvas.freeDrawingBrush.strokeLineCap = 'round';
124
- canvas.freeDrawingBrush.strokeLineJoin = 'round';
125
- canvas.freeDrawingBrush.shadow = new fabric.Shadow({
126
- blur: 10,
127
- color: document.getElementById('colorPicker').value
128
- });
129
- break;
130
-
131
- case 'splatter':
132
- canvas.freeDrawingBrush.width = 15;
133
- canvas.freeDrawingBrush.color = document.getElementById('colorPicker').value;
134
- canvas.freeDrawingBrush.strokeLineCap = 'round';
135
- canvas.freeDrawingBrush.strokeLineJoin = 'round';
136
- canvas.freeDrawingBrush.shadow = new fabric.Shadow({
137
- blur: 15,
138
- color: document.getElementById('colorPicker').value
139
- });
140
- break;
141
-
142
- default: // Pencil
143
- canvas.freeDrawingBrush.width = 5;
144
- canvas.freeDrawingBrush.color = document.getElementById('colorPicker').value;
145
- canvas.freeDrawingBrush.strokeLineCap = 'round';
146
- canvas.freeDrawingBrush.strokeLineJoin = 'round';
147
  }
148
- }
149
-
150
- // Layer management
151
- function addLayer() {
152
- const layerId = Date.now();
153
- const newLayer = {
154
- id: layerId,
155
- name: `Layer ${layers.length + 1}`,
156
- visible: true,
157
- canvas: new fabric.Canvas('mainCanvas') // In real implementation, manage multiple canvases
158
- };
159
- layers.push(newLayer);
160
- activeLayer = layerId;
161
- updateLayerList();
162
- }
163
 
164
- function toggleLayerVisibility(layerId) {
165
- const layer = layers.find(l => l.id === layerId);
166
- layer.visible = !layer.visible;
167
- updateLayerList();
168
- }
169
-
170
- function updateLayerList() {
171
- const layerList = document.getElementById('layerList');
172
- layerList.innerHTML = layers.map(layer => `
173
- <div class="flex items-center justify-between bg-slate-700 p-2 rounded ${activeLayer === layer.id ? 'ring-2 ring-blue-400' : ''}">
174
- <span class="text-white text-sm">${layer.name}</span>
175
- <div class="flex gap-2">
176
- <button onclick="toggleLayerVisibility(${layer.id})" class="text-slate-300 hover:text-white">
177
- <i class="fas ${layer.visible ? 'fa-eye' : 'fa-eye-slash'}"></i>
178
- </button>
179
- <button class="text-red-400 hover:text-red-300">
180
- <i class="fas fa-trash"></i>
181
- </button>
182
- </div>
183
- </div>
184
- `).join('');
185
- }
186
-
187
- // Tools
188
- function toggleEraser() {
189
- isErasing = !isErasing;
190
- canvas.freeDrawingBrush.color = isErasing ? '#ffffff' : document.getElementById('colorPicker').value;
191
- }
192
-
193
- function clearCanvas() {
194
- canvas.clear();
195
- }
196
-
197
- // Event Listeners
198
- document.getElementById('colorPicker').addEventListener('input', (e) => {
199
- canvas.freeDrawingBrush.color = e.target.value;
200
- });
201
-
202
- document.getElementById('brushSize').addEventListener('input', (e) => {
203
- canvas.freeDrawingBrush.width = parseInt(e.target.value);
204
- });
205
-
206
- // Initialize
207
- window.onload = initCanvas;
208
- </script>
209
 
210
- <style>
211
- .tool-btn {
212
- @apply p-3 bg-slate-700 text-white rounded hover:bg-slate-600 transition-colors;
213
- }
 
 
 
 
214
 
215
- .range-sm::-webkit-slider-thumb {
216
- @apply w-4 h-4 bg-blue-500 rounded-full cursor-pointer;
217
- }
 
 
 
 
218
 
219
- #mainCanvas {
220
- border: 2px solid #e2e8f0;
221
- }
 
 
 
 
 
 
222
 
223
- .fabric-canvas {
224
- position: absolute;
225
- top: 0;
226
- left: 0;
227
- }
228
- </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
 
 
 
 
 
230
  </body>
231
  </html>
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <!-- Tailwind CSS (Play CDN) -->
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <!-- FontAwesome -->
9
+ <link rel="stylesheet"
10
+ href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css"
11
+ />
12
+ <!-- Fabric.js -->
13
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/6.6.4/fabric.min.js"></script>
14
+ <!-- fabric-brushes addon -->
15
+ <script src="https://cdn.jsdelivr.net/gh/av01d/fabric-brushes@1.0/dist/fabric.brushes.min.js"></script>
16
  </head>
17
+ <body class="h-screen flex bg-gray-100">
18
+ <!-- Layers Panel -->
19
+ <aside class="w-64 bg-white border-r p-4 flex flex-col">
20
+ <h2 class="text-xl font-semibold mb-4">Layers</h2>
21
+ <div id="layers" class="flex-1 overflow-auto space-y-2"></div>
22
+ <button id="add-layer"
23
+ class="mt-4 flex items-center justify-center px-3 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
24
+ <i class="fa fa-plus mr-2"></i>Add Layer
25
+ </button>
26
+ </aside>
27
+
28
+ <!-- Main Canvas Area -->
29
+ <main class="flex-1 flex flex-col">
30
+ <!-- Brush Toolbar -->
31
+ <div class="p-4 bg-white border-b flex space-x-4">
32
+ <button class="brush-btn" data-brush="pencil" title="Pencil">
33
+ <i class="fa fa-pencil-alt fa-lg"></i>
34
+ </button>
35
+ <button class="brush-btn" data-brush="chalk" title="Chalk">
36
+ <i class="fa fa-chalkboard fa-lg"></i>
37
+ </button>
38
+ <button class="brush-btn" data-brush="paint" title="Paint">
39
+ <i class="fa fa-paint-brush fa-lg"></i>
40
+ </button>
41
+ <button class="brush-btn" data-brush="splatter" title="Splatter">
42
+ <i class="fa fa-spray-can fa-lg"></i>
43
+ </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  </div>
45
 
46
+ <!-- Canvas Stack -->
47
+ <div id="canvas-wrapper" class="relative flex-1 bg-white"></div>
48
+ </main>
49
+
50
+ <!-- Script -->
51
+ <script>
52
+ const layersContainer = document.getElementById('layers');
53
+ const addLayerBtn = document.getElementById('add-layer');
54
+ const canvasWrapper = document.getElementById('canvas-wrapper');
55
+ let layers = [], current = -1;
56
+
57
+ // Create a new layer
58
+ function addLayer(name='Layer') {
59
+ const id = Date.now().toString();
60
+ // Create <canvas>
61
+ const c = document.createElement('canvas');
62
+ c.id = 'canvas-' + id;
63
+ c.width = canvasWrapper.clientWidth;
64
+ c.height = canvasWrapper.clientHeight;
65
+ c.classList.add('absolute','top-0','left-0');
66
+ canvasWrapper.appendChild(c);
67
+
68
+ // Init Fabric canvas
69
+ const fc = new fabric.Canvas(c.id, {
70
  isDrawingMode: true,
71
+ backgroundColor: 'transparent'
72
+ });
73
+ fc.freeDrawingBrush = new fabric.PencilBrush(fc); // default :contentReference[oaicite:5]{index=5}
 
 
 
74
 
75
+ layers.push({ id, name, el: c, fc });
76
+ selectLayer(layers.length - 1);
77
+ updateLayersUI();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
+ // Refresh the layers panel
81
+ function updateLayersUI() {
82
+ layersContainer.innerHTML = '';
83
+ layers.forEach((ly, i) => {
84
+ const div = document.createElement('div');
85
+ div.className = [
86
+ 'flex items-center justify-between p-2 rounded',
87
+ i===current ? 'bg-blue-100' : 'hover:bg-gray-100 cursor-pointer'
88
+ ].join(' ');
89
+ div.innerHTML = `
90
+ <span>${ly.name}</span>
91
+ <div class="space-x-1">
92
+ <button onclick="moveLayer(${i},-1)"><i class="fa fa-arrow-up"></i></button>
93
+ <button onclick="moveLayer(${i},+1)"><i class="fa fa-arrow-down"></i></button>
94
+ <button onclick="removeLayer(${i})"><i class="fa fa-trash"></i></button>
95
+ </div>`;
96
+ div.addEventListener('click',()=>selectLayer(i));
97
+ layersContainer.appendChild(div);
98
+ });
99
+ // Stack canvases by index
100
+ layers.forEach((ly,i)=> {
101
+ ly.el.style.zIndex = i;
102
+ });
103
+ if(current>=0) layers[current].el.style.zIndex = layers.length;
104
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
 
106
+ // Select a layer
107
+ function selectLayer(i) {
108
+ current = i;
109
+ layers.forEach((ly,idx)=>{
110
+ ly.fc.selection = (idx===i);
111
+ });
112
+ updateLayersUI();
113
+ }
114
 
115
+ // Remove a layer
116
+ function removeLayer(i) {
117
+ canvasWrapper.removeChild(layers[i].el);
118
+ layers.splice(i,1);
119
+ if(current >= layers.length) current = layers.length -1;
120
+ updateLayersUI();
121
+ }
122
 
123
+ // Move layer up/down
124
+ function moveLayer(i, dir) {
125
+ const j = i + dir;
126
+ if(j<0||j>=layers.length) return;
127
+ [layers[i], layers[j]] = [layers[j], layers[i]];
128
+ if(current === i) current = j;
129
+ else if(current === j) current = i;
130
+ updateLayersUI();
131
+ }
132
 
133
+ // Change brush type
134
+ document.querySelectorAll('.brush-btn').forEach(btn=>{
135
+ btn.addEventListener('click',()=>{
136
+ if(current<0) return;
137
+ const f = layers[current].fc;
138
+ switch(btn.dataset.brush) {
139
+ case 'pencil':
140
+ f.freeDrawingBrush = new fabric.PencilBrush(f); break;
141
+ case 'chalk':
142
+ f.freeDrawingBrush = new fabric.SketchyBrush(f,{
143
+ width: 10, color:'#222', opacity:0.6
144
+ }); break; // Sketchy for chalk :contentReference[oaicite:6]{index=6}
145
+ case 'paint':
146
+ f.freeDrawingBrush = new fabric.RibbonBrush(f,{
147
+ width: 20, color:'#c00', opacity:0.8
148
+ }); break; // Ribbon for paint drips :contentReference[oaicite:7]{index=7}
149
+ case 'splatter':
150
+ f.freeDrawingBrush = new fabric.SpraypaintBrush(f,{
151
+ width: 30, color:'#008', opacity:0.7
152
+ }); break; // Spraypaint for splatter :contentReference[oaicite:8]{index=8}
153
+ }
154
+ });
155
+ });
156
 
157
+ // Init with one layer
158
+ window.addEventListener('DOMContentLoaded',()=> addLayer('Layer 1'));
159
+ addLayerBtn.addEventListener('click',()=>addLayer(`Layer ${layers.length+1}`));
160
+ </script>
161
  </body>
162
  </html>