File size: 8,019 Bytes
b2644cb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c3216d4
b2644cb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23a236c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ScribbleSense - Draw and Recognize Text</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="https://unpkg.com/feather-icons"></script>
    <script src="https://cdn.jsdelivr.net/npm/tesseract.js@4/dist/tesseract.min.js"></script>
</head>
<body class="bg-gradient-to-br from-indigo-100 to-purple-50 min-h-screen flex flex-col items-center justify-center p-4">
    <div class="max-w-4xl w-full mx-auto text-center">
        <h1 class="text-4xl md:text-5xl font-bold text-indigo-800 mb-2">ScribbleSense ✍️</h1>
        <p class="text-lg text-indigo-600 mb-8">Draw anything and watch it transform into text!</p>
        
        <div class="bg-white rounded-xl shadow-xl p-6 mb-8">
            <div class="relative">
                <canvas id="drawingCanvas" class="border-2 border-gray-300 rounded-lg w-full h-64 md:h-96 touch-none bg-white"></canvas>
                <div id="clearBtn" class="absolute top-4 right-4 p-2 bg-white rounded-full shadow-md cursor-pointer hover:bg-gray-100 transition">
                    <i data-feather="x" class="text-gray-600"></i>
                </div>
            </div>
        </div>
        
        <div id="resultContainer" class="bg-white rounded-xl shadow-xl p-6 hidden">
            <h2 class="text-2xl font-semibold text-indigo-700 mb-4">Recognized Text</h2>
            <div id="resultText" class="text-3xl md:text-4xl font-mono p-4 bg-gray-50 rounded-lg min-h-20 break-all">
                <!-- OCR result will appear here -->
            </div>
            <button id="copyBtn" class="mt-4 px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition flex items-center justify-center gap-2 mx-auto">
                <i data-feather="copy" class="w-5 h-5"></i> Copy Text
            </button>
        </div>
        
        <div class="mt-8 text-sm text-gray-500">
            <p>Draw with left mouse button pressed. The system will automatically recognize your writing after a pause.</p>
            <p class="mt-1">Supports: Roman alphabets, numbers, emojis, Chinese, Hangul, and more!</p>
        </div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            feather.replace();
            
            const canvas = document.getElementById('drawingCanvas');
            const ctx = canvas.getContext('2d');
            const resultContainer = document.getElementById('resultContainer');
            const resultText = document.getElementById('resultText');
            const clearBtn = document.getElementById('clearBtn');
            const copyBtn = document.getElementById('copyBtn');
            
            // Set canvas size
            function resizeCanvas() {
                const containerWidth = canvas.parentElement.clientWidth;
                canvas.width = containerWidth - 32; // accounting for padding
                canvas.height = Math.min(window.innerHeight * 0.6, 600);
                ctx.lineWidth = 4;
                ctx.lineCap = 'round';
                ctx.strokeStyle = '#4f46e5'; // indigo-600
            }
            
            window.addEventListener('resize', resizeCanvas);
            resizeCanvas();
            
            // Drawing variables
            let isDrawing = false;
            let lastX = 0;
            let lastY = 0;
            let inactivityTimer;
            let lastDrawTime = 0;
            
            // Drawing functions
            function startDrawing(e) {
                isDrawing = true;
                [lastX, lastY] = getPosition(e);
                clearTimeout(inactivityTimer);
            }
            
            function draw(e) {
                if (!isDrawing) return;
                
                const [x, y] = getPosition(e);
                
                ctx.beginPath();
                ctx.moveTo(lastX, lastY);
                ctx.lineTo(x, y);
                ctx.stroke();
                
                [lastX, lastY] = [x, y];
                lastDrawTime = Date.now();
                
                // Reset inactivity timer
                clearTimeout(inactivityTimer);
                inactivityTimer = setTimeout(performOCR, 500);
            }
            
            function stopDrawing() {
                isDrawing = false;
            }
            
            function getPosition(e) {
                let x, y;
                if (e.type.includes('touch')) {
                    const rect = canvas.getBoundingClientRect();
                    x = e.touches[0].clientX - rect.left;
                    y = e.touches[0].clientY - rect.top;
                } else {
                    x = e.offsetX;
                    y = e.offsetY;
                }
                return [x, y];
            }
            
            // OCR function
            function performOCR() {
                if (Date.now() - lastDrawTime < 2) return;
                
                Tesseract.recognize(
                    canvas,
                    'eng+chi_sim+chi_tra+kor+jpn+equ',
                    {
                        logger: m => console.log(m)
                    }
                ).then(({ data: { text } }) => {
                    resultText.textContent = text.trim() || "Couldn't recognize any text";
                    resultContainer.classList.remove('hidden');
                    
                    // Scroll to result if needed
                    resultContainer.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
                });
            }
            
            // Clear canvas
            function clearCanvas() {
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                resultContainer.classList.add('hidden');
                clearTimeout(inactivityTimer);
            }
            
            // Copy text function
            function copyText() {
                navigator.clipboard.writeText(resultText.textContent).then(() => {
                    const originalText = copyBtn.innerHTML;
                    copyBtn.innerHTML = '<i data-feather="check" class="w-5 h-5"></i> Copied!';
                    setTimeout(() => {
                        copyBtn.innerHTML = originalText;
                        feather.replace();
                    }, 2000);
                });
            }
            
            // Event listeners
            canvas.addEventListener('mousedown', startDrawing);
            canvas.addEventListener('mousemove', draw);
            canvas.addEventListener('mouseup', stopDrawing);
            canvas.addEventListener('mouseout', stopDrawing);
            
            // Touch support
            canvas.addEventListener('touchstart', (e) => {
                e.preventDefault();
                startDrawing(e);
            });
            canvas.addEventListener('touchmove', (e) => {
                e.preventDefault();
                draw(e);
            });
            canvas.addEventListener('touchend', stopDrawing);
            
            clearBtn.addEventListener('click', clearCanvas);
            copyBtn.addEventListener('click', copyText);
            
            // Instructions tooltip
            setTimeout(() => {
                const tooltip = document.createElement('div');
                tooltip.className = 'absolute bg-indigo-600 text-white px-4 py-2 rounded-lg shadow-lg z-10 animate-bounce';
                tooltip.style.top = '20px';
                tooltip.style.left = '50%';
                tooltip.style.transform = 'translateX(-50%)';
                tooltip.textContent = 'Draw here with your mouse or finger!';
                canvas.parentElement.appendChild(tooltip);
                
                setTimeout(() => {
                    tooltip.remove();
                }, 3000);
            }, 1000);
        });
    </script>
</body>
</html>