diff --git a/src/components/tools/QrCode.vue b/src/components/tools/QrCode.vue
index 9c15e98..8547cfa 100644
--- a/src/components/tools/QrCode.vue
+++ b/src/components/tools/QrCode.vue
@@ -13,9 +13,10 @@ const router = useRouter()
const text = useLocalStorage('text', '', 'qr-code')
const ecc = useLocalStorage('ecc', 'M', 'qr-code')
const size = useLocalStorage('size', 300, 'qr-code')
-const format = useLocalStorage('format', 'png', 'qr-code')
const isBgTransparent = useLocalStorage('isBgTransparent', true, 'qr-code')
-const bgColor = useLocalStorage('bgColor', '#ffffff', 'qr-code')
+const bgType = useLocalStorage('bgType', 'solid', 'qr-code')
+const bgColor1 = useLocalStorage('bgColor1', '#ffffff', 'qr-code')
+const bgColor2 = useLocalStorage('bgColor2', '#e2e8f0', 'qr-code')
const fgType = useLocalStorage('fgType', 'solid', 'qr-code')
const fgColor1 = useLocalStorage('fgColor1', '#000000', 'qr-code')
const fgColor2 = useLocalStorage('fgColor2', '#10b981', 'qr-code')
@@ -60,14 +61,16 @@ const generateQR = () => {
text: text.value,
ecc: ecc.value,
isBgTransparent: isBgTransparent.value,
- bgColor: bgColor.value,
+ bgType: bgType.value,
+ bgColor1: bgColor1.value,
+ bgColor2: bgColor2.value,
fgType: fgType.value,
fgColor1: fgColor1.value,
fgColor2: fgColor2.value
})
}
-watch([text, ecc, isBgTransparent, bgColor, fgType, fgColor1, fgColor2], () => {
+watch([text, ecc, isBgTransparent, bgType, bgColor1, bgColor2, fgType, fgColor1, fgColor2], () => {
generateQR()
})
@@ -128,6 +131,11 @@ const downloadFile = async () => {
if (format.value === 'jpeg' && isBgTransparent.value) {
ctx.fillStyle = '#ffffff'
ctx.fillRect(0, 0, size.value, size.value)
+ } else if (format.value === 'jpeg' && bgType.value !== 'solid') {
+ // Let the Canvas render the SVG's background gradient naturally instead of filling
+ // Though drawing bounding rect white might still be needed behind transparent parts
+ ctx.fillStyle = '#ffffff'
+ ctx.fillRect(0, 0, size.value, size.value)
}
ctx.drawImage(img, 0, 0, size.value, size.value)
@@ -204,10 +212,20 @@ const triggerDownload = (blob, filename) => {
-
+
+
+
+
+
+
-
-
@@ -216,7 +234,7 @@ const triggerDownload = (blob, filename) => {
diff --git a/src/workers/qrcode.worker.js b/src/workers/qrcode.worker.js
index e5e64c7..956bc94 100644
--- a/src/workers/qrcode.worker.js
+++ b/src/workers/qrcode.worker.js
@@ -1,7 +1,7 @@
import QRCode from 'qrcode'
self.onmessage = async (e) => {
- const { id, text, ecc, isBgTransparent, bgColor, fgType, fgColor1, fgColor2 } = e.data
+ const { id, text, ecc, isBgTransparent, bgType, bgColor1, bgColor2, fgType, fgColor1, fgColor2 } = e.data
if (!text) {
self.postMessage({ id, svgContent: '' })
@@ -15,19 +15,44 @@ self.onmessage = async (e) => {
margin: 1,
color: {
dark: fgType === 'solid' ? fgColor1 : '#000000',
- light: isBgTransparent ? '#00000000' : bgColor
+ light: isBgTransparent ? '#00000000' : (bgType === 'solid' ? bgColor1 : '#00000000')
}
})
+ let defsHtml = ''
+
if (fgType !== 'solid') {
const isLinear = fgType === 'linear'
- const defs = isLinear
- ? `
`
- : `
`
+ defsHtml += isLinear
+ ? `
`
+ : `
`
+ }
- svgContent = svgContent.replace('shape-rendering="crispEdges">', `shape-rendering="crispEdges">${defs}`)
+ if (!isBgTransparent && bgType !== 'solid') {
+ const isLinear = bgType === 'linear'
+ defsHtml += isLinear
+ ? `
`
+ : `
`
+ }
+
+ if (defsHtml) {
+ svgContent = svgContent.replace('shape-rendering="crispEdges">', `shape-rendering="crispEdges">
${defsHtml}`)
+ }
+
+ if (fgType !== 'solid') {
// qrcode outputs
so it's safe to replace
- svgContent = svgContent.replace(/stroke="#000000"/g, 'stroke="url(#qr-grad)"')
+ svgContent = svgContent.replace(/stroke="#000000"/g, 'stroke="url(#qr-fg-grad)"')
+ }
+
+ if (!isBgTransparent && bgType !== 'solid') {
+ // Find viewBox to inject background rect
+ const viewBoxMatch = svgContent.match(/viewBox="0 0 (\d+) (\d+)"/)
+ if (viewBoxMatch) {
+ const w = viewBoxMatch[1]
+ const h = viewBoxMatch[2]
+ // Inject a rect immediately inside the svg
+ svgContent = svgContent.replace('', ``)
+ }
}
self.postMessage({ id, svgContent })