如何在JavaScript服务端将API获取的SVG二维码旋转45度
解决方案
问题分析
核心问题是svgToImg函数用法错误,同时画布旋转逻辑存在疏漏——原代码先绘制未旋转的图片,再旋转画布重绘,导致两张图重叠。另外,直接操作SVG文本实现旋转比转PNG再处理更高效。
方案一:修正PNG转换与旋转逻辑
用你已引入的svg2img替代svgToImg,调整画布旋转的正确步骤:
const { createCanvas } = require("canvas"); const svg2img = require("svg2img"); const axios = require("axios"); async function processQrCode(qrCodeData) { const qrCodeSvgUrl = qrCodeData.data.qr_code; // 获取SVG文本 const svgResponse = await axios.get(qrCodeSvgUrl, { responseType: "text" }); const qrCodeSvg = svgResponse.data; // 将SVG转为PNG Buffer const pngBuffer = await new Promise((resolve, reject) => { svg2img(qrCodeSvg, { width: 200, height: 200 }, (error, buffer) => { if (error) reject(error); else resolve(buffer); }); }); // 创建画布并处理旋转 const canvas = createCanvas(283, 283); // 旋转后正方形变菱形,扩大画布避免裁剪 const ctx = canvas.getContext("2d"); // 移动原点到画布中心,旋转45度 ctx.translate(canvas.width / 2, canvas.height / 2); ctx.rotate((45 * Math.PI) / 180); // 绘制图片到旋转后的画布(中心对齐) const img = new canvas.Image(); img.src = pngBuffer; ctx.drawImage(img, -img.width / 2, -img.height / 2); // 获取旋转后的PNG Buffer const rotatedPngBuffer = canvas.toBuffer(); qrCodeData.data.qr_code = rotatedPngBuffer; // 后续存入数据库逻辑... }
关键修正点:
- 将
svg2img的回调转为Promise,适配async/await逻辑 - 扩大画布尺寸:正方形旋转45度后对角线为原边长的√2倍,200*1.414≈283,防止二维码被裁剪
- 调整旋转顺序:先平移原点、旋转画布,再绘制图片,确保只渲染旋转后的内容
方案二:直接修改SVG文本实现旋转(更高效)
无需转换格式,直接给SVG根元素添加transform属性实现旋转,处理速度更快:
const axios = require("axios"); async function processQrCode(qrCodeData) { const qrCodeSvgUrl = qrCodeData.data.qr_code; const svgResponse = await axios.get(qrCodeSvgUrl, { responseType: "text" }); let qrCodeSvg = svgResponse.data; // 给SVG根元素添加旋转属性(以中心为原点旋转45度) const svgWidth = 200; // 可从SVG文本中提取实际宽高 const svgHeight = 200; const transform = `rotate(45 ${svgWidth/2} ${svgHeight/2})`; // 替换svg标签,插入transform属性 qrCodeSvg = qrCodeSvg.replace(/<svg/, `<svg transform="${transform}"`); // 若需转PNG,取消下方注释 // const rotatedPngBuffer = await new Promise((resolve, reject) => { // svg2img(qrCodeSvg, { width: svgWidth, height: svgHeight }, (error, buffer) => { // error ? reject(error) : resolve(buffer); // }); // }); // qrCodeData.data.qr_code = rotatedPngBuffer; // 直接存储修改后的SVG文本 qrCodeData.data.qr_code = qrCodeSvg; // 后续存入数据库逻辑... }
优势:
- 避免格式转换的性能损耗
- 保留SVG的矢量特性(若数据库支持存储SVG文本)
- 代码更简洁,无需依赖canvas库
内容的提问来源于stack exchange,提问作者program.exe
相关产品推荐
相关产品推荐

