JSPDF支持中文(思源黑体)采坑之旅,JSPDF中文字体乱码解决方案
我拍个砖,通常标称自己文章完美解决何种问题的,往往就是解决不了任何问题!
众所周知,JSPDF是一个开源的,易用的,但是对中文支持非常差的PDF库。
下面,我教大家,如何在pdf中使用思源黑体。思源黑体是开源字体。思源黑体具有很广泛使用性,实用性,也是规避字体版权风险的重要选择!请严格按照我说的做!
1、准备思源黑体的ttf文件,不要用otf文件,如下
https://github.com/be5invis/source-han-sans-ttf/releases
.
我们挑其中的SourceHanSans-Bold.ttf和SourceHanSans-Normal.ttf来使用,代表一粗一细。
2、把下载的字体命名统统改为小写,如下

为什么改为小写,见 issues2465 ,命名为大写的统统失效~

在这个网站进行转换https://rawgit.com/MrRio/jsPDF/master/fontconverter/fontconverter.html
注意,这个网站就算挂了,我们也可以在jspdf的源码里找到转换器 https://github.com/MrRio/jsPDF/blob/master/fontconverter/fontconverter.html
3、于是,我们得到这2个文件

PS:字体是bold字体,网站的fontStyle你就选bold,normal也是这样!
用记事本(win)打开这2个文件,不要用编辑器,会异常卡,除非你内存高,mac爱什么打开什么打开,双击选中那串长的,ctrl+c。

你的项目新建font.js,内容如下
export function addfont(pdf) {
var font = 'AADSSDDT12......' // ←就是很长那串
pdf.addFileToVFS('bolds', font)
return true;
}
使用方法:(我的项目是ant-design pro 4.0)
import { addfont } from '@/font/font'
//前面只是添加了字体,还要注册字体,addfont第3个参数一定是normal,即使你add的字体是bold的,也要设置为normal
addfont(doc)
doc.addFont('bolds', 'b', 'normal') //使用字体时,使用这句即可
doc.setFont('b');
坑:
1、autoTable需要使用默认字体,是一种叫做NotoSansCJKtc-Regular.ttf的字体,否则乱码,或者你改源码,使之兼容
doc.addFont('NotoSansCJKtc-Regular.ttf', 'NotoSansCJKtc', 'normal');
doc.setFont('NotoSansCJKtc');
2、因为字体文件太大,导致JS运行时内存溢出 JavaScript heap out of memory
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory

资料:https://stackoverflow.com/questions/38558989/node-js-heap-out-of-memory
解决办法:https://lwjandmy.github.io/myblog/articles/+.+category+.+%E7%BC%96%E7%A8%8BJavaScript+.+title+.+node%20%E5%87%BA%E7%8E%B0heap%20out%20of%20memory%E9%97%AE%E9%A2%98+.+createtime+.+20181228%E4%B8%80190612+.+lastmodifiedtime+.+20181228%E4%B8%80190612+.+.html

由于我用了umi,因此改umi.cmd,如下
@IF EXIST "%~dp0\node.exe" (
"%~dp0\node.exe" "%~dp0\..\umi\bin\umi.js" %*
) ELSE (
@SETLOCAL
@SET PATHEXT=%PATHEXT:;.JS;=;%
node --max-old-space-size=4096 "%~dp0\..\umi\bin\umi.js" %*
)
若你是用webpack,改webpack.cmd
3、最后不得不说句,我把字体放在前端项目,是因为我的项目要打包为electron的,若你的项目是发布到线上,最好做cdn或者考虑使用默认一种字体~!
由于字体文件实在太大,执行打包时必定触发V8的内存限制,我使用umi打包时,8G内存直接爆了,--max-old-space-size=7000也不起作用,换成mac的16G内存一样爆了,问题在哪?思维错了!我们不能苛求webpack/umi能够具有打包系统级文件的能力:如大型音视频,字体包,压缩文件,msi等,此时只有使用系统的文件管理能力来加持,因此,ele的原生能力就要发挥作用。
用到线程通信和node的文件读取能力即可
https://electronjs.org/docs/api/ipc-main
// 在主进程中.
const { ipcMain } = require('electron')
ipcMain.on('asynchronous-message', (event, arg) => {
console.log(arg) // prints "ping"
event.reply('asynchronous-reply', 'pong')
}) ipcMain.on('synchronous-message', (event, arg) => {
console.log(arg) // prints "ping"
event.returnValue = 'pong'
})
//在渲染器进程 (网页) 中。
const { ipcRenderer } = require('electron')
console.log(ipcRenderer.sendSync('synchronous-message', 'ping')) // prints "pong" ipcRenderer.on('asynchronous-reply', (event, arg) => {
console.log(arg) // prints "pong"
})
ipcRenderer.send('asynchronous-message', 'ping')
所谓渲染器进程就是你的前端项目,下面说一下的处理方式
1 准备字体文件

2.由于不是项目主要部分,而是支持性部分,因此我就用了一个回调地狱 /滑稽
var fs = require("fs");
ipcMain.on('asynchronous-message', (event, arg) => {
console.log('main', arg) // 请求的消息
// 使用通信方式输送字体给前端
let filePath = path.join(__dirname, ".", "font/font.js");
let filePath2 = path.join(__dirname, ".", "font/font2.js");
let filePath3 = path.join(__dirname, ".", "font/font3.js");
console.log(filePath, "filePath")
fs.readFile(filePath, { encoding: "utf-8" }, function (err, fr) {
//readFile回调函数
// if (err) {
// console.log(err);
// }
fs.readFile(filePath2, { encoding: "utf-8" }, function (err, fr2) {
//readFile回调函数
fs.readFile(filePath3, { encoding: "utf-8" }, function (err, fr3) {
//readFile回调函数
event.reply('asynchronous-reply', {
addFont: fr,
addFont2: fr2,
addFont3: fr3,
})
})
})
})
})
前端调用
const { ipcRenderer } = require('electron')
ipcRenderer.send('asynchronous-message', 'ping')
ipcRenderer.on('asynchronous-reply', (event, arg) => {
// console.log('web', arg) // prints "pong"
const {
addFont,
addFont2,
addFont3
} = arg
this.setState({
addFont,
addFont2,
addFont3
})
})
使用字体
doc.addFileToVFS('bolds', this.state.addFont)
doc.addFileToVFS('normals', this.state.addFont2)
doc.addFont('bolds', 'b', 'normal')
doc.addFont('normals', 'n', 'normal')
...
doc.setFont('n');
...
doc.setFont('b');
JSPDF支持中文(思源黑体)采坑之旅,JSPDF中文字体乱码解决方案的更多相关文章
- css中文字体乱码解决方案
css中文字体乱码解决方案:把css编码和html页面编码统一起来.如果html页面是utf-8.css.js也统一成utf-8编码.还有一个避免中文乱码的办法就是把中文字体写成英文来表示 css中文 ...
- VUE 采坑之旅-- Mint-ui 按需引入报出Module build failed: Error: Couldn't find preset "es2015" relative to directory "C:\\phpStudy\\PHPTutorial\\WWW\\text\\vuep\\vue-demo"
首先按照mint-ui的文档中按需引入的要求,先执行 npm install babel-plugin-component -D 然后,将.babelrc文件替换了,但是后来我又将其改了(采坑过程我也 ...
- 从APP跳转到微信指定联系人聊天页面功能的实现与采坑之旅
起因: 最近做的APP中有一个新功能:已知用户微信号,可点击直接跳转到当前用户微信聊天窗口页面. 当时第一想法是使用无障碍来做,并且觉得应该不难,只是逻辑有点复杂.没想到最终踩了好多坑,特地把踩过的坑 ...
- CentOS7.6系统安装详解(含真机装系统的采坑之旅)!
刚开始学习linux操作系统是总是很茫然,无所适从,以下是自己总结的工作经验,仅供参考! 一.准备资源 安装前需要准备的资源有linux系统centos7.6发行版系统镜像,vmware workst ...
- angular5采坑之旅
开始尝试angular5,在此记录下踩过的坑以备查询 1.按照element-angular的文档引入后报错 is not part of the compilation output.解决方法--在 ...
- vue的采坑之旅--vue-cli脚手架loader重复--Invalid CSS after "...load the styles": expected 1 selector or at-rule
在使用scss是可能会添加loader,例如 { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'], } 然而当使 ...
- mac 如何卸载node和npm采坑之旅
因为本地npm一直报错,所以决定直接卸载node和npm,重新装.第一次卸载,具体咱也不会呀!能咋整呢,百度呗 茫茫百度中各种找呀,找到一个转载最多的方法 sudo npm uninstall npm ...
- weex打包android apk采坑之旅(windows)
1. npm install weex-toolkit -g 后weex命令不起作用 ,解决办法把weex.cmd所在的目录添加到环境变量PATH 2.weex命令每次报找不到文件'C:\Progra ...
- stm32填坑之旅 - stm32f103c8t6点亮板载贴片蓝色LED
转载请注明:https://www.cnblogs.com/rockyf/p/11691622.html 开篇 开篇一定要精彩,不然路人不理睬!下述是笔者作为arm小白的填坑之旅 没错,这个之前一直从 ...
随机推荐
- 剑指offer:对称的二叉树
题目描述: 请实现一个函数,用来判断一颗二叉树是不是对称的.注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的. 思路分析: 二叉树的镜像就是左右相反,对称二叉树即镜像相等.利用一个递归函数 ...
- Qt 绘制图表 - Qt Charts版
一.前言 自从 Qt 发布以来,给广大跨平台界面研发人员带来了无数的福利.但是Qt自己却一直没有提供自带的图表库,这就使得 QWT.QCustomPlot 等第三方图表库有了巨大的生存空间,为了降低开 ...
- mybatis + mysql 批量插入、删除、更新
mybatis + mysql 批量插入.删除.更新 Student 表结构 批量插入 public int insertBatchStudent(List<Student> studen ...
- freemarker中8个常用的指令
这里列举出Freemarker模板文件中8个常用的指令. 1. assign assign指令用于创建或替换一个顶层变量,assign指令的用法有多种,包括创建或替换一个顶层变量,创建或替换多个变量等 ...
- flutter-初识(基础语法)
前言:笔者学过 java,刚刚接触 flutter,记录下基本的一些语法. 一.认识Flutter Flutter 是 google 推出的,使用的 Dart 语言,它可以跨平台实现 Android ...
- SSM基本配置详解
需要查看SSM基本依赖和完整配置文件的到:SSM基本配置及依赖 示例项目:SSMDemo 1 Spring IOC容器配置 1.1 applicationContext.xml 1.1.1 配置数据源 ...
- JVM 的垃圾回收器详解
Parallel Scavenge(Paraller):Parallel Scavenge和ParNew关注的点不一样:ParNew关注的是尽可能缩短暂停的时间,Parallel Scavenge关注 ...
- 『Pushbox 点双联通分量』
Pushbox Description 周婧涵和她的小伙伴们发明了一个新游戏.游戏名字很准确,但不是特别有 创意.她们称之为"推动箱子在谷仓周围找到正确的位置,不要移动干草"游戏 ...
- Mysql系列(十一)—— 性能分析其他常用监控
show status show status可以查询显示出当前mysql server的状态信息.该语句不需要任何权限. 对于show status可以时用like子句,模糊检索需要的状态信息.如: ...
- JavaScript变量与数据类型
变量 javascript的变量很松散,每个变量初始仅仅用于保存一个占位符而已.定义变量的操作符是 var, var 后面跟着一个标识符--当作变量的名字. 比如: var myname;//定义了一 ...