84 lines
2.1 KiB
JavaScript
84 lines
2.1 KiB
JavaScript
import QRCode from 'qrcode'
|
|
|
|
function loadImage(src) {
|
|
return new Promise((resolve, reject) => {
|
|
const img = new Image()
|
|
img.crossOrigin = 'anonymous'
|
|
img.onload = () => resolve(img)
|
|
img.onerror = reject
|
|
img.src = src
|
|
})
|
|
}
|
|
|
|
/** 在 canvas 上绘制喜庆二维码,中心为配置图或圆圈大囍 */
|
|
export async function renderFestiveQr(canvas, url, options = {}) {
|
|
const size = options.size || 148
|
|
const centerImg = String(options.centerImg || '').trim()
|
|
|
|
await QRCode.toCanvas(canvas, url, {
|
|
width: size,
|
|
margin: 1,
|
|
color: {
|
|
dark: '#8b0000',
|
|
light: '#fff8e7',
|
|
},
|
|
errorCorrectionLevel: 'H',
|
|
})
|
|
|
|
const ctx = canvas.getContext('2d')
|
|
if (!ctx) return
|
|
|
|
const w = canvas.width
|
|
const h = canvas.height
|
|
const cx = w / 2
|
|
const cy = h / 2
|
|
const diameter = Math.round(Math.min(w, h) * 0.3)
|
|
const r = diameter / 2
|
|
const ring = Math.max(2, Math.round(w * 0.012))
|
|
|
|
ctx.save()
|
|
// 外圈底
|
|
ctx.beginPath()
|
|
ctx.arc(cx, cy, r + ring, 0, Math.PI * 2)
|
|
ctx.fillStyle = '#fff8e7'
|
|
ctx.fill()
|
|
ctx.strokeStyle = '#c41e3a'
|
|
ctx.lineWidth = ring
|
|
ctx.stroke()
|
|
|
|
let drewImg = false
|
|
if (centerImg) {
|
|
try {
|
|
const img = await loadImage(centerImg)
|
|
ctx.beginPath()
|
|
ctx.arc(cx, cy, r - 0.5, 0, Math.PI * 2)
|
|
ctx.clip()
|
|
const side = (r - 0.5) * 2
|
|
const scale = Math.max(side / img.width, side / img.height)
|
|
const dw = img.width * scale
|
|
const dh = img.height * scale
|
|
ctx.drawImage(img, cx - dw / 2, cy - dh / 2, dw, dh)
|
|
drewImg = true
|
|
} catch {
|
|
drewImg = false
|
|
}
|
|
}
|
|
|
|
if (!drewImg) {
|
|
ctx.beginPath()
|
|
ctx.arc(cx, cy, r - 0.5, 0, Math.PI * 2)
|
|
ctx.fillStyle = 'rgba(255, 248, 231, 0.96)'
|
|
ctx.fill()
|
|
ctx.strokeStyle = '#c41e3a'
|
|
ctx.lineWidth = Math.max(1.5, ring * 0.7)
|
|
ctx.stroke()
|
|
ctx.fillStyle = '#c41e3a'
|
|
ctx.font = `700 ${Math.round(r * 1.45)}px "Noto Serif SC","Source Han Serif SC","Songti SC",serif`
|
|
ctx.textAlign = 'center'
|
|
ctx.textBaseline = 'middle'
|
|
ctx.fillText('囍', cx, cy + r * 0.04)
|
|
}
|
|
|
|
ctx.restore()
|
|
}
|