diff --git a/src/assets/js/qr-code.js b/src/assets/js/qr-code.js
index c141e1a..21d2182 100644
--- a/src/assets/js/qr-code.js
+++ b/src/assets/js/qr-code.js
@@ -4,6 +4,15 @@ import {
writeBarcode,
} from 'zxing-wasm/full';
+/** 默认背景颜色 */
+const DEFAULT_BGC = 'transparent';
+
+/** 默认前景颜色 */
+const DEFAULT_FGC = '#000000';
+
+/** 模块名称 */
+const PREFIX = '[qr-code]';
+
/**
* @desc 二维码读取配置选项
* @type { import('zxing-wasm').ReaderOptions }
@@ -25,7 +34,7 @@ const readerOptions = {
const writerOptions = {
ecLevel: '',
format: 'QRCode',
- scale: 1,
+ scale: 0,
};
// 配置 wasm 文件路径
@@ -46,7 +55,7 @@ prepareZXingModule({
* @param {Blob} blob
* @param {Callback} callback
*/
-export function blobToDataURL(blob, callback) {
+function blobToDataURL(blob, callback) {
/** @typedef {(data: { error: boolean, result: string }) => void} Callback */
@@ -70,11 +79,77 @@ export function blobToDataURL(blob, callback) {
}
+/**
+ * @description 修改 SVG 内容,获取信息
+ * @param {object} options
+ * @param {string} options.background
+ * @param {string} options.foreground
+ * @param {string} options.svgString
+ */
+function modifySvgContent(options) {
+
+ let {
+ background = DEFAULT_BGC,
+ foreground = DEFAULT_FGC,
+ svgString,
+ } = options;
+
+ let divElement = document.createElement('div');
+ let gElement = null;
+ let pathElement = null;
+ let rectElement = null;
+ let svgElement = null;
+
+ // 添加 DOM 元素,用于获取位置大小信息
+ document.body.appendChild(divElement);
+
+ divElement.innerHTML = svgString;
+ gElement = divElement.getElementsByTagName('g')[0] || null;
+ pathElement = divElement.getElementsByTagName('path')[0] || null;
+ rectElement = divElement.getElementsByTagName('rect')[0] || null;
+ svgElement = divElement.getElementsByTagName('svg')[0] || null;
+
+ if (!(gElement && pathElement && rectElement && svgElement)) {
+ return null;
+ }
+
+ // 修改填充颜色
+ gElement.setAttribute('fill', foreground);
+ rectElement.setAttribute('fill', background);
+
+ // 获取位置大小信息
+ let rectOfG = gElement.getBoundingClientRect();
+ let rectOfPath = pathElement.getBoundingClientRect();
+
+ let offsetX = Math.round(rectOfPath.left - rectOfG.left);
+ let offsetY = Math.round(rectOfPath.top - rectOfG.top);
+ let sizeW = Math.round(rectOfPath.width);
+ let sizeH = Math.round(rectOfPath.height);
+ let result = {
+ offsetX: offsetX,
+ offsetY: offsetY,
+ sizeW: sizeW,
+ sizeH: sizeH,
+ svgString: divElement.innerHTML,
+ };
+
+ // 输出处理结果
+ console.debug(PREFIX, '处理 SVG', result);
+
+ // 处理完成,移除 DOM 元素
+ document.body.removeChild(divElement);
+
+ return result;
+
+}
+
/**
* @description 将 SVG 字符串渲染到 Canvas
* @param {object} options
* @param {HTMLCanvasElement} options.canvas
* @param {string} options.svgString
+ * @param {string} options.background
+ * @param {string} options.foreground
* @param {number} options.drawLeft
* @param {number} options.drawTop
* @param {number} options.drawWidth
@@ -85,27 +160,42 @@ function renderSvgToCanvas(options) {
let {
canvas, svgString,
+ background = DEFAULT_BGC, foreground = DEFAULT_FGC,
drawLeft = 0, drawTop = 0,
drawWidth = 0, drawHeight = 0,
} = options;
+ let svgInfo = modifySvgContent({
+ background: background,
+ foreground: foreground,
+ svgString: svgString,
+ });
+
+ if (!svgInfo) {
+ return Promise.resolve(false);
+ }
+
return new Promise((resolve) => {
- let svgBlob = new Blob([svgString], {
+ let svgBlob = new Blob([svgInfo.svgString], {
type: 'image/svg+xml;charset=utf-8',
});
let svgUrl = URL.createObjectURL(svgBlob);
let image = new Image();
image.onerror = () => {
- console.error('加载 SVG 失败');
+ console.error(PREFIX, '加载 SVG 失败');
URL.revokeObjectURL(svgUrl);
resolve(false);
};
image.onload = () => {
let ctx = canvas.getContext('2d');
- ctx.drawImage(image, drawLeft, drawTop, drawWidth, drawHeight);
+ ctx.drawImage(
+ image,
+ svgInfo.offsetX, svgInfo.offsetY, svgInfo.sizeW, svgInfo.sizeH,
+ drawLeft, drawTop, drawWidth, drawHeight,
+ );
URL.revokeObjectURL(svgUrl);
resolve(true);
};
@@ -138,7 +228,7 @@ export function readQrCodeImage(image) {
// 处理读取异常
fileReader.onerror = function () {
- console.error('解析二维码失败:读取图片失败');
+ console.error(PREFIX, '解析二维码失败:读取图片失败');
returns.error = '读取图片失败';
resolve('');
};
@@ -163,10 +253,10 @@ export function readQrCodeImage(image) {
let textList = returns.textList;
if (resultList.length === 0) {
- console.warn('解析二维码失败:未识别到内容');
+ console.warn(PREFIX, '解析二维码失败:未识别到内容');
return returns;
} else {
- console.debug('解析二维码成功:', resultList);
+ console.debug(PREFIX, '解析二维码成功:', resultList);
}
for (let i = 0; i < resultList.length; i++) {
@@ -180,7 +270,7 @@ export function readQrCodeImage(image) {
return returns;
}).catch((error) => {
- console.error('解析二维码失败:');
+ console.error(PREFIX, '解析二维码失败:');
console.error(error);
returns.error = String(error);
return returns;
@@ -192,13 +282,19 @@ export function readQrCodeImage(image) {
* @description 生成二维码图片
* @param {object} options
* @param {string} options.content
+ * @param {string} options.background
+ * @param {string} options.foreground
* @param {number} options.width
* @param {number} options.height
* @returns 二维码图片 DataURL
*/
export function writeQrCodeImage(options = {}) {
- let { content = '', width = 256, height = 256 } = options;
+ let {
+ content = '',
+ background = DEFAULT_BGC, foreground = DEFAULT_FGC,
+ width = 256, height = 256,
+ } = options;
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
@@ -208,15 +304,15 @@ export function writeQrCodeImage(options = {}) {
canvas.height = height;
// 设置背景颜色
- ctx.fillStyle = '#FFFFFF';
+ ctx.fillStyle = background;
ctx.fillRect(0, 0, width, height);
return writeBarcode(content, writerOptions).then((result) => {
- console.debug('生成二维码', result);
+ console.debug(PREFIX, '生成二维码', result);
if (result.error) {
- console.error(`生成二维码失败:${result.error}`);
+ console.error(PREFIX, `生成二维码失败:${result.error}`);
return '';
} else {
return result.svg;
@@ -227,6 +323,8 @@ export function writeQrCodeImage(options = {}) {
return renderSvgToCanvas({
canvas: canvas,
svgString: svgString,
+ background: background,
+ foreground: foreground,
drawLeft: 0,
drawTop: 0,
drawWidth: width,
@@ -244,7 +342,7 @@ export function writeQrCodeImage(options = {}) {
}
}).catch((error) => {
- console.error('生成二维码失败:');
+ console.error(PREFIX, '生成二维码失败:');
console.error(error);
return '';
});
diff --git a/src/views/ToolboxView/Conversion/QrcodeReaderAndGenerator.vue b/src/views/ToolboxView/Conversion/QrcodeReaderAndGenerator.vue
index 87325ce..31cd37a 100644
--- a/src/views/ToolboxView/Conversion/QrcodeReaderAndGenerator.vue
+++ b/src/views/ToolboxView/Conversion/QrcodeReaderAndGenerator.vue
@@ -3,6 +3,14 @@
+
+ 清空
+
-
+
+
+
+ 生成
+ 下载
+ 清空
+
+
+ >
+
+
+
+
+
+
+
+
+ px
+
+
+
+
+
+ 前景颜色:
+
+ 背景颜色:
+
+
+
+
+
+
+
+
+
@@ -72,9 +161,9 @@