RED243 commited on
Commit
7e43775
·
verified ·
1 Parent(s): 0402e84

une application quinperme de cree des image ou la modifie

Browse files
Files changed (2) hide show
  1. image-editor.html +314 -0
  2. index.html +10 -3
image-editor.html ADDED
@@ -0,0 +1,314 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>Image Editor - ChatNimbus</title>
7
+ <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://unpkg.com/feather-icons"></script>
10
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
11
+ <script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
12
+ <script src="https://cdn.jsdelivr.net/npm/fabric@5.3.1/dist/fabric.min.js"></script>
13
+ <style>
14
+ #canvas-container {
15
+ width: 100%;
16
+ height: 70vh;
17
+ border: 2px dashed #ccc;
18
+ position: relative;
19
+ }
20
+ .tool-btn {
21
+ transition: all 0.2s;
22
+ }
23
+ .tool-btn:hover {
24
+ transform: scale(1.1);
25
+ }
26
+ </style>
27
+ </head>
28
+ <body class="bg-gray-100 min-h-screen">
29
+ <div class="container mx-auto px-4 py-8">
30
+ <div class="flex justify-between items-center mb-6">
31
+ <h1 class="text-3xl font-bold text-gray-800">Image Editor</h1>
32
+ <a href="index.html" class="flex items-center text-blue-500 hover:text-blue-700">
33
+ <i data-feather="arrow-left" class="mr-1"></i> Back to Chat
34
+ </a>
35
+ </div>
36
+
37
+ <div class="bg-white rounded-lg shadow-md p-6">
38
+ <div class="flex flex-col md:flex-row gap-6">
39
+ <!-- Tools Panel -->
40
+ <div class="w-full md:w-1/4 bg-gray-50 p-4 rounded-lg">
41
+ <div class="mb-6">
42
+ <h2 class="text-lg font-semibold mb-3">Upload Image</h2>
43
+ <input type="file" id="image-upload" accept="image/*" class="hidden">
44
+ <button onclick="document.getElementById('image-upload').click()" class="w-full bg-blue-500 text-white py-2 px-4 rounded-lg hover:bg-blue-600 flex items-center justify-center">
45
+ <i data-feather="upload" class="mr-2"></i> Choose File
46
+ </button>
47
+ </div>
48
+
49
+ <div class="mb-6">
50
+ <h2 class="text-lg font-semibold mb-3">Drawing Tools</h2>
51
+ <div class="grid grid-cols-3 gap-2">
52
+ <button id="draw-btn" class="tool-btn bg-gray-200 p-2 rounded-lg" title="Draw">
53
+ <i data-feather="edit-3"></i>
54
+ </button>
55
+ <button id="text-btn" class="tool-btn bg-gray-200 p-2 rounded-lg" title="Add Text">
56
+ <i data-feather="type"></i>
57
+ </button>
58
+ <button id="shape-btn" class="tool-btn bg-gray-200 p-2 rounded-lg" title="Add Shape">
59
+ <i data-feather="square"></i>
60
+ </button>
61
+ <button id="eraser-btn" class="tool-btn bg-gray-200 p-2 rounded-lg" title="Eraser">
62
+ <i data-feather="x"></i>
63
+ </button>
64
+ <button id="crop-btn" class="tool-btn bg-gray-200 p-2 rounded-lg" title="Crop">
65
+ <i data-feather="crop"></i>
66
+ </button>
67
+ <button id="clear-btn" class="tool-btn bg-gray-200 p-2 rounded-lg" title="Clear All">
68
+ <i data-feather="trash-2"></i>
69
+ </button>
70
+ </div>
71
+ </div>
72
+
73
+ <div class="mb-6">
74
+ <h2 class="text-lg font-semibold mb-3">Filters</h2>
75
+ <select id="filter-select" class="w-full p-2 border rounded-lg">
76
+ <option value="none">No Filter</option>
77
+ <option value="grayscale">Grayscale</option>
78
+ <option value="sepia">Sepia</option>
79
+ <option value="invert">Invert</option>
80
+ <option value="blur">Blur</option>
81
+ </select>
82
+ </div>
83
+
84
+ <div class="mb-6">
85
+ <h2 class="text-lg font-semibold mb-3">Text Options</h2>
86
+ <input type="text" id="text-input" placeholder="Enter text" class="w-full p-2 border rounded-lg mb-2">
87
+ <div class="flex justify-between">
88
+ <input type="color" id="text-color" value="#000000" class="w-8 h-8">
89
+ <select id="font-select" class="w-3/4 p-1 border rounded-lg">
90
+ <option value="Arial">Arial</option>
91
+ <option value="Times New Roman">Times New Roman</option>
92
+ <option value="Courier New">Courier New</option>
93
+ <option value="Georgia">Georgia</option>
94
+ </select>
95
+ </div>
96
+ </div>
97
+
98
+ <div class="mb-6">
99
+ <h2 class="text-lg font-semibold mb-3">Brush Options</h2>
100
+ <div class="flex items-center mb-2">
101
+ <span class="mr-2">Size:</span>
102
+ <input type="range" id="brush-size" min="1" max="50" value="5" class="flex-1">
103
+ </div>
104
+ <div class="flex items-center">
105
+ <span class="mr-2">Color:</span>
106
+ <input type="color" id="brush-color" value="#000000" class="w-8 h-8">
107
+ </div>
108
+ </div>
109
+
110
+ <div>
111
+ <button id="save-btn" class="w-full bg-green-500 text-white py-2 px-4 rounded-lg hover:bg-green-600 flex items-center justify-center">
112
+ <i data-feather="save" class="mr-2"></i> Save Image
113
+ </button>
114
+ </div>
115
+ </div>
116
+
117
+ <!-- Canvas Area -->
118
+ <div class="w-full md:w-3/4">
119
+ <div id="canvas-container">
120
+ <canvas id="canvas"></canvas>
121
+ </div>
122
+ <div class="mt-4 flex justify-center gap-4">
123
+ <button id="undo-btn" class="bg-gray-200 py-2 px-4 rounded-lg hover:bg-gray-300 flex items-center">
124
+ <i data-feather="rotate-ccw" class="mr-2"></i> Undo
125
+ </button>
126
+ <button id="redo-btn" class="bg-gray-200 py-2 px-4 rounded-lg hover:bg-gray-300 flex items-center">
127
+ <i data-feather="rotate-cw" class="mr-2"></i> Redo
128
+ </button>
129
+ </div>
130
+ </div>
131
+ </div>
132
+ </div>
133
+ </div>
134
+
135
+ <script>
136
+ document.addEventListener('DOMContentLoaded', function() {
137
+ feather.replace();
138
+
139
+ // Initialize Fabric.js canvas
140
+ const canvas = new fabric.Canvas('canvas', {
141
+ width: document.getElementById('canvas-container').offsetWidth - 4,
142
+ height: document.getElementById('canvas-container').offsetHeight - 4,
143
+ backgroundColor: '#ffffff'
144
+ });
145
+
146
+ // Upload image
147
+ document.getElementById('image-upload').addEventListener('change', function(e) {
148
+ const file = e.target.files[0];
149
+ if (!file) return;
150
+
151
+ const reader = new FileReader();
152
+ reader.onload = function(event) {
153
+ fabric.Image.fromURL(event.target.result, function(img) {
154
+ canvas.clear();
155
+ canvas.add(img);
156
+ canvas.renderAll();
157
+ });
158
+ };
159
+ reader.readAsDataURL(file);
160
+ });
161
+
162
+ // Drawing tools
163
+ document.getElementById('draw-btn').addEventListener('click', function() {
164
+ canvas.isDrawingMode = true;
165
+ });
166
+
167
+ document.getElementById('text-btn').addEventListener('click', function() {
168
+ const text = new fabric.IText('Double click to edit', {
169
+ left: 100,
170
+ top: 100,
171
+ fontFamily: document.getElementById('font-select').value,
172
+ fill: document.getElementById('text-color').value
173
+ });
174
+ canvas.add(text);
175
+ canvas.setActiveObject(text);
176
+ canvas.renderAll();
177
+ });
178
+
179
+ document.getElementById('shape-btn').addEventListener('click', function() {
180
+ const rect = new fabric.Rect({
181
+ left: 100,
182
+ top: 100,
183
+ fill: 'transparent',
184
+ stroke: document.getElementById('brush-color').value,
185
+ strokeWidth: document.getElementById('brush-size').value,
186
+ width: 200,
187
+ height: 100
188
+ });
189
+ canvas.add(rect);
190
+ canvas.renderAll();
191
+ });
192
+
193
+ document.getElementById('eraser-btn').addEventListener('click', function() {
194
+ canvas.isDrawingMode = true;
195
+ canvas.freeDrawingBrush.color = '#ffffff';
196
+ });
197
+
198
+ document.getElementById('clear-btn').addEventListener('click', function() {
199
+ if (confirm('Are you sure you want to clear the canvas?')) {
200
+ canvas.clear();
201
+ }
202
+ });
203
+
204
+ // Brush settings
205
+ document.getElementById('brush-size').addEventListener('input', function() {
206
+ canvas.freeDrawingBrush.width = parseInt(this.value);
207
+ });
208
+
209
+ document.getElementById('brush-color').addEventListener('input', function() {
210
+ canvas.freeDrawingBrush.color = this.value;
211
+ });
212
+
213
+ // Text settings
214
+ document.getElementById('text-color').addEventListener('input', function() {
215
+ const activeObject = canvas.getActiveObject();
216
+ if (activeObject && activeObject.type === 'i-text') {
217
+ activeObject.set('fill', this.value);
218
+ canvas.renderAll();
219
+ }
220
+ });
221
+
222
+ document.getElementById('font-select').addEventListener('change', function() {
223
+ const activeObject = canvas.getActiveObject();
224
+ if (activeObject && activeObject.type === 'i-text') {
225
+ activeObject.set('fontFamily', this.value);
226
+ canvas.renderAll();
227
+ }
228
+ });
229
+
230
+ // Filters
231
+ document.getElementById('filter-select').addEventListener('change', function() {
232
+ const objects = canvas.getObjects();
233
+ objects.forEach(obj => {
234
+ if (obj.type === 'image') {
235
+ obj.filters = [];
236
+
237
+ switch(this.value) {
238
+ case 'grayscale':
239
+ obj.filters.push(new fabric.Image.filters.Grayscale());
240
+ break;
241
+ case 'sepia':
242
+ obj.filters.push(new fabric.Image.filters.Sepia());
243
+ break;
244
+ case 'invert':
245
+ obj.filters.push(new fabric.Image.filters.Invert());
246
+ break;
247
+ case 'blur':
248
+ obj.filters.push(new fabric.Image.filters.Blur({
249
+ blur: 0.2
250
+ }));
251
+ break;
252
+ }
253
+
254
+ obj.applyFilters();
255
+ canvas.renderAll();
256
+ }
257
+ });
258
+ });
259
+
260
+ // Save image
261
+ document.getElementById('save-btn').addEventListener('click', function() {
262
+ const link = document.createElement('a');
263
+ link.download = 'edited-image.png';
264
+ link.href = canvas.toDataURL({
265
+ format: 'png',
266
+ quality: 1
267
+ });
268
+ link.click();
269
+ });
270
+
271
+ // Undo/Redo
272
+ const history = [];
273
+ let historyIndex = -1;
274
+
275
+ canvas.on('object:modified', saveState);
276
+ canvas.on('object:added', saveState);
277
+
278
+ function saveState() {
279
+ if (historyIndex < history.length - 1) {
280
+ history.splice(historyIndex + 1);
281
+ }
282
+
283
+ history.push(JSON.stringify(canvas));
284
+ historyIndex = history.length - 1;
285
+ }
286
+
287
+ document.getElementById('undo-btn').addEventListener('click', function() {
288
+ if (historyIndex <= 0) return;
289
+
290
+ historyIndex--;
291
+ canvas.loadFromJSON(history[historyIndex], function() {
292
+ canvas.renderAll();
293
+ });
294
+ });
295
+
296
+ document.getElementById('redo-btn').addEventListener('click', function() {
297
+ if (historyIndex >= history.length - 1) return;
298
+
299
+ historyIndex++;
300
+ canvas.loadFromJSON(history[historyIndex], function() {
301
+ canvas.renderAll();
302
+ });
303
+ });
304
+
305
+ // Window resize
306
+ window.addEventListener('resize', function() {
307
+ canvas.setWidth(document.getElementById('canvas-container').offsetWidth - 4);
308
+ canvas.setHeight(document.getElementById('canvas-container').offsetHeight - 4);
309
+ canvas.renderAll();
310
+ });
311
+ });
312
+ </script>
313
+ </body>
314
+ </html>
index.html CHANGED
@@ -35,11 +35,15 @@
35
  <div class="sidebar w-64 md:w-80 bg-white border-r border-gray-200 fixed h-full z-10">
36
  <!-- Header -->
37
  <div class="flex items-center justify-between p-4 border-b border-gray-200">
38
- <div class="flex items-center">
39
  <div class="w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold">CN</div>
40
  <span class="ml-2 font-semibold">ChatNimbus</span>
 
 
 
 
41
  </div>
42
- <button id="menu-toggle" class="md:hidden">
43
  <i data-feather="x"></i>
44
  </button>
45
  </div>
@@ -111,10 +115,13 @@
111
  </div>
112
  </div>
113
  <div class="ml-auto flex space-x-4">
 
 
 
114
  <button class="text-gray-500 hover:text-gray-700">
115
  <i data-feather="phone"></i>
116
  </button>
117
- <button class="text-gray-500 hover:text-gray-700">
118
  <i data-feather="video"></i>
119
  </button>
120
  <button class="text-gray-500 hover:text-gray-700">
 
35
  <div class="sidebar w-64 md:w-80 bg-white border-r border-gray-200 fixed h-full z-10">
36
  <!-- Header -->
37
  <div class="flex items-center justify-between p-4 border-b border-gray-200">
38
+ <div class="flex items-center space-x-4">
39
  <div class="w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold">CN</div>
40
  <span class="ml-2 font-semibold">ChatNimbus</span>
41
+ <a href="image-editor.html" class="text-blue-500 hover:text-blue-700 flex items-center">
42
+ <i data-feather="image" class="mr-1"></i>
43
+ <span class="hidden md:inline">Image Editor</span>
44
+ </a>
45
  </div>
46
+ <button id="menu-toggle" class="md:hidden">
47
  <i data-feather="x"></i>
48
  </button>
49
  </div>
 
115
  </div>
116
  </div>
117
  <div class="ml-auto flex space-x-4">
118
+ <a href="image-editor.html" class="text-gray-500 hover:text-gray-700">
119
+ <i data-feather="image"></i>
120
+ </a>
121
  <button class="text-gray-500 hover:text-gray-700">
122
  <i data-feather="phone"></i>
123
  </button>
124
+ <button class="text-gray-500 hover:text-gray-700">
125
  <i data-feather="video"></i>
126
  </button>
127
  <button class="text-gray-500 hover:text-gray-700">