Mustafa7assan commited on
Commit
cb10101
·
verified ·
1 Parent(s): 54cbb0a

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +405 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Hand Written
3
- emoji: 📊
4
- colorFrom: gray
5
- colorTo: gray
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: hand-written
3
+ emoji: 🐳
4
+ colorFrom: red
5
+ colorTo: yellow
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,405 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </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
+ <title>Handwriting Canvas</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
+ <style>
10
+ @import url('https://fonts.googleapis.com/css2?family=Caveat:wght@400;700&display=swap');
11
+
12
+ .handwriting {
13
+ font-family: 'Caveat', cursive;
14
+ }
15
+
16
+ canvas {
17
+ touch-action: none;
18
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
19
+ }
20
+
21
+ .tool-btn {
22
+ transition: all 0.2s ease;
23
+ }
24
+
25
+ .tool-btn.active {
26
+ transform: scale(1.1);
27
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.5);
28
+ }
29
+
30
+ #drawingCanvas {
31
+ background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImdyaWQiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTSAwIDEwIEwgNDAgMTAgTSAxMCAwIEwgMTAgNDAgTSAwIDIwIEwgNDAgMjAgTSAyMCAwIEwgMjAgNDAgTSAwIDMwIEwgNDAgMzAgTSAzMCAwIEwgMzAgNDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2QwZDBkMCIgb3BhY2l0eT0iMC4yIiBzdHJva2Utd2lkdGg9IjEiLz48L3BhdHRlcm4+PC9kZWZzPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JpZCkiLz48L3N2Zz4=');
32
+ }
33
+
34
+ .ink-effect {
35
+ position: relative;
36
+ }
37
+
38
+ .ink-effect::after {
39
+ content: '';
40
+ position: absolute;
41
+ top: 0;
42
+ left: 0;
43
+ right: 0;
44
+ bottom: 0;
45
+ background: radial-gradient(circle, transparent 0%, rgba(0,0,0,0.05) 100%);
46
+ pointer-events: none;
47
+ }
48
+ </style>
49
+ </head>
50
+ <body class="bg-gray-100 min-h-screen">
51
+ <div class="container mx-auto px-4 py-8">
52
+ <header class="mb-8 text-center">
53
+ <h1 class="text-4xl font-bold text-indigo-700 handwriting mb-2">Handwriting Canvas</h1>
54
+ <p class="text-gray-600">Draw or write naturally on images or blank paper</p>
55
+ </header>
56
+
57
+ <div class="flex flex-col lg:flex-row gap-6">
58
+ <!-- Tools Panel -->
59
+ <div class="bg-white rounded-lg shadow-md p-4 lg:w-1/4">
60
+ <h2 class="text-xl font-semibold mb-4 text-gray-800 handwriting">Tools</h2>
61
+
62
+ <div class="space-y-4">
63
+ <!-- Color Picker -->
64
+ <div>
65
+ <label class="block text-sm font-medium text-gray-700 mb-1 handwriting">Pen Color</label>
66
+ <div class="flex flex-wrap gap-2">
67
+ <button data-color="#000000" class="tool-btn w-8 h-8 rounded-full bg-black border-2 border-gray-300"></button>
68
+ <button data-color="#e53e3e" class="tool-btn w-8 h-8 rounded-full bg-red-600 border-2 border-gray-300"></button>
69
+ <button data-color="#3182ce" class="tool-btn w-8 h-8 rounded-full bg-blue-600 border-2 border-gray-300"></button>
70
+ <button data-color="#38a169" class="tool-btn w-8 h-8 rounded-full bg-green-600 border-2 border-gray-300"></button>
71
+ <button data-color="#805ad5" class="tool-btn w-8 h-8 rounded-full bg-purple-600 border-2 border-gray-300"></button>
72
+ </div>
73
+ </div>
74
+
75
+ <!-- Brush Size -->
76
+ <div>
77
+ <label class="block text-sm font-medium text-gray-700 mb-1 handwriting">Brush Size</label>
78
+ <input type="range" id="brushSize" min="1" max="20" value="3" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer">
79
+ <div class="flex justify-between text-xs text-gray-500 mt-1">
80
+ <span>Thin</span>
81
+ <span>Thick</span>
82
+ </div>
83
+ </div>
84
+
85
+ <!-- Background Options -->
86
+ <div>
87
+ <label class="block text-sm font-medium text-gray-700 mb-1 handwriting">Background</label>
88
+ <div class="flex flex-wrap gap-2">
89
+ <button data-bg="blank" class="tool-btn px-3 py-1 bg-white border border-gray-300 rounded-md handwriting">White Paper</button>
90
+ <button data-bg="grid" class="tool-btn px-3 py-1 bg-white border border-gray-300 rounded-md handwriting">Grid Paper</button>
91
+ <button id="uploadImageBtn" class="tool-btn px-3 py-1 bg-indigo-100 text-indigo-700 border border-indigo-200 rounded-md handwriting">
92
+ <i class="fas fa-image mr-1"></i> Upload Image
93
+ </button>
94
+ <input type="file" id="imageUpload" accept="image/*" class="hidden">
95
+ </div>
96
+ </div>
97
+
98
+ <!-- Actions -->
99
+ <div class="pt-4 border-t border-gray-200">
100
+ <button id="clearCanvas" class="w-full bg-red-100 text-red-700 py-2 rounded-md hover:bg-red-200 transition handwriting">
101
+ <i class="fas fa-trash-alt mr-2"></i> Clear Canvas
102
+ </button>
103
+ <button id="downloadCanvas" class="w-full mt-2 bg-indigo-100 text-indigo-700 py-2 rounded-md hover:bg-indigo-200 transition handwriting">
104
+ <i class="fas fa-download mr-2"></i> Download
105
+ </button>
106
+ </div>
107
+
108
+ <!-- Handwriting Toggle -->
109
+ <div class="pt-4 border-t border-gray-200">
110
+ <label class="inline-flex items-center cursor-pointer">
111
+ <input type="checkbox" id="handwritingEffect" class="sr-only peer" checked>
112
+ <div class="relative w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-indigo-300 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-indigo-600"></div>
113
+ <span class="ml-3 text-sm font-medium text-gray-700 handwriting">Handwriting Effect</span>
114
+ </label>
115
+ </div>
116
+ </div>
117
+ </div>
118
+
119
+ <!-- Canvas Area -->
120
+ <div class="flex-1">
121
+ <div class="bg-white rounded-lg shadow-md p-4">
122
+ <div class="relative overflow-hidden rounded-md ink-effect">
123
+ <canvas id="drawingCanvas" class="bg-white w-full h-96 lg:h-[500px] border border-gray-200"></canvas>
124
+ </div>
125
+
126
+ <div class="mt-4 flex justify-center space-x-4">
127
+ <button id="undoBtn" class="px-4 py-2 bg-gray-100 text-gray-700 rounded-md hover:bg-gray-200 transition handwriting">
128
+ <i class="fas fa-undo mr-2"></i> Undo
129
+ </button>
130
+ <button id="redoBtn" class="px-4 py-2 bg-gray-100 text-gray-700 rounded-md hover:bg-gray-200 transition handwriting">
131
+ <i class="fas fa-redo mr-2"></i> Redo
132
+ </button>
133
+ </div>
134
+ </div>
135
+ </div>
136
+ </div>
137
+ </div>
138
+
139
+ <script>
140
+ document.addEventListener('DOMContentLoaded', function() {
141
+ const canvas = document.getElementById('drawingCanvas');
142
+ const ctx = canvas.getContext('2d');
143
+ const colorButtons = document.querySelectorAll('[data-color]');
144
+ const bgButtons = document.querySelectorAll('[data-bg]');
145
+ const brushSizeInput = document.getElementById('brushSize');
146
+ const clearCanvasBtn = document.getElementById('clearCanvas');
147
+ const downloadCanvasBtn = document.getElementById('downloadCanvas');
148
+ const uploadImageBtn = document.getElementById('uploadImageBtn');
149
+ const imageUpload = document.getElementById('imageUpload');
150
+ const handwritingEffect = document.getElementById('handwritingEffect');
151
+ const undoBtn = document.getElementById('undoBtn');
152
+ const redoBtn = document.getElementById('redoBtn');
153
+
154
+ let isDrawing = false;
155
+ let currentColor = '#000000';
156
+ let currentBrushSize = 3;
157
+ let handwritingEnabled = true;
158
+ let canvasHistory = [];
159
+ let historyIndex = -1;
160
+
161
+ // Set canvas size
162
+ function resizeCanvas() {
163
+ const container = canvas.parentElement;
164
+ canvas.width = container.clientWidth;
165
+ canvas.height = container.clientHeight;
166
+ redrawCanvas();
167
+ }
168
+
169
+ // Initialize canvas
170
+ function initCanvas() {
171
+ resizeCanvas();
172
+ setBackground('blank');
173
+
174
+ // Add event listeners for window resize
175
+ window.addEventListener('resize', () => {
176
+ resizeCanvas();
177
+ });
178
+
179
+ // Save initial state
180
+ saveCanvasState();
181
+ }
182
+
183
+ // Set background
184
+ function setBackground(type) {
185
+ if (type === 'blank') {
186
+ canvas.style.backgroundImage = 'none';
187
+ canvas.style.backgroundColor = '#ffffff';
188
+ } else if (type === 'grid') {
189
+ canvas.style.backgroundImage = 'url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImdyaWQiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTSAwIDEwIEwgNDAgMTAgTSAxMCAwIEwgMTAgNDAgTSAwIDIwIEwgNDAgMjAgTSAyMCAwIEwgMjAgNDAgTSAwIDMwIEwgNDAgMzAgTSAzMCAwIEwgMzAgNDAiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2QwZDBkMCIgb3BhY2l0eT0iMC4yIiBzdHJva2Utd2lkdGg9IjEiLz48L3BhdHRlcm4+PC9kZWZzPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JpZCkiLz48L3N2Zz4=")';
190
+ }
191
+ }
192
+
193
+ // Save canvas state to history
194
+ function saveCanvasState() {
195
+ // Remove any states after current index (for redo)
196
+ if (historyIndex < canvasHistory.length - 1) {
197
+ canvasHistory = canvasHistory.slice(0, historyIndex + 1);
198
+ }
199
+
200
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
201
+ canvasHistory.push(imageData);
202
+ historyIndex = canvasHistory.length - 1;
203
+
204
+ updateUndoRedoButtons();
205
+ }
206
+
207
+ // Update undo/redo button states
208
+ function updateUndoRedoButtons() {
209
+ undoBtn.disabled = historyIndex <= 0;
210
+ redoBtn.disabled = historyIndex >= canvasHistory.length - 1;
211
+ }
212
+
213
+ // Undo action
214
+ function undo() {
215
+ if (historyIndex > 0) {
216
+ historyIndex--;
217
+ redrawCanvas();
218
+ }
219
+ }
220
+
221
+ // Redo action
222
+ function redo() {
223
+ if (historyIndex < canvasHistory.length - 1) {
224
+ historyIndex++;
225
+ redrawCanvas();
226
+ }
227
+ }
228
+
229
+ // Redraw canvas from history
230
+ function redrawCanvas() {
231
+ if (canvasHistory.length > 0) {
232
+ ctx.putImageData(canvasHistory[historyIndex], 0, 0);
233
+ }
234
+ }
235
+
236
+ // Start drawing
237
+ function startDrawing(e) {
238
+ isDrawing = true;
239
+ draw(e);
240
+ }
241
+
242
+ // Stop drawing
243
+ function stopDrawing() {
244
+ isDrawing = false;
245
+ ctx.beginPath();
246
+ saveCanvasState();
247
+ }
248
+
249
+ // Draw on canvas
250
+ function draw(e) {
251
+ if (!isDrawing) return;
252
+
253
+ ctx.lineCap = 'round';
254
+ ctx.lineJoin = 'round';
255
+ ctx.strokeStyle = currentColor;
256
+ ctx.lineWidth = currentBrushSize;
257
+
258
+ // Get position (handling both mouse and touch events)
259
+ let x, y;
260
+ if (e.type.includes('touch')) {
261
+ const rect = canvas.getBoundingClientRect();
262
+ x = e.touches[0].clientX - rect.left;
263
+ y = e.touches[0].clientY - rect.top;
264
+ } else {
265
+ x = e.offsetX;
266
+ y = e.offsetY;
267
+ }
268
+
269
+ // Apply handwriting effect by adding slight randomness
270
+ if (handwritingEnabled) {
271
+ ctx.lineTo(
272
+ x + (Math.random() - 0.5) * currentBrushSize * 0.5,
273
+ y + (Math.random() - 0.5) * currentBrushSize * 0.5
274
+ );
275
+ } else {
276
+ ctx.lineTo(x, y);
277
+ }
278
+
279
+ ctx.stroke();
280
+ ctx.beginPath();
281
+ ctx.moveTo(x, y);
282
+ }
283
+
284
+ // Clear canvas
285
+ function clearCanvas() {
286
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
287
+ saveCanvasState();
288
+ }
289
+
290
+ // Download canvas as image
291
+ function downloadCanvas() {
292
+ const link = document.createElement('a');
293
+ link.download = 'handwriting-' + new Date().toISOString().slice(0, 10) + '.png';
294
+ link.href = canvas.toDataURL('image/png');
295
+ link.click();
296
+ }
297
+
298
+ // Handle image upload
299
+ function handleImageUpload(e) {
300
+ const file = e.target.files[0];
301
+ if (!file) return;
302
+
303
+ const reader = new FileReader();
304
+ reader.onload = function(event) {
305
+ const img = new Image();
306
+ img.onload = function() {
307
+ // Clear canvas and draw the image
308
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
309
+
310
+ // Calculate dimensions to maintain aspect ratio
311
+ const ratio = Math.min(
312
+ canvas.width / img.width,
313
+ canvas.height / img.height
314
+ );
315
+ const width = img.width * ratio;
316
+ const height = img.height * ratio;
317
+ const x = (canvas.width - width) / 2;
318
+ const y = (canvas.height - height) / 2;
319
+
320
+ ctx.drawImage(img, x, y, width, height);
321
+ saveCanvasState();
322
+ };
323
+ img.src = event.target.result;
324
+ };
325
+ reader.readAsDataURL(file);
326
+ }
327
+
328
+ // Event listeners
329
+ canvas.addEventListener('mousedown', startDrawing);
330
+ canvas.addEventListener('mousemove', draw);
331
+ canvas.addEventListener('mouseup', stopDrawing);
332
+ canvas.addEventListener('mouseout', stopDrawing);
333
+
334
+ // Touch events for mobile
335
+ canvas.addEventListener('touchstart', (e) => {
336
+ e.preventDefault();
337
+ startDrawing(e);
338
+ });
339
+ canvas.addEventListener('touchmove', (e) => {
340
+ e.preventDefault();
341
+ draw(e);
342
+ });
343
+ canvas.addEventListener('touchend', (e) => {
344
+ e.preventDefault();
345
+ stopDrawing();
346
+ });
347
+
348
+ // Color buttons
349
+ colorButtons.forEach(button => {
350
+ button.addEventListener('click', () => {
351
+ currentColor = button.dataset.color;
352
+
353
+ // Update active state
354
+ colorButtons.forEach(btn => btn.classList.remove('active'));
355
+ button.classList.add('active');
356
+ });
357
+ });
358
+
359
+ // Background buttons
360
+ bgButtons.forEach(button => {
361
+ button.addEventListener('click', () => {
362
+ setBackground(button.dataset.bg);
363
+
364
+ // Update active state
365
+ bgButtons.forEach(btn => btn.classList.remove('active'));
366
+ button.classList.add('active');
367
+ });
368
+ });
369
+
370
+ // Brush size
371
+ brushSizeInput.addEventListener('input', () => {
372
+ currentBrushSize = brushSizeInput.value;
373
+ });
374
+
375
+ // Clear canvas
376
+ clearCanvasBtn.addEventListener('click', clearCanvas);
377
+
378
+ // Download
379
+ downloadCanvasBtn.addEventListener('click', downloadCanvas);
380
+
381
+ // Image upload
382
+ uploadImageBtn.addEventListener('click', () => {
383
+ imageUpload.click();
384
+ });
385
+ imageUpload.addEventListener('change', handleImageUpload);
386
+
387
+ // Handwriting effect toggle
388
+ handwritingEffect.addEventListener('change', () => {
389
+ handwritingEnabled = handwritingEffect.checked;
390
+ });
391
+
392
+ // Undo/redo buttons
393
+ undoBtn.addEventListener('click', undo);
394
+ redoBtn.addEventListener('click', redo);
395
+
396
+ // Initialize
397
+ initCanvas();
398
+
399
+ // Set black as default active color
400
+ document.querySelector('[data-color="#000000"]').classList.add('active');
401
+ document.querySelector('[data-bg="blank"]').classList.add('active');
402
+ });
403
+ </script>
404
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Mustafa7assan/hand-written" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
405
+ </html>