<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>jsPDF</title>
	<atom:link href="https://www.hu365.dev/blog/tag/jspdf/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.hu365.dev</link>
	<description>Justin Woo（吴晓虎）的个人博客，生命不息，学习不止</description>
	<lastBuildDate>Sun, 18 Feb 2024 01:34:37 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.4.3</generator>

<image>
	<url>https://www.hu365.dev/wp-content/uploads/2022/10/cropped-logo-正矩形.blue_-32x32.png</url>
	<title>jsPDF</title>
	<link>https://www.hu365.dev</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>记录jsPdf相关使用</title>
		<link>https://www.hu365.dev/blog/2022/11/184/</link>
		
		<dc:creator><![CDATA[Justin]]></dc:creator>
		<pubDate>Wed, 30 Nov 2022 13:37:30 +0000</pubDate>
				<category><![CDATA[前端笔记]]></category>
		<category><![CDATA[html2canvas]]></category>
		<category><![CDATA[JAVASCRIPT]]></category>
		<category><![CDATA[jsPDF]]></category>
		<guid isPermaLink="false">https://www.hu365.dev/?p=184</guid>

					<description><![CDATA[相关文档： 一：我的需求 浏览器接口：window.print()，可以直接调用打印，并存储为PDF文档用工具库：html2canvas+jsPDF实现以上（类似的）PDF 二：我的实现 2.1：基础参数 首先定义一个标准数据，以Windows下的A4打印为基 <a href="https://www.hu365.dev/blog/2022/11/184/" class="cosmoswp-btn">阅读更多</a>]]></description>
										<content:encoded><![CDATA[
<p>相关文档：</p>



<ul>
<li><a href="https://artskydj.github.io/jsPDF/docs/jsPDF.html">jsPDF &#8211; Documentation (artskydj.github.io)</a></li>



<li><a href="https://html2canvas.hertzen.com/configuration">Options &#8211; html2canvas (hertzen.com)</a></li>
</ul>



<h2 class="wp-block-heading">一：我的需求</h2>



<p>浏览器接口：<code>window.print()</code>，可以直接调用打印，并存储为<code>PDF</code>文档<br>用工具库：<code>html2canvas</code>+<code>jsPDF</code>实现以上（类似的）<code>PDF</code></p>



<h2 class="wp-block-heading">二：我的实现</h2>



<h3 class="wp-block-heading">2.1：基础参数</h3>



<p>首先定义一个标准数据，以<code>Windows</code>下的<code>A4</code>打印为基础：</p>



<pre class="EnlighterJSRAW" data-enlighter-language="js" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// 基础参数
const printParams = {
	a4: {
		dpi: 96, // windows 下默认 dpi
		width: 210, // A4 标准宽度 mm，含边距
		height: 297, // A4 标准高度 mm， 含边距
		marginX: 10, // 默认打印左右边距，约为 10mm
		marginY: 10, // 默认打印上下边距，约为 10mm
	},
	// 以下是设置值/初始值
	dpi: 288, // 设置的打印密度，数值越大越清晰，PDF文件越大
	format: 'a4', // 打印类型，这里只有 A4
	orientation: 'portrait', // portrait | landscape
	// 以下为计算出的值，方便调用
	ratio: 1, // dpi 比例
	width: 0, // PDF 文档宽度，不含边距
	widthFull: 0, // PDF 文档完整宽度
	height: 0, // PDF 文档高度，不含边距
	heightFull: 0, // PDF 文档完整高度
	marginX: 0, // PDF 左右边距
	marginY: 0, // PDF 上下边距
}</pre>



<p>数据初始化：</p>



<pre class="EnlighterJSRAW" data-enlighter-language="js" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// 根据设置的 dpi，format，orientation 数据初始化
const { dpi: setDpi, orientation, format } = printParams;
const { dpi, width, height, marginX, marginY } = printParams[format];
printParams.ratio = setDpi/dpi;
let setWidth;
switch (orientation) {
	case 'landscape':
		printParams.width = height - 2 * marginY; // 不含边距的内容宽度
		printParams.height = width - 2 * marginX; // 不含边距的内容高度
		printParams.widthFull = height; // 整页PDF宽度
		printParams.heightFull = width; // 整页PDF高度
		printParams.marginX = marginY; // 左右单边边距
		printParams.marginY = marginX; // 上下单边边距
		setWidth = mm2px(height, dpi); // 页面宽度像素值
		break;
	case 'portrait':
	default:
		printParams.width = width - 2 * marginX;
		printParams.height = height - 2 * marginY;
		printParams.widthFull = width;
		printParams.heightFull = height;
		printParams.marginX = marginX;
		printParams.marginY = marginY;
		setWidth = mm2px(width, dpi);
}
// 设置body宽度，给 window.print 一个“最适合”的宽度
window.document.body.style.width = `${setWidth}px`;</pre>



<p>这里有用到一个<code>mm</code>/<code>px</code>的转换，把以前写过的方法拿过来：</p>



<pre class="EnlighterJSRAW" data-enlighter-language="js" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">/**
 * 工具类：mm转px
 * */
function mm2px(mm, dpi, radio) {
	if (mm == null) return 0;
	dpi = dpi || printParams.dpi;
	const ret = parseFloat(`${(mm * dpi * 10) / 254}`);
	if (radio == null || radio &lt;= 0) radio = 4;
	radio = 10 ** radio;
	return Math.floor(ret * radio) / radio;
}
/**
 * 工具类：px转mm
 * */
function px2mm(px, dpi, radio) {
	if (px == null) return 0;
	dpi = dpi || printParams.dpi;
	const ret = parseFloat(`${(px * 254) / (dpi * 10)}`);
	if (radio == null || radio &lt;= 0) radio = 4;
	radio = 10 ** radio;
	return Math.floor(ret * radio) / radio;
}</pre>



<h3 class="wp-block-heading">2.2：生成图片</h3>



<pre class="EnlighterJSRAW" data-enlighter-language="js" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// 需要用到的数据
const $pdfDom = document.getElementById('pdf');
const {
	ratio, orientation, format,
	width, height, widthFull, marginX, marginY
} = printParams;

html2canvas($pdfDom, {
	scale: window.devicePixelRatio * Math.ceil(ratio), // 缩放
	allowTaint: true,
	useCORS: true,
}).then((canvas) => {
	const canvasWidth = this.px2mm(canvas.width);
	const canvasHeight = this.px2mm(canvas.height);
	// ··· 以下是 pdf 生成
	// ···
});</pre>



<p>此处用到<code>html2canvas</code>实现绘制页面生成图片，主要影响清晰度的是参数<code>scale</code>：</p>



<figure class="wp-block-table is-style-stripes has-small-font-size"><table><tbody><tr><td width="90">scale</td><td width="280"><code>window.devicePixelRatio</code></td><td>The scale to use for rendering. Defaults to the browsers device pixel ratio.</td></tr></tbody></table></figure>



<p>默认值为<code>window.devicePixelRatio</code>，主要用于防止页面缩放导致的生成图片不清晰问题<br>为了实现更好地缩放，最好乘以一个整数值，以保证像素值的对应，就把它当作<code>windows</code>下的高分屏缩放理解就行</p>



<p>这里用<code>px2mm</code>转换成<code>mm</code>主要方便用于后面的<code>PDF</code>编辑</p>



<h3 class="wp-block-heading">2.3：生成PDF</h3>



<pre class="EnlighterJSRAW" data-enlighter-language="js" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">// 得到图片数据
const pageData = canvas.toDataURL('image/jpeg', 1.0);
// 创建PDF文档对象
const PDF = new JsPDF({ orientation, format });
// 标准宽度下，图片的相对高度
const imageHeight = (width / canvasWidth) * canvasHeight;
// 考虑可能有多页的情况，用 leftHeight 循环判断
let leftHeight = imageHeight;
// 每次绘制图片的位置垂直偏移量
let position = marginY;
while (leftHeight > 0) {
	// 1：图形绘制到PDF
	PDF.addImage(pageData, 'JPEG', marginX, position, width, imageHeight);
	leftHeight -= height;
	position -= height;
	// 2：页头页脚添加，用 rect 遮罩
	PDF.setFillColor(255, 255, 255); // 填充白色，每次填充前都要定义
	PDF.rect(0, 0, widthFull, marginY, 'F');
	PDF.rect(0, height + marginY, widthFull, marginY, 'F');
	// 添加空白页
	if (leftHeight > 0) {
		PDF.addPage();
	}
}
PDF.save(`${title}.pdf`);</pre>



<p>这里有几个点，需要留意：</p>



<ol>
<li>默认PDF为单页，需要判断“图片”相对高度，超出标准高度时添加新页面</li>



<li>每次添加新页面，<code>PDF</code>绘制即“当前页”，相对位置都是相对“当前页”而言</li>



<li>绘制遵循页面标准的层级，后绘制内容会覆盖已绘制内容</li>



<li>垂直偏移<code>position</code>是图片相对“当前页”的偏移，向上偏移一个内容页的距离后，当前页绘制的就是下一页该显示的图片内容</li>



<li>页眉页脚的模拟绘制，每次都要设置填充颜色（默认为黑色），因为每次都是“不同页”，参考第<code>2</code>点</li>
</ol>



<h2 class="wp-block-heading">三：实现效果</h2>



<p>目前只需要模拟<code>A4</code>下的打印，在对比使用<code>window.print()</code>生成的<code>PDF</code>和手动生成的<code>PDF</code>之后，还是比较满意的，以后再有自定义编辑页眉页脚，到时候再说</p>



<figure class="wp-block-image size-large"><a href="https://www.hu365.dev/wp-content/uploads/2022/11/lQLPJxbsCEPoFavNBJzNCfywOBr7ZJwPYlgDg8gWt8BwAA_2556_1180-jpeg.webp"><img data-dominant-color="dbdbdb" data-has-transparency="false" style="--dominant-color: #dbdbdb;" fetchpriority="high" decoding="async" width="1024" height="473" src="https://www.hu365.dev/wp-content/uploads/2022/11/lQLPJxbsCEPoFavNBJzNCfywOBr7ZJwPYlgDg8gWt8BwAA_2556_1180-1024x473.webp" alt="pdf对比" class="not-transparent wp-image-188" srcset="https://www.hu365.dev/wp-content/uploads/2022/11/lQLPJxbsCEPoFavNBJzNCfywOBr7ZJwPYlgDg8gWt8BwAA_2556_1180-1024x473.webp 1024w, https://www.hu365.dev/wp-content/uploads/2022/11/lQLPJxbsCEPoFavNBJzNCfywOBr7ZJwPYlgDg8gWt8BwAA_2556_1180-300x138.webp 300w, https://www.hu365.dev/wp-content/uploads/2022/11/lQLPJxbsCEPoFavNBJzNCfywOBr7ZJwPYlgDg8gWt8BwAA_2556_1180-768x355.webp 768w, https://www.hu365.dev/wp-content/uploads/2022/11/lQLPJxbsCEPoFavNBJzNCfywOBr7ZJwPYlgDg8gWt8BwAA_2556_1180-1536x709.webp 1536w, https://www.hu365.dev/wp-content/uploads/2022/11/lQLPJxbsCEPoFavNBJzNCfywOBr7ZJwPYlgDg8gWt8BwAA_2556_1180-2048x945.webp 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">看起来分页和边距都差不多</figcaption></figure>



<figure class="wp-block-image size-large"><a href="https://www.hu365.dev/wp-content/uploads/2022/11/lQLPJxbsCEPoFnLNBHzNCfqwF0k3xKX6TnMDg8gWwgAcAA_2554_1148-jpeg.webp"><img data-dominant-color="ededed" data-has-transparency="false" style="--dominant-color: #ededed;" decoding="async" width="1024" height="460" src="https://www.hu365.dev/wp-content/uploads/2022/11/lQLPJxbsCEPoFnLNBHzNCfqwF0k3xKX6TnMDg8gWwgAcAA_2554_1148-1024x460.webp" alt="PDF对比" class="not-transparent wp-image-189" srcset="https://www.hu365.dev/wp-content/uploads/2022/11/lQLPJxbsCEPoFnLNBHzNCfqwF0k3xKX6TnMDg8gWwgAcAA_2554_1148-1024x460.webp 1024w, https://www.hu365.dev/wp-content/uploads/2022/11/lQLPJxbsCEPoFnLNBHzNCfqwF0k3xKX6TnMDg8gWwgAcAA_2554_1148-300x135.webp 300w, https://www.hu365.dev/wp-content/uploads/2022/11/lQLPJxbsCEPoFnLNBHzNCfqwF0k3xKX6TnMDg8gWwgAcAA_2554_1148-768x345.webp 768w, https://www.hu365.dev/wp-content/uploads/2022/11/lQLPJxbsCEPoFnLNBHzNCfqwF0k3xKX6TnMDg8gWwgAcAA_2554_1148-1536x690.webp 1536w, https://www.hu365.dev/wp-content/uploads/2022/11/lQLPJxbsCEPoFnLNBHzNCfqwF0k3xKX6TnMDg8gWwgAcAA_2554_1148-2048x921.webp 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">清晰度也还满意</figcaption></figure>



<p>要说有什么不满意的地方，那肯定是哪里不满意再改哪里，哪里不购加哪里<br>不过呢，有个东西肯定只会越改（加）越糟的，那就是文件大小：</p>



<figure class="wp-block-image size-full"><a href="https://www.hu365.dev/wp-content/uploads/2022/11/710AAC88-0F98-42df-8A72-A372AEEE26EA-jpeg.webp"><img data-dominant-color="f5f6f7" data-has-transparency="false" style="--dominant-color: #f5f6f7;" decoding="async" width="983" height="297" src="https://www.hu365.dev/wp-content/uploads/2022/11/710AAC88-0F98-42df-8A72-A372AEEE26EA-jpeg.webp" alt="PDF文件大小对比" class="not-transparent wp-image-190" srcset="https://www.hu365.dev/wp-content/uploads/2022/11/710AAC88-0F98-42df-8A72-A372AEEE26EA-jpeg.webp 983w, https://www.hu365.dev/wp-content/uploads/2022/11/710AAC88-0F98-42df-8A72-A372AEEE26EA-300x91.webp 300w, https://www.hu365.dev/wp-content/uploads/2022/11/710AAC88-0F98-42df-8A72-A372AEEE26EA-768x232.webp 768w" sizes="(max-width: 983px) 100vw, 983px" /></a><figcaption class="wp-element-caption">2081 VS 124</figcaption></figure>



<p>Holy shit，大了整整20倍·····<br>这和生成图片时设置的缩放比（<code>scale</code>）有关，目前我测试时改值为<code>4.5</code>（<code>1.5*288/96</code>），既使变成<code>1/5</code>也还有400KB，大约4倍的差距，看来文件大小的劣势还是挺明显的</p>



<p>不过呢，现在谁还在乎这么点大小呢···谁还在乎呢···谁···</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
