一、应用场景
我们经常需要将链接url生成二维码并下载,有时还需在图片上添加说明文字,如下图所示:

类似实现的在线工具有很多,在前端项目开发过程中要实现,以下说明一种方法,可直接copy使用:
二、实现方式:
1、安装QRCode
bash
npm install qrcode --save
或
bash
yarn add qrcode --save
2、封装一个根据url生成并下载的工具函数
我这里是vue+ts项目,封装了个工具函数generateQRCode, 可直接copy至项目中
javascript
import QRCode from 'qrcode'
/**
* 二维码图片配置选项
*/
export interface QRCodeImageOptions {
url: string // 要生成二维码的URL地址
fileName?: string // 下载的文件名,默认为'qrcode.png'
canvasWidth?: number // 画布宽度,当有文字内容时使用,默认为400
canvasHeight?: number // 画布高度,当有文字内容时使用,默认为400
qrSize?: number // 二维码尺寸,默认为380
textContent?: string // 文字内容,如果传入则显示文字,不传入则生成纯二维码
// 文字配置选项
textConfig?: {
x?: number // 文字起始X坐标
y?: number // 文字起始Y坐标
lineHeight?: number // 文字行高,默认为24
maxWidth?: number // 文字最大宽度,超过会自动换行
fontSize?: string // 文字字体样式,默认为'48px Microsoft YaHei'
color?: string // 文字颜色,默认为'black'
}
}
/**
* 文字换行处理函数
*/
function wrapText( ctx: CanvasRenderingContext2D, text: string, x: number, y: number, maxWidth: number, lineHeight: number): void {
const chars = text.split('')
let line = ''
let testLine = ''
// 设置精确文本测量基线
ctx.textBaseline = 'alphabetic'
let xCoord = x
for (let i = 0; i < chars.length; i++) {
testLine = line + chars[i]
const metrics = ctx.measureText(testLine)
if (metrics.width > maxWidth && i > 0) {
ctx.fillText(line, x, y)
line = chars[i]
y += lineHeight
} else {
line = testLine
// 居中显示文字
xCoord = (maxWidth - metrics.width) / 2 + 40
}
}
ctx.fillText(line, xCoord, y)
}
/**
* 生成并下载二维码图片
* @param options 二维码图片配置选项
* @returns Promise<boolean> 是否成功生成并下载
*/
export async function generateQRCode(options: QRCodeImageOptions): Promise<boolean> {
const {
url,
fileName = 'qrcode.png',
canvasWidth = 660,
canvasHeight = 700,
qrSize = 600,
textContent = '',
textConfig = {
x: 40,
y: 630,
lineHeight: 48,
maxWidth: 580, // canvasWidth - textConfig.x
fontSize: '48px Microsoft YaHei',
color: 'black'
}
} = options
try {
// 创建隐藏的canvas元素
const canvas = document.createElement('canvas')
// 如果有文字内容,使用更大的画布;否则使用二维码尺寸
if (textContent) {
canvas.width = canvasWidth
canvas.height = canvasHeight
} else {
canvas.width = qrSize
canvas.height = qrSize
}
const ctx = canvas.getContext('2d')
if (!ctx) {
throw new Error('无法获取canvas上下文')
}
// 绘制背景
ctx.fillStyle = 'white'
ctx.fillRect(0, 0, canvas.width, canvas.height)
// 生成二维码
const qrDataURL = await QRCode.toDataURL(url, { width: qrSize })
await new Promise<void>((resolve) => {
const img = new Image()
img.onload = () => {
// 如果有文字内容,居中绘制二维码;否则直接绘制
if (textContent) {
const margin = (canvasWidth - qrSize) / 2
ctx.drawImage(img, margin, 20, qrSize, qrSize)
} else {
ctx.drawImage(img, 0, 0, qrSize, qrSize)
}
resolve()
}
img.src = qrDataURL
})
// 如果有文字内容,绘制文字
if (textContent) {
// 设置文字样式
ctx.fillStyle = textConfig.color || 'black'
ctx.font = textConfig.fontSize || '48px "Microsoft YaHei", sans-serif'
ctx.textBaseline = 'alphabetic'
// 确保字体设置生效
await new Promise(resolve => setTimeout(resolve, 10))
wrapText(
ctx,
textContent,
textConfig.x || 40,
textConfig.y || 630,
textConfig.maxWidth || 580,
textConfig.lineHeight || 48
)
}
// 触发下载
const link = document.createElement('a')
link.download = fileName
link.href = canvas.toDataURL('image/png')
link.click()
// 清理canvas元素
canvas.remove()
return true
} catch (error) {
console.error('生成二维码失败:', error)
return false
}
}
3、在实际业务中调用
javascript
generateQRCode({
textContent: '你的描述文字',
fileName: '自定义文件名' || new Date().getTime() + ".png",
url: '生成二维码的链接url',
textConfig: { // 根据你需要配置,具体看函数定义说明
fontSize: 32px Microsoft YaHei',
lineHeight: 40,
}
})
end
希望记录的问题能帮助到你!