victor HF Staff commited on
Commit
0b94f90
·
verified ·
1 Parent(s): e0582d0

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +382 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Text Flow
3
- emoji: 💻
4
- colorFrom: green
5
  colorTo: blue
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: text-flow
3
+ emoji: 🐳
4
+ colorFrom: pink
5
  colorTo: blue
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,382 @@
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>Text Flow Drawing Canvas</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <style>
9
+ body {
10
+ overflow: hidden;
11
+ touch-action: none;
12
+ font-family: 'Georgia', serif;
13
+ }
14
+ canvas {
15
+ position: absolute;
16
+ top: 0;
17
+ left: 0;
18
+ z-index: 1;
19
+ }
20
+ .controls {
21
+ position: absolute;
22
+ bottom: 20px;
23
+ left: 50%;
24
+ transform: translateX(-50%);
25
+ z-index: 10;
26
+ background: rgba(255, 255, 255, 0.9);
27
+ padding: 15px;
28
+ border-radius: 15px;
29
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
30
+ backdrop-filter: blur(5px);
31
+ max-width: 90%;
32
+ }
33
+ .text-palette {
34
+ display: flex;
35
+ flex-wrap: wrap;
36
+ gap: 8px;
37
+ margin-bottom: 15px;
38
+ justify-content: center;
39
+ }
40
+ .text-option {
41
+ cursor: pointer;
42
+ padding: 8px 12px;
43
+ border-radius: 8px;
44
+ background: white;
45
+ border: 1px solid #e2e8f0;
46
+ transition: all 0.2s;
47
+ font-size: 14px;
48
+ white-space: nowrap;
49
+ }
50
+ .text-option:hover, .text-option.active {
51
+ background: #3b82f6;
52
+ color: white;
53
+ transform: translateY(-2px);
54
+ }
55
+ .color-picker {
56
+ display: flex;
57
+ gap: 10px;
58
+ margin-bottom: 15px;
59
+ justify-content: center;
60
+ }
61
+ .color-option {
62
+ width: 28px;
63
+ height: 28px;
64
+ border-radius: 50%;
65
+ cursor: pointer;
66
+ border: 2px solid white;
67
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
68
+ transition: transform 0.2s;
69
+ }
70
+ .color-option:hover, .color-option.active {
71
+ transform: scale(1.2);
72
+ }
73
+ .controls-group {
74
+ display: flex;
75
+ gap: 15px;
76
+ justify-content: center;
77
+ margin-bottom: 15px;
78
+ flex-wrap: wrap;
79
+ }
80
+ .control-item {
81
+ display: flex;
82
+ flex-direction: column;
83
+ align-items: center;
84
+ }
85
+ .control-label {
86
+ font-size: 12px;
87
+ margin-bottom: 5px;
88
+ color: #4b5563;
89
+ font-weight: 500;
90
+ }
91
+ .title {
92
+ position: absolute;
93
+ top: 20px;
94
+ left: 50%;
95
+ transform: translateX(-50%);
96
+ z-index: 10;
97
+ background: rgba(255, 255, 255, 0.9);
98
+ padding: 12px 25px;
99
+ border-radius: 30px;
100
+ font-family: 'Playfair Display', serif;
101
+ font-weight: 600;
102
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
103
+ color: #1e40af;
104
+ }
105
+ .custom-text {
106
+ width: 100%;
107
+ padding: 8px 12px;
108
+ border-radius: 8px;
109
+ border: 1px solid #e2e8f0;
110
+ margin-bottom: 10px;
111
+ font-size: 14px;
112
+ }
113
+ .btn {
114
+ padding: 8px 16px;
115
+ border-radius: 8px;
116
+ font-weight: 500;
117
+ transition: all 0.2s;
118
+ border: none;
119
+ cursor: pointer;
120
+ }
121
+ .btn-primary {
122
+ background: #3b82f6;
123
+ color: white;
124
+ }
125
+ .btn-primary:hover {
126
+ background: #2563eb;
127
+ transform: translateY(-1px);
128
+ }
129
+ .btn-danger {
130
+ background: #ef4444;
131
+ color: white;
132
+ }
133
+ .btn-danger:hover {
134
+ background: #dc2626;
135
+ transform: translateY(-1px);
136
+ }
137
+ .btn-group {
138
+ display: flex;
139
+ gap: 10px;
140
+ justify-content: center;
141
+ }
142
+ </style>
143
+ </head>
144
+ <body class="bg-gray-50">
145
+ <div class="title">Text Flow Drawing Canvas</div>
146
+
147
+ <canvas id="drawingCanvas"></canvas>
148
+
149
+ <div class="controls">
150
+ <input type="text" id="customText" class="custom-text" placeholder="Type your own text here..." value="Love is patient, love is kind">
151
+
152
+ <div class="text-palette">
153
+ <div class="text-option active">Love is patient</div>
154
+ <div class="text-option">Be the change</div>
155
+ <div class="text-option">Dream big</div>
156
+ <div class="text-option">Stay curious</div>
157
+ <div class="text-option">Create magic</div>
158
+ <div class="text-option">Find joy</div>
159
+ <div class="text-option">Never give up</div>
160
+ <div class="text-option">You matter</div>
161
+ </div>
162
+
163
+ <div class="color-picker">
164
+ <div class="color-option active" style="background-color: #3b82f6;" data-color="#3b82f6"></div>
165
+ <div class="color-option" style="background-color: #ef4444;" data-color="#ef4444"></div>
166
+ <div class="color-option" style="background-color: #10b981;" data-color="#10b981"></div>
167
+ <div class="color-option" style="background-color: #f59e0b;" data-color="#f59e0b"></div>
168
+ <div class="color-option" style="background-color: #8b5cf6;" data-color="#8b5cf6"></div>
169
+ <div class="color-option" style="background-color: #000000;" data-color="#000000"></div>
170
+ </div>
171
+
172
+ <div class="controls-group">
173
+ <div class="control-item">
174
+ <span class="control-label">Font Size</span>
175
+ <input type="range" id="sizeSlider" min="12" max="36" value="18" class="w-24">
176
+ <span id="sizeValue" class="text-xs mt-1">18px</span>
177
+ </div>
178
+ <div class="control-item">
179
+ <span class="control-label">Spacing</span>
180
+ <input type="range" id="spacingSlider" min="0.5" max="2" step="0.1" value="1" class="w-24">
181
+ <span id="spacingValue" class="text-xs mt-1">1.0</span>
182
+ </div>
183
+ <div class="control-item">
184
+ <span class="control-label">Opacity</span>
185
+ <input type="range" id="opacitySlider" min="0.2" max="1" step="0.1" value="0.8" class="w-24">
186
+ <span id="opacityValue" class="text-xs mt-1">80%</span>
187
+ </div>
188
+ </div>
189
+
190
+ <div class="btn-group">
191
+ <button id="clearBtn" class="btn btn-danger">Clear Canvas</button>
192
+ <button id="saveBtn" class="btn btn-primary">Save as Image</button>
193
+ </div>
194
+ </div>
195
+
196
+ <script>
197
+ document.addEventListener('DOMContentLoaded', () => {
198
+ const canvas = document.getElementById('drawingCanvas');
199
+ const ctx = canvas.getContext('2d');
200
+ let isDrawing = false;
201
+ let currentText = "Love is patient, love is kind";
202
+ let currentColor = '#3b82f6';
203
+ let currentSize = 18;
204
+ let currentSpacing = 1;
205
+ let currentOpacity = 0.8;
206
+ let lastX = 0;
207
+ let lastY = 0;
208
+ let textPosition = 0;
209
+
210
+ // Set canvas to full window size
211
+ function resizeCanvas() {
212
+ canvas.width = window.innerWidth;
213
+ canvas.height = window.innerHeight;
214
+ // Add a subtle off-white background
215
+ ctx.fillStyle = '#f8fafc';
216
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
217
+ }
218
+
219
+ resizeCanvas();
220
+ window.addEventListener('resize', resizeCanvas);
221
+
222
+ // Drawing functions
223
+ function startDrawing(e) {
224
+ isDrawing = true;
225
+ const pos = getPosition(e);
226
+ lastX = pos.x;
227
+ lastY = pos.y;
228
+ textPosition = 0; // Reset text position for new stroke
229
+ draw(e);
230
+ }
231
+
232
+ function stopDrawing() {
233
+ isDrawing = false;
234
+ }
235
+
236
+ function getPosition(e) {
237
+ let x, y;
238
+ if (e.type.includes('touch')) {
239
+ x = e.touches[0].clientX;
240
+ y = e.touches[0].clientY;
241
+ } else {
242
+ x = e.clientX;
243
+ y = e.clientY;
244
+ }
245
+ return { x, y };
246
+ }
247
+
248
+ function draw(e) {
249
+ if (!isDrawing) return;
250
+
251
+ const pos = getPosition(e);
252
+ const x = pos.x;
253
+ const y = pos.y;
254
+
255
+ // Calculate distance from last point
256
+ const distance = Math.sqrt(Math.pow(x - lastX, 2) + Math.pow(y - lastY, 2));
257
+
258
+ if (distance > currentSize / 3) {
259
+ // Calculate angle for text rotation
260
+ const angle = Math.atan2(y - lastY, x - lastX);
261
+
262
+ ctx.save();
263
+ ctx.translate(x, y);
264
+ ctx.rotate(angle);
265
+
266
+ // Set text style
267
+ ctx.font = `${currentSize}px Georgia, serif`;
268
+ ctx.fillStyle = currentColor;
269
+ ctx.globalAlpha = currentOpacity;
270
+
271
+ // Draw the next character in the text
272
+ const char = currentText[textPosition % currentText.length];
273
+ ctx.fillText(char, 0, 0);
274
+
275
+ // Move forward in the text and position
276
+ textPosition++;
277
+ lastX = x;
278
+ lastY = y;
279
+
280
+ // Move to next position based on spacing
281
+ ctx.translate(currentSize * currentSpacing, 0);
282
+ ctx.restore();
283
+ }
284
+ }
285
+
286
+ // Event listeners for drawing
287
+ canvas.addEventListener('mousedown', startDrawing);
288
+ canvas.addEventListener('mousemove', draw);
289
+ canvas.addEventListener('mouseup', stopDrawing);
290
+ canvas.addEventListener('mouseout', stopDrawing);
291
+
292
+ // Touch support
293
+ canvas.addEventListener('touchstart', (e) => {
294
+ e.preventDefault();
295
+ startDrawing(e);
296
+ });
297
+ canvas.addEventListener('touchmove', (e) => {
298
+ e.preventDefault();
299
+ draw(e);
300
+ });
301
+ canvas.addEventListener('touchend', stopDrawing);
302
+
303
+ // Text selection
304
+ document.querySelectorAll('.text-option').forEach(option => {
305
+ option.addEventListener('click', () => {
306
+ document.querySelectorAll('.text-option').forEach(opt => opt.classList.remove('active'));
307
+ option.classList.add('active');
308
+ currentText = option.textContent;
309
+ });
310
+ });
311
+
312
+ // Custom text input
313
+ document.getElementById('customText').addEventListener('input', (e) => {
314
+ currentText = e.target.value;
315
+ // Also activate the custom text field
316
+ document.querySelectorAll('.text-option').forEach(opt => opt.classList.remove('active'));
317
+ });
318
+
319
+ // Color selection
320
+ document.querySelectorAll('.color-option').forEach(option => {
321
+ option.addEventListener('click', () => {
322
+ document.querySelectorAll('.color-option').forEach(opt => opt.classList.remove('active'));
323
+ option.classList.add('active');
324
+ currentColor = option.getAttribute('data-color');
325
+ });
326
+ });
327
+
328
+ // Size control
329
+ const sizeSlider = document.getElementById('sizeSlider');
330
+ const sizeValue = document.getElementById('sizeValue');
331
+
332
+ sizeSlider.addEventListener('input', () => {
333
+ currentSize = parseInt(sizeSlider.value);
334
+ sizeValue.textContent = `${currentSize}px`;
335
+ });
336
+
337
+ // Spacing control
338
+ const spacingSlider = document.getElementById('spacingSlider');
339
+ const spacingValue = document.getElementById('spacingValue');
340
+
341
+ spacingSlider.addEventListener('input', () => {
342
+ currentSpacing = parseFloat(spacingSlider.value);
343
+ spacingValue.textContent = currentSpacing.toFixed(1);
344
+ });
345
+
346
+ // Opacity control
347
+ const opacitySlider = document.getElementById('opacitySlider');
348
+ const opacityValue = document.getElementById('opacityValue');
349
+
350
+ opacitySlider.addEventListener('input', () => {
351
+ currentOpacity = parseFloat(opacitySlider.value);
352
+ opacityValue.textContent = `${Math.round(currentOpacity * 100)}%`;
353
+ });
354
+
355
+ // Clear canvas
356
+ document.getElementById('clearBtn').addEventListener('click', () => {
357
+ if (confirm('Are you sure you want to clear the canvas?')) {
358
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
359
+ // Reset background
360
+ ctx.fillStyle = '#f8fafc';
361
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
362
+ }
363
+ });
364
+
365
+ // Save canvas as image
366
+ document.getElementById('saveBtn').addEventListener('click', () => {
367
+ const link = document.createElement('a');
368
+ link.download = 'text-drawing.png';
369
+ link.href = canvas.toDataURL('image/png');
370
+ link.click();
371
+ });
372
+
373
+ // Prevent scrolling when touching canvas
374
+ document.addEventListener('touchmove', (e) => {
375
+ if (isDrawing) {
376
+ e.preventDefault();
377
+ }
378
+ }, { passive: false });
379
+ });
380
+ </script>
381
+ <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=victor/text-flow" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body>
382
+ </html>