在 PDF 文件上打印生成的二维码
Printing generated QR codes on a PDF file
我正在创建一个使用 QR 码的 ReactJS 应用程序,我希望能够一次打印带有一批代码的 PDF 文档。我目前正在使用 react-qr-svg to generate the codes and @react-pdf/renderer 来创建文档。问题是我一直无法在文档上显示这些二维码。
首先,我尝试使用来自@react-pdf/renderer 的图片标签,如下所示:
<Image
src={<QRCode
level="Q"
style={{width: 256, marginBottom: 50 }}
value={'hello world'}
/>}
/>
Whick 当然没有用,之后我尝试将 SVG 转换为数据缓冲区但没有结果。
有什么直接的解决方案吗?我应该为此项目使用其他库吗?
直接来自文档:https://www.npmjs.com/package/react-qr-svg
你不需要把它放在图片标签中。
我的假设是这个库输出 <svg> ... </svg>
(即有效的 HTML 标签直接输出)
可以直接把tag/element输出出来吗?
import React from "react";
import { QRCode } from "react-qr-svg";
class Demo extends React.Component {
render() {
return (
<QRCode
bgColor="#FFFFFF"
fgColor="#000000"
level="Q"
style={{ width: 256 }}
value="some text"
/>
);
}
}
更新
如果我理解正确的话,我们不能简单地在页面上输出<svg>...</svg>
,因为库@react-pdf/renderer 不能使用svg 标签。所以我建议我们将 svg 序列化为 base-64 字符串,将其分配给图像标签的 src 然后它应该可以工作。
我做了一个没有库的简化演示:https://codepen.io/Alexander9111/pen/QWweYXO
HTML(简体):
<svg>
<ellipse class="ground" fill="##787f6a" cx="283.5" cy="487.5" rx="259" ry="80"/>
<path class="kiwi" fill="#94d31b" d="M210.333,65.331C104.367,...,203.01z"/>
</svg>
<div id="target">
<!-- place to put our img tag -->
</div>
JS:
const svg = document.querySelector("svg");
const serializer = new XMLSerializer();
const svgStr = serializer.serializeToString(svg);
const img = document.createElement("img")
img.src = 'data:image/svg+xml;base64,'+ window.btoa(svgStr);
const target = document.querySelector("#target");
target.appendChild(img);
svg.parentNode.removeChild(svg);
现在,如果我们想在 React 中执行此操作,我想我们可以这样做:
import React from "react";
import { QRCode } from "react-qr-svg";
class Demo extends React.Component {
render() {
const svg = function {
return (<QRCode
level="Q"
style={{width: 256, marginBottom: 50 }}
value={'hello world'}
/>);
};
const serializer = new XMLSerializer();
const svgStr = serializer.serializeToString(svg);
const img_src = 'data:image/svg+xml;base64,'+ window.btoa(svgStr);
return (
<img src={ img_src }/>
);
}
}
或 我们或许可以使用生命周期钩子来做到这一点,例如 componentDidMount()
import React from "react";
import { QRCode } from "react-qr-svg";
class Demo extends React.Component {
componentDidMount() {
const div = this.refs.target;
const svg = div.querySelector("svg");
const serializer = new XMLSerializer();
const svgStr = serializer.serializeToString(svg);
const img = this.refs.img;
img.src = 'data:image/svg+xml;base64,'+ window.btoa(svgStr);
svg.parentNode.removeChild(svg);
}
render() {
return (<div ref="target">
<QRCode
level="Q"
style={{width: 256, marginBottom: 50 }}
value={'hello world'}
/>
<img ref="img"/>
</div>
)
}
}
更新 - 我让它在 CodePen 上的 React 中工作:https://codepen.io/Alexander9111/pen/GRJKQQK
HTML: <div id="root"></div>
CSS: svg{border: 2px solid black;} img{border: 2px solid blue;}
反应 JS:
class Demo extends React.Component {
componentDidMount() {
const div = this.refs.target;
const svg = div.querySelector("svg");
console.log(svg);
const serializer = new XMLSerializer();
const svgStr = serializer.serializeToString(svg);
const img = this.refs.img;
console.log(img);
img.src = 'data:image/svg+xml;base64,'+ window.btoa(svgStr);
svg.parentNode.removeChild(svg);
}
render() {
return (
<div ref="target">
<svg width="400" height="400">
<circle r="100" cx="200" cy="200" fill="red" />
</svg>
<img ref="img"/>
</div>
);
}
}
ReactDOM.render(
<Demo/>,
document.getElementById('root')
);
我使用 qrcode.react
和 @react-pdf/renderer
。
您需要做的第一件事是将 QR canvas 转换为 base64
const qrCodeCanvas = document.querySelector('canvas');
const qrCodeDataUri = qrCodeCanvas.toDataURL('image/jpg', 0.3);
然后,将 base64 字符串 (qrCodeDataUri
) 作为道具传递给 @react-pdf/renderer
图片标签源中的 PDF 组件:
<Image source={ {uri: props.yourBase64Image} } />
我的解决方案不会将初始 svg 写入 DOM,而是将 React 组件转换为静态标记。然后我解析该标记以在 @react-pdf/renderer
支持的 Svg 组件中使用它的属性。
import React from 'react';
import { Text, View, Svg, Path } from '@react-pdf/renderer';
import { renderToStaticMarkup } from 'react-dom/server';
import ReactHtmlParser from 'react-html-parser';
import QRCode from 'qrcode.react';
const PdfWithQrCode = () => {
const qrCodeComponent = (
<QRCode
value={ssf_id}
renderAs="svg"
size={80}
/>
);
const qrCodeComponentStaticMarkup = renderToStaticMarkup(qrCodeComponent);
const parsedQrCodeSvg = parseQrCodeMarkup(qrCodeComponentStaticMarkup);
if (! parsedQrCodeSvg) {
return null;
}
return (
<View>
<Svg
style={{ width: 50, height: 50 }}
viewBox="0 0 29 29"
>
{parsedQrCodeSvg.props.children.filter(c => c.type === 'path').map((child, index) => (
<Path
key={index}
d={child.props.d}
fill={child.props.fill}
/>
))}
</Svg>
</View>
);
}
const parseQrCodeMarkup = (markup) => {
let parsedQrCodeSvg = null;
ReactHtmlParser(markup).forEach(el => {
const { type } = el;
if (type === 'svg') {
parsedQrCodeSvg = el;
}
});
return parsedQrCodeSvg;
};
export default PdfWithQrCode;
我正在创建一个使用 QR 码的 ReactJS 应用程序,我希望能够一次打印带有一批代码的 PDF 文档。我目前正在使用 react-qr-svg to generate the codes and @react-pdf/renderer 来创建文档。问题是我一直无法在文档上显示这些二维码。
首先,我尝试使用来自@react-pdf/renderer 的图片标签,如下所示:
<Image
src={<QRCode
level="Q"
style={{width: 256, marginBottom: 50 }}
value={'hello world'}
/>}
/>
Whick 当然没有用,之后我尝试将 SVG 转换为数据缓冲区但没有结果。
有什么直接的解决方案吗?我应该为此项目使用其他库吗?
直接来自文档:https://www.npmjs.com/package/react-qr-svg
你不需要把它放在图片标签中。
我的假设是这个库输出 <svg> ... </svg>
(即有效的 HTML 标签直接输出)
可以直接把tag/element输出出来吗?
import React from "react";
import { QRCode } from "react-qr-svg";
class Demo extends React.Component {
render() {
return (
<QRCode
bgColor="#FFFFFF"
fgColor="#000000"
level="Q"
style={{ width: 256 }}
value="some text"
/>
);
}
}
更新
如果我理解正确的话,我们不能简单地在页面上输出<svg>...</svg>
,因为库@react-pdf/renderer 不能使用svg 标签。所以我建议我们将 svg 序列化为 base-64 字符串,将其分配给图像标签的 src 然后它应该可以工作。
我做了一个没有库的简化演示:https://codepen.io/Alexander9111/pen/QWweYXO
HTML(简体):
<svg>
<ellipse class="ground" fill="##787f6a" cx="283.5" cy="487.5" rx="259" ry="80"/>
<path class="kiwi" fill="#94d31b" d="M210.333,65.331C104.367,...,203.01z"/>
</svg>
<div id="target">
<!-- place to put our img tag -->
</div>
JS:
const svg = document.querySelector("svg");
const serializer = new XMLSerializer();
const svgStr = serializer.serializeToString(svg);
const img = document.createElement("img")
img.src = 'data:image/svg+xml;base64,'+ window.btoa(svgStr);
const target = document.querySelector("#target");
target.appendChild(img);
svg.parentNode.removeChild(svg);
现在,如果我们想在 React 中执行此操作,我想我们可以这样做:
import React from "react";
import { QRCode } from "react-qr-svg";
class Demo extends React.Component {
render() {
const svg = function {
return (<QRCode
level="Q"
style={{width: 256, marginBottom: 50 }}
value={'hello world'}
/>);
};
const serializer = new XMLSerializer();
const svgStr = serializer.serializeToString(svg);
const img_src = 'data:image/svg+xml;base64,'+ window.btoa(svgStr);
return (
<img src={ img_src }/>
);
}
}
或 我们或许可以使用生命周期钩子来做到这一点,例如 componentDidMount()
import React from "react";
import { QRCode } from "react-qr-svg";
class Demo extends React.Component {
componentDidMount() {
const div = this.refs.target;
const svg = div.querySelector("svg");
const serializer = new XMLSerializer();
const svgStr = serializer.serializeToString(svg);
const img = this.refs.img;
img.src = 'data:image/svg+xml;base64,'+ window.btoa(svgStr);
svg.parentNode.removeChild(svg);
}
render() {
return (<div ref="target">
<QRCode
level="Q"
style={{width: 256, marginBottom: 50 }}
value={'hello world'}
/>
<img ref="img"/>
</div>
)
}
}
更新 - 我让它在 CodePen 上的 React 中工作:https://codepen.io/Alexander9111/pen/GRJKQQK
HTML: <div id="root"></div>
CSS: svg{border: 2px solid black;} img{border: 2px solid blue;}
反应 JS:
class Demo extends React.Component {
componentDidMount() {
const div = this.refs.target;
const svg = div.querySelector("svg");
console.log(svg);
const serializer = new XMLSerializer();
const svgStr = serializer.serializeToString(svg);
const img = this.refs.img;
console.log(img);
img.src = 'data:image/svg+xml;base64,'+ window.btoa(svgStr);
svg.parentNode.removeChild(svg);
}
render() {
return (
<div ref="target">
<svg width="400" height="400">
<circle r="100" cx="200" cy="200" fill="red" />
</svg>
<img ref="img"/>
</div>
);
}
}
ReactDOM.render(
<Demo/>,
document.getElementById('root')
);
我使用 qrcode.react
和 @react-pdf/renderer
。
您需要做的第一件事是将 QR canvas 转换为 base64
const qrCodeCanvas = document.querySelector('canvas');
const qrCodeDataUri = qrCodeCanvas.toDataURL('image/jpg', 0.3);
然后,将 base64 字符串 (qrCodeDataUri
) 作为道具传递给 @react-pdf/renderer
图片标签源中的 PDF 组件:
<Image source={ {uri: props.yourBase64Image} } />
我的解决方案不会将初始 svg 写入 DOM,而是将 React 组件转换为静态标记。然后我解析该标记以在 @react-pdf/renderer
支持的 Svg 组件中使用它的属性。
import React from 'react';
import { Text, View, Svg, Path } from '@react-pdf/renderer';
import { renderToStaticMarkup } from 'react-dom/server';
import ReactHtmlParser from 'react-html-parser';
import QRCode from 'qrcode.react';
const PdfWithQrCode = () => {
const qrCodeComponent = (
<QRCode
value={ssf_id}
renderAs="svg"
size={80}
/>
);
const qrCodeComponentStaticMarkup = renderToStaticMarkup(qrCodeComponent);
const parsedQrCodeSvg = parseQrCodeMarkup(qrCodeComponentStaticMarkup);
if (! parsedQrCodeSvg) {
return null;
}
return (
<View>
<Svg
style={{ width: 50, height: 50 }}
viewBox="0 0 29 29"
>
{parsedQrCodeSvg.props.children.filter(c => c.type === 'path').map((child, index) => (
<Path
key={index}
d={child.props.d}
fill={child.props.fill}
/>
))}
</Svg>
</View>
);
}
const parseQrCodeMarkup = (markup) => {
let parsedQrCodeSvg = null;
ReactHtmlParser(markup).forEach(el => {
const { type } = el;
if (type === 'svg') {
parsedQrCodeSvg = el;
}
});
return parsedQrCodeSvg;
};
export default PdfWithQrCode;