67 lines
2.8 KiB
JavaScript
67 lines
2.8 KiB
JavaScript
import QRCode from 'qrcode'
|
|
|
|
self.onmessage = async (e) => {
|
|
const { id, text, ecc, isBgTransparent, bgType, bgColor1, bgColor2, bgGradPos, fgType, fgColor1, fgColor2, fgGradPos } = e.data
|
|
|
|
if (!text) {
|
|
self.postMessage({ id, svgContent: '' })
|
|
return
|
|
}
|
|
|
|
try {
|
|
let svgContent = await QRCode.toString(text, {
|
|
type: 'svg',
|
|
errorCorrectionLevel: ecc,
|
|
margin: 1,
|
|
color: {
|
|
dark: fgType === 'solid' ? fgColor1 : '#000000',
|
|
light: isBgTransparent ? '#00000000' : (bgType === 'solid' ? bgColor1 : '#00000000')
|
|
}
|
|
})
|
|
|
|
let defsHtml = ''
|
|
|
|
if (fgType !== 'solid') {
|
|
const isLinear = fgType === 'linear'
|
|
const pos = fgGradPos || { x1: 0, y1: 0, x2: 100, y2: 100 }
|
|
const r = Math.sqrt(Math.pow(pos.x2 - pos.x1, 2) + Math.pow(pos.y2 - pos.y1, 2))
|
|
defsHtml += isLinear
|
|
? `<linearGradient id="qr-fg-grad" x1="${pos.x1}%" y1="${pos.y1}%" x2="${pos.x2}%" y2="${pos.y2}%"><stop offset="0%" stop-color="${fgColor1}" /><stop offset="100%" stop-color="${fgColor2}" /></linearGradient>`
|
|
: `<radialGradient id="qr-fg-grad" cx="${pos.x1}%" cy="${pos.y1}%" r="${r}%"><stop offset="0%" stop-color="${fgColor1}" /><stop offset="100%" stop-color="${fgColor2}" /></radialGradient>`
|
|
}
|
|
|
|
if (!isBgTransparent && bgType !== 'solid') {
|
|
const isLinear = bgType === 'linear'
|
|
const pos = bgGradPos || { x1: 0, y1: 0, x2: 100, y2: 100 }
|
|
const r = Math.sqrt(Math.pow(pos.x2 - pos.x1, 2) + Math.pow(pos.y2 - pos.y1, 2))
|
|
defsHtml += isLinear
|
|
? `<linearGradient id="qr-bg-grad" x1="${pos.x1}%" y1="${pos.y1}%" x2="${pos.x2}%" y2="${pos.y2}%"><stop offset="0%" stop-color="${bgColor1}" /><stop offset="100%" stop-color="${bgColor2}" /></linearGradient>`
|
|
: `<radialGradient id="qr-bg-grad" cx="${pos.x1}%" cy="${pos.y1}%" r="${r}%"><stop offset="0%" stop-color="${bgColor1}" /><stop offset="100%" stop-color="${bgColor2}" /></radialGradient>`
|
|
}
|
|
|
|
if (defsHtml) {
|
|
svgContent = svgContent.replace('shape-rendering="crispEdges">', `shape-rendering="crispEdges"><defs>${defsHtml}</defs>`)
|
|
}
|
|
|
|
if (fgType !== 'solid') {
|
|
// qrcode outputs <path stroke="#000000"...> so it's safe to replace
|
|
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('</defs>', `</defs><rect width="${w}" height="${h}" fill="url(#qr-bg-grad)" />`)
|
|
}
|
|
}
|
|
|
|
self.postMessage({ id, svgContent })
|
|
} catch (err) {
|
|
self.postMessage({ id, error: err.message })
|
|
}
|
|
}
|