-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
133 lines (115 loc) · 6.45 KB
/
Copy pathindex.html
File metadata and controls
133 lines (115 loc) · 6.45 KB
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
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Free QR Code Generator | Create & Download QR Codes Online</title>
<meta name="description" content="Free QR Code Generator. Instantly create and download QR codes online as PNG or SVG. No signup required — fast, secure, and free." />
<meta name="keywords" content="free qr code generator, qr code, qr code maker, qr generator, qr code online, qr code png, qr code svg, create qr code" />
<meta name="author" content="Free QR Code Generator" />
<link rel="canonical" href="https://yourdomain.com/qr-generator" />
<script src="https://cdn.tailwindcss.com"></script>
<style>
#qrCanvas { width: 100%; height: auto; }
</style>
</head>
<body class="bg-gradient-to-br from-blue-50 to-blue-100 min-h-screen flex items-center justify-center p-6">
<div class="max-w-xl w-full bg-white rounded-2xl shadow-2xl p-8 border border-gray-200">
<h1 class="text-3xl font-bold mb-2 text-gray-800 text-center">Free QR Code Generator</h1>
<p class="text-sm text-gray-500 mb-6 text-center">Generate and download free QR codes instantly — no signup required.</p>
<label class="block mb-2 text-sm font-medium text-gray-700">URL</label>
<div class="flex gap-2 mb-6">
<input id="urlInput" type="url" placeholder="https://example.com" class="flex-1 px-4 py-3 border rounded-xl shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
<button id="generateBtn" class="px-6 py-3 bg-blue-600 text-white rounded-xl shadow hover:bg-blue-700 transition">Generate</button>
</div>
<div class="mb-6">
<label class="block text-sm font-medium text-gray-700 mb-2">Size</label>
<input id="sizeRange" type="range" min="128" max="1024" value="300" class="w-full accent-blue-600" />
<div class="text-xs text-gray-500 mt-1"><span id="sizeLabel">300</span> px</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 items-start">
<div class="bg-gray-50 rounded-xl p-6 flex flex-col items-center border border-gray-200 shadow-sm">
<div id="qrHolder" class="mb-4">
<canvas id="qrCanvas"></canvas>
</div>
<div class="text-sm text-gray-600">Preview</div>
</div>
<div class="flex flex-col gap-3">
<button id="downloadPng" class="w-full px-4 py-3 bg-green-600 text-white rounded-xl shadow hover:bg-green-700 transition">Download PNG</button>
<button id="downloadSvg" class="w-full px-4 py-3 bg-indigo-600 text-white rounded-xl shadow hover:bg-indigo-700 transition">Download SVG</button>
<button id="copyBtn" class="w-full px-4 py-3 bg-gray-700 text-white rounded-xl shadow hover:bg-gray-800 transition">Copy URL to clipboard</button>
<div id="error" class="text-sm text-red-600 mt-1"></div>
</div>
</div>
<footer class="mt-8 text-xs text-gray-400 text-center space-y-2">
<div>⚡ Free QR Code Generator — all QR codes are created securely in your browser. No data leaves your device.</div>
<div class="text-gray-500">Sponsored by <a href="https://fabform.io" target="_blank" rel="noopener" class="text-blue-600 hover:underline">Fabform.io</a> — the Typeform alternative.</div>
</footer>
</div>
<!-- QRCode library (browser bundle) -->
<script src="https://cdn.jsdelivr.net/npm/qrcode@1.5.1/build/qrcode.min.js"></script>
<script>
const urlInput = document.getElementById('urlInput');
const generateBtn = document.getElementById('generateBtn');
const qrCanvas = document.getElementById('qrCanvas');
const downloadPng = document.getElementById('downloadPng');
const downloadSvg = document.getElementById('downloadSvg');
const copyBtn = document.getElementById('copyBtn');
const sizeRange = document.getElementById('sizeRange');
const sizeLabel = document.getElementById('sizeLabel');
const errorEl = document.getElementById('error');
let currentUrl = '';
function setError(msg) { errorEl.textContent = msg || ''; }
function validUrl(s) {
try { const u = new URL(s); return u.protocol === 'http:' || u.protocol === 'https:'; } catch (e) { return false; }
}
async function renderQR(url, size) {
setError('');
if (!validUrl(url)) { setError('Please enter a valid http:// or https:// URL.'); return; }
currentUrl = url;
qrCanvas.width = size;
qrCanvas.height = size;
try { await QRCode.toCanvas(qrCanvas, url, { width: size, margin: 1 }); }
catch (err) { setError('Failed to generate QR code: ' + err.message); }
}
generateBtn.addEventListener('click', () => {
const url = urlInput.value.trim();
renderQR(url, Number(sizeRange.value));
});
sizeRange.addEventListener('input', () => { sizeLabel.textContent = sizeRange.value; });
downloadPng.addEventListener('click', () => {
if (!currentUrl) { setError('Generate a QR code first.'); return; }
try {
const dataUrl = qrCanvas.toDataURL('image/png');
const a = document.createElement('a');
a.href = dataUrl; a.download = 'qr.png';
document.body.appendChild(a); a.click(); a.remove();
} catch (e) { setError('Failed to download PNG: ' + e.message); }
});
downloadSvg.addEventListener('click', async () => {
if (!currentUrl) { setError('Generate a QR code first.'); return; }
try {
const svgString = await QRCode.toString(currentUrl, { type: 'svg', width: Number(sizeRange.value), margin: 1 });
const blob = new Blob([svgString], { type: 'image/svg+xml' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url; a.download = 'qr.svg';
document.body.appendChild(a); a.click(); a.remove();
URL.revokeObjectURL(url);
} catch (e) { setError('Failed to create SVG: ' + e.message); }
});
copyBtn.addEventListener('click', async () => {
const url = urlInput.value.trim();
if (!url) { setError('No URL to copy.'); return; }
try {
await navigator.clipboard.writeText(url);
setError('URL copied to clipboard.');
setTimeout(() => setError(''), 1500);
} catch (e) { setError('Failed to copy: ' + e.message); }
});
urlInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') { e.preventDefault(); generateBtn.click(); } });
urlInput.value = 'https://example.com';
renderQR(urlInput.value.trim(), Number(sizeRange.value));
</script>
</body>
</html>