2025-02-21
html2canvas生成图片、vue-plugin-hiprint生成PDF后第三方字体丢失

核心原理是,动态生成的canvas元素,要在绘制之前,插入到真实的DOM中去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// 处理html2canvas 生成图片字体丢失
// 核心兼容代码
// 处理html2canvas字体偏移
const style = document.createElement("style")
document.head.appendChild(style)
style.sheet?.insertRule(`
body > div:last-child img {display: inline-block}
`)
// 处理html2canvas字体偏移

// 要转换为图片的DOM
var shareContent = qrEl.value!;
var width = shareContent.offsetWidth;
var height = shareContent.offsetHeight;
var scale = 3;

const canvas = document.createElement("canvas")
// 重点,指定的canvas 一定要在绘制内容前插入到真实DOM中
document.body.appendChild(canvas)

// canvas 尺寸设置为缩放的大小
canvas.width = width * 3
canvas.height = height * 3
// canvas 尺寸设置为缩放的大小

// canvas 样式设置为实际页面预览大小
canvas.style.width = `${width}px`
canvas.style.height = `${height}px`
// canvas 样式设置为实际页面预览大小

// 展示样式 不重要
canvas.style.position = "fixed";
canvas.style.zIndex = "3000"
canvas.style.left = "50%";
canvas.style.marginLeft = "-186px";
canvas.style.top = "62px";
// 展示样式 不重要

const el = await htmlToCanvas(shareContent, {
scale: scale,
width: width,
height: height,
useCORS: true,
canvas: canvas,
x: 0,
y: 0,
scrollX: 0,
scrollY: 0,
})

// 处理html2canvas字体偏移
style.remove()
// 处理html2canvas字体偏移

el.toBlob((blob) => {
const fileName = `收款码-${props.bill?.number || "无"}-${expireTime}.png`
const file = new File([blob!], fileName, {
type: "image/png",
});
// 移除canvas dom
canvas.remove();
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// 处理 vue-plugin-hiprint 导出PDF 第三方字体丢失
// 在toPdf 方法中,html2canvas配置中,加入我们创建的canvas,并在html2canvas绘制之前,把创建的canvas插入到真实DOM中。
toPdf = function ( t, e, options ) {
var i = this;
var dtd = $.Deferred();
var isDownload = true;
if ( this.printPanels.length ) {
const canvas = document.createElement( 'canvas' )
var scale = 2
var r = o.a.mm.toPt( this.printPanels[0].width ),
a = o.a.mm.toPt( this.printPanels[0].height );
var w = o.a.pt.toPx( r );
canvas.width = w * scale
canvas.style.width = `${w}px`
document.body.appendChild( canvas )
var p = $.extend( {
scale: scale,
width: o.a.pt.toPx( r ),
x: 0,
y: 0,
useCORS: !0,
canvas: canvas,
}, options || {} ),
s = new jsPDF( {
orientation: 1 == this.getOrient( 0 ) ? "portrait" : "landscape",
unit: "pt",
format: this.printPanels[0].paperType ? this.printPanels[0].paperType.toLocaleLowerCase() : [r, a]
} ),
l = this.getHtml( t, options );
// 移除节点
if ( options && undefined != options.isDownload ) {
isDownload = options.isDownload
}
this.createTempContainer();
var u = this.getTempContainer();
this.svg2canvas( l ), u.html( l[0] );
canvas.height = l[0].offsetHeight * scale
canvas.style.height = `${l[0].offsetHeight}px`
var d = u.find( ".hiprint-printPanel .hiprint-printPaper" ).length;
$( l ).css( "position:fixed" ), html2canvas( l[0], p ).then( function ( t ) {
var n = t.getContext( "2d" );
n.mozImageSmoothingEnabled = !1, n.webkitImageSmoothingEnabled = !1, n.msImageSmoothingEnabled = !1, n.imageSmoothingEnabled = !1;
canvas.remove();

for ( var o = t.toDataURL( "image/jpeg" ), p = 0; p < d; p++ ) {
s.addImage( o, "JPEG", 0, 0 - p * a, r, d * a ), p < d - 1 && s.addPage();
}
if ( isDownload ) {
i.removeTempContainer(), e.indexOf( ".pdf" ) > -1 ? s.save( e ) : s.save( e + ".pdf" );
} else {
i.removeTempContainer();
let type = options.type || 'blob';
var pdfFile = s.output( type );
dtd.resolve( pdfFile );
}
} );
}
return dtd.promise();
}
Read More

2025-02-18
html2canvas生成图片文案偏移

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 核心兼容代码
const style = document.createElement("style")
document.head.appendChild(style)
style.sheet?.insertRule("body > div:last-child img {display: inline-block}")
// 核心兼容代码

var shareContent = qrEl.value!;
var width = shareContent.offsetWidth;
var height = shareContent.offsetHeight;
var canvas = document.createElement("canvas");
var scale = 1;

canvas.width = width * scale;
canvas.height = height * scale;
canvas.getContext("2d")!.scale(scale, scale);

const res = await htmlToCanvas(shareContent, {
scale: scale,
canvas: canvas,
logging: true,
width: width,
height: height,
useCORS: true,
scrollX: 0,
scrollY: 0
})
style.remove() // 删除动态添加的style

res.toBlob((blob) => {
const url = URL.createObjectURL(blob!)
window.open(url)
})
Read More

2024-11-19
pnpm patch修改第三方包

  1. 第一步 生成需要修改的包的路径和版本号
1
2
3
4
5
6
7
8
9
10
# 生成包的一个修改路路径 (包名称@版本号)
pnpm patch <package-name><package-version>
# 会得到一个生成的patch 路径
# Patch: You can now edit the package at:

# /Users/zhangyu/work/ttzz/ttzzerp-app/node_modules/.pnpm_patches/pdfh5@1.4.9

# To commit your changes, run:

# pnpm patch-commit '/Users/zhangyu/work/ttzz/ttzzerp-app/node_modules/.pnpm_patches/pdfh5@1.4.9'
  1. 修改生成包的内容

    1
    2
    # file-path /Users/zhangyu/work/ttzz/ttzzerp-app/node_modules/.pnpm_patches/pdfh5@1.4.9
    code <file-path>
  2. 重新patch-commit 修改的包

1
2
# 生成patch目录,保存修改的diff信息 (file-path: /Users/zhangyu/work/ttzz/ttzzerp-app/node_modules/.pnpm_patches/pdfh5@1.4.9)
pnpm patch-commit <file-path>
  1. 重新启动项目
    1
    # 启动项目
Read More