您可以使用与amcharts相同的pdfmake库,但需要按照上面的答案所述使用gulp生成字体。由于存在承诺问题,因此我替换了语法以进行快速解决,因此您必须转到位于项目根目录的node_modules中的pdfmake文件夹,并在其中运行npm install,之后您需要在示例目录下创建fonts文件夹-> examples/fonts并将您的ttf字体复制到那里,然后运行gulp文件,它将为您提供vfs_fonts.js文件。
您需要编辑此文件并更改
this.pdfMake = this.pdfMake || {}; pdfMake.vfs = {}
为
export const pdfMake={ vfs : { }}; 如此屏幕截图所示:
并适当结束键,如下所示:
而不是这个};
之后,您可以在此处检查我使用Montserrat字体制作的完整工作代码,该代码是通过使用下面的Amchart自定义内容演示而制作的:
import { Component, NgZone } from "@angular/core";
import * as am4core from "@amcharts/amcharts4/core";
import * as am4charts from "@amcharts/amcharts4/charts";
import am4themes_animated from "@amcharts/amcharts4/themes/animated";
import am4themes_dataviz from "@amcharts/amcharts4/themes/dataviz";
import * as pdfFontsVfs from "../../node_modules/pdfmake/build/vfs_fonts";
am4core.useTheme(am4themes_animated);
am4core.useTheme(am4themes_animated);
am4core.useTheme(am4themes_dataviz);
@Component({
selector: "app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
private chart: am4charts.XYChart;
private chart2: am4charts.XYChart;
private chart3: am4charts.XYChart;
private chart4: am4charts.PieChart;
constructor(private zone: NgZone) {}
ngAfterViewInit() {
this.zone.runOutsideAngular(() => {
var chart = am4core.create("chartdiv", am4charts.XYChart);
chart.data = [{
"date": new Date(2018, 0, 1),
"value": 450,
"value2": 362,
"value3": 699
}, {
"date": new Date(2018, 0, 2),
"value": 269,
"value2": 450,
"value3": 841
}, {
"date": new Date(2018, 0, 3),
"value": 700,
"value2": 358,
"value3": 699
}, {
"date": new Date(2018, 0, 4),
"value": 490,
"value2": 367,
"value3": 500
}, {
"date": new Date(2018, 0, 5),
"value": 500,
"value2": 485,
"value3": 369
}, {
"date": new Date(2018, 0, 6),
"value": 550,
"value2": 354,
"value3": 250
}, {
"date": new Date(2018, 0, 7),
"value": 420,
"value2": 350,
"value3": 600
}];
var categoryAxis = chart.xAxes.push(new am4charts.DateAxis());
categoryAxis.renderer.grid.template.location = 0;
categoryAxis.renderer.labels.template.disabled = true;
categoryAxis.renderer.minGridDistance = 30;
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.renderer.labels.template.disabled = true;
this.createSeries("value", "Series #1",chart);
this.createSeries("value2", "Series #2",chart);
this.createSeries("value3", "Series #3",chart);
this.chart = chart;
var chart2 = am4core.create("chartdiv2", am4charts.XYChart);
chart2.paddingBottom = 25;
chart2.data = [{
"country": "USA",
"visits": 3025
}, {
"country": "China",
"visits": 1882
}, {
"country": "Japan",
"visits": 1809
}, {
"country": "Germany",
"visits": 1322
}, {
"country": "UK",
"visits": 1122
}, {
"country": "France",
"visits": 1114
}, {
"country": "India",
"visits": 984
}];
var categoryAxis2 = chart2.xAxes.push(new am4charts.CategoryAxis());
categoryAxis2.dataFields.category = "country";
categoryAxis2.renderer.grid.template.location = 0;
categoryAxis2.renderer.minGridDistance = 30;
categoryAxis2.renderer.labels.template.disabled = true;
var valueAxis = chart2.yAxes.push(new am4charts.ValueAxis());
valueAxis.renderer.labels.template.disabled = true;
var series = chart2.series.push(new am4charts.ColumnSeries());
series.sequencedInterpolation = true;
series.dataFields.valueY = "visits";
series.dataFields.categoryX = "country";
series.columns.template.strokeWidth = 0;
series.columns.template.column.cornerRadiusTopLeft = 10;
series.columns.template.column.cornerRadiusTopRight = 10;
var hoverState = series.columns.template.column.states.create("hover");
hoverState.properties.cornerRadiusTopLeft = 0;
hoverState.properties.cornerRadiusTopRight = 0;
hoverState.properties.fillOpacity = 1;
series.columns.template.adapter.add("fill", (fill, target)=>{
return chart.colors.getIndex(target.dataItem.index);
});
this.chart2 = chart2;
var chart3 = am4core.create("chartdiv3", am4charts.XYChart);
chart3.paddingBottom = 25;
chart3.numberFormatter.numberFormat = "#.3'%'";
chart3.data = [{
"country": "USA",
"year2004": 3.5,
"year2005": 4.2
}, {
"country": "UK",
"year2004": 1.7,
"year2005": 3.1
}, {
"country": "Canada",
"year2004": 2.8,
"year2005": 2.9
}, {
"country": "Japan",
"year2004": 2.6,
"year2005": 2.3
}, {
"country": "France",
"year2004": 1.4,
"year2005": 2.1
}, {
"country": "Brazil",
"year2004": 2.6,
"year2005": 4.9
}];
var categoryAxis3 = chart3.xAxes.push(new am4charts.CategoryAxis());
categoryAxis3.dataFields.category = "country";
categoryAxis3.renderer.grid.template.location = 0;
categoryAxis3.renderer.minGridDistance = 30;
categoryAxis3.renderer.labels.template.disabled = true;
var valueAxis3 = chart3.yAxes.push(new am4charts.ValueAxis());
valueAxis3.renderer.labels.template.disabled = true;
var series3 = chart3.series.push(new am4charts.ColumnSeries());
series3.dataFields.valueY = "year2004";
series3.dataFields.categoryX = "country";
series3.clustered = false;
series3.columns.template.column.cornerRadiusTopLeft = 10;
series3.columns.template.column.cornerRadiusTopRight = 10;
var series2 = chart3.series.push(new am4charts.ColumnSeries());
series2.dataFields.valueY = "year2005";
series2.dataFields.categoryX = "country";
series2.clustered = false;
series2.columns.template.width = am4core.percent(50);
series2.columns.template.column.cornerRadiusTopLeft = 6;
series2.columns.template.column.cornerRadiusTopRight = 6;
this.chart3 = chart3;
var chart4 = am4core.create("chartdiv4", am4charts.PieChart);
chart4.padding(0, 0, 0, 0);
chart4.data = [
{
country: "Lithuania",
value: 260
},
{
country: "Czech Republic",
value: 230
},
{
country: "Ireland",
value: 200
},
{
country: "Germany",
value: 165
},
{
country: "Australia",
value: 139
},
{
country: "Austria",
value: 128
}
];
var series4 = chart4.series.push(new am4charts.PieSeries());
series4.dataFields.value = "value";
series4.dataFields.radiusValue = "value";
series4.dataFields.category = "country";
series4.slices.template.cornerRadius = 6;
series4.colors.step = 3;
series4.radius = am4core.percent(100);
series4.labels.template.disabled = true;
series4.ticks.template.disabled = true;
this.chart4 = chart4;
});
}
async savePDF() {
var res = [];
var fonts = {
"Montserrat": {
normal: "Montserrat-Regular.ttf",
bold: "Montserrat-Bold.ttf",
italics: "Montserrat-Italic.ttf",
bolditalics: "Montserrat-BoldItalic.ttf"
}
};
var PdfMake = await this.chart.exporting.pdfmake;
PdfMake.vfs = pdfFontsVfs.pdfMake.vfs;
PdfMake.addVirtualFileSystem = pdfFontsVfs;
PdfMake.fonts = fonts;
res[1] = await this.chart.exporting.getImage("png");
res[2] = await this.chart2.exporting.getImage("png");
res[3] = await this.chart3.exporting.getImage("png");
res[4] = await this.chart4.exporting.getImage("png");
var doc = {
pageSize: "A4",
pageOrientation: "portrait",
pageMargins: [30, 30, 30, 30],
content: [],
defaultStyle:{
font: "Montserrat"
}
};
doc.content.push({
text: "In accumsan velit in orci tempor",
fontSize: 20,
bold: true,
margin: [0, 20, 0, 15]
});
doc.content.push({
text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sem quam, sodales ac volutpat sed, vestibulum id quam. Sed quis arcu non elit fringilla mattis. Sed auctor mi sed efficitur vehicula. Sed bibendum odio urna, quis lobortis dui luctus ac. Duis eu lacus sodales arcu tincidunt ultrices viverra a risus. Vivamus justo massa, malesuada quis pellentesque ut, placerat in massa. Nunc bibendum diam justo, in consequat ipsum fringilla ac. Praesent porta nibh ac arcu viverra, at scelerisque neque venenatis. Donec aliquam lorem non ultrices ultrices. Aliquam efficitur eros quis tortor condimentum, id pellentesque metus iaculis. Aenean at consequat neque, a posuere lectus. In eu libero magna. Pellentesque molestie tellus nec nisi molestie, eu dignissim lacus tristique. Sed tellus nulla, suscipit a velit non, mattis dictum metus. Curabitur mi mi, convallis nec libero quis, venenatis vestibulum ante.",
fontSize: 15,
margin: [0, 0, 0, 15]
});
doc.content.push({
text: "Aliquam lacinia justo",
fontSize: 20,
bold: true,
margin: [0, 20, 0, 15]
});
doc.content.push({
image: res[1],
width: 530
});
doc.content.push({
text: "Phasellus suscipit in diam a interdum",
fontSize: 20,
bold: true,
margin: [0, 20, 0, 15]
});
doc.content.push({
table: {
headerRows: 1,
widths: [ "*", "*", "*", "*" ],
body: [
[
{ text: "USA", bold: true },
{ text: "Japan", bold: true },
{ text: "France", bold: true },
{ text: "Mexico", bold: true }
],
[ "2500", "2500", "2200", "1200" ],
[ "800", "1200", "990", "708" ],
[ "2100", "2150", "900", "1260" ],
]
}
});
doc.content.push({
text: "Duis sed efficitur mauris",
fontSize: 20,
bold: true,
margin: [0, 20, 0, 15]
});
doc.content.push({
columns: [{
image: res[2],
width: 250
}, {
image: res[3],
width: 250
}],
columnGap: 30
});
doc.content.push({
text: "Aliquam semper lacinia",
fontSize: 20,
bold: true,
margin: [0, 20, 0, 15]
});
doc.content.push({
columns: [{
image: res[4],
width: 150
}, {
stack: [{
text: "Maecenas congue leo vel tortor faucibus, non semper odio viverra. In ac libero rutrum libero elementum blandit vel in orci. Donec sit amet nisl ac eros mollis molestie. Curabitur ut urna vitae turpis bibendum malesuada sit amet imperdiet orci. Etiam pulvinar quam at lorem pellentesque congue. Integer sed odio enim. Maecenas eu nulla justo. Sed quis enim in est sodales facilisis non sed erat. Aenean vel ornare urna. Praesent viverra volutpat ex a aliquet.",
fontSize: 15,
margin: [0, 0, 0, 15]
}, {
text: "Fusce sed quam pharetra, ornare ligula id, maximus risus. Integer dignissim risus in placerat mattis. Fusce malesuada dui ut lectus ultricies, et sollicitudin nisl placerat. In dignissim elit in pretium lobortis. Fusce ornare enim at metus laoreet, ut convallis elit lacinia. Maecenas pharetra aliquet mi. Nulla orci nunc, egestas id nisi ut, volutpat sollicitudin mi.",
fontSize: 15,
margin: [0, 0, 0, 15]
}],
width: "*"
}],
columnGap: 30
});
await PdfMake.createPdf(doc,null, fonts,pdfFontsVfs.pdfMake.vfs).download("report.pdf");
}
createSeries(field, name, chart) {
console.log(chart);
var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.valueY = field;
series.dataFields.dateX = "date";
series.name = name;
series.tooltipText = "{dateX}: [b]{valueY}[/]";
series.strokeWidth = 3;
var bullet = series.bullets.push(new am4charts.CircleBullet());
bullet.circle.stroke = am4core.color("#fff");
bullet.circle.strokeWidth = 3;
bullet.circle.radius = 7;
}
ngOnDestroy() {
this.zone.runOutsideAngular(() => {
if (this.chart) {
this.chart.dispose();
...dispose other charts
}
});
}
}
而 webpack 配置是:
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/main.ts',
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
use: ['ts-loader', 'angular2-template-loader'],
exclude: [ /node_modules/, /pdfmake.js$/ ]
},
{
test: /\.(html|css)$/,
use: 'raw-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({ template: './src/index.html' })
],
}
而 HTML 是:
<div class="main">
<input type="button" value="Save as PDF" (click)="savePDF()" />
<h1>In accumsan velit in orci tempor</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sem quam, sodales ac volutpat sed, vestibulum id quam. Sed quis arcu non elit fringilla mattis. Sed auctor mi sed efficitur vehicula. Sed bibendum odio urna, quis lobortis dui luctus ac. Duis eu lacus sodales arcu tincidunt ultrices viverra a risus. Vivamus justo massa, malesuada quis pellentesque ut, placerat in massa. Nunc bibendum diam justo, in consequat ipsum fringilla ac. Praesent porta nibh ac arcu viverra, at scelerisque neque venenatis. Donec aliquam lorem non ultrices ultrices. Aliquam efficitur eros quis tortor condimentum, id pellentesque metus iaculis. Aenean at consequat neque, a posuere lectus. In eu libero magna. Pellentesque molestie tellus nec nisi molestie, eu dignissim lacus tristique. Sed tellus nulla, suscipit a velit non, mattis dictum metus. Curabitur mi mi, convallis nec libero quis, venenatis vestibulum ante.</p>
<h2>Aliquam lacinia justo</h2>
<div id="chartdiv" class="chart"></div>
<h2>Phasellus suscipit in diam a interdum</h2>
<table>
<tr>
<th>USA</th>
<th>Japan</th>
<th>France</th>
<th>Mexico</th>
</tr>
<tr>
<td>2500</td>
<td>1900</td>
<td>2200</td>
<td>1200</td>
</tr>
<tr>
<td>800</td>
<td>1200</td>
<td>990</td>
<td>708</td>
</tr>
<tr>
<td>2100</td>
<td>2150</td>
<td>900</td>
<td>1260</td>
</tr>
</table>
<h2>Duis sed efficitur mauris</h2>
<div>
<div class="col">
<div id="chartdiv2" class="chart"></div>
</div>
<div class="col">
<div id="chartdiv3" class="chart"></div>
</div>
</div>
<br>
<h2>Aliquam semper lacinia</h2>
<div id="chartdiv4" class="chart"></div>
<p>Maecenas congue leo vel tortor faucibus, non semper odio viverra. In ac libero rutrum libero elementum blandit vel in orci. Donec sit amet nisl ac eros mollis molestie. Curabitur ut urna vitae turpis bibendum malesuada sit amet imperdiet orci. Etiam pulvinar quam at lorem pellentesque congue. Integer sed odio enim. Maecenas eu nulla justo. Sed quis enim in est sodales facilisis non sed erat. Aenean vel ornare urna. Praesent viverra volutpat ex a aliquet.</p>
<p>Fusce sed quam pharetra, ornare ligula id, maximus risus. Integer dignissim risus in placerat mattis. Fusce malesuada dui ut lectus ultricies, et sollicitudin nisl placerat. In dignissim elit in pretium lobortis. Fusce ornare enim at metus laoreet, ut convallis elit lacinia. Maecenas pharetra aliquet mi. Nulla orci nunc, egestas id nisi ut, volutpat sollicitudin mi.</p>
</div>
而 package.json 是:
{
"name": "angular-7-tutorial",
"version": "1.0.0",
"scripts": {
"start": "webpack-dev-server --mode development --open"
},
"dependencies": {
"@amcharts/amcharts4": "^4.9.1",
"@angular/common": "^7.2.13",
"@angular/compiler": "^7.2.13",
"@angular/core": "^7.2.13",
"@angular/forms": "^7.2.13",
"@angular/platform-browser": "^7.2.13",
"@angular/platform-browser-dynamic": "^7.2.13",
"@angular/router": "^7.2.13",
"core-js": "^3.0.1",
"rxjs": "^6.4.0",
"zone.js": "^0.9.0"
},
"devDependencies": {
"@types/node": "^11.13.5",
"angular2-template-loader": "^0.6.2",
"html-webpack-plugin": "^3.2.0",
"raw-loader": "^1.0.0",
"ts-loader": "^5.3.3",
"typescript": "^3.4.4",
"webpack": "^4.30.0",
"webpack-cli": "^3.3.0",
"webpack-dev-server": "^3.3.1"
}
}
关于文件夹结构:
![在此输入图片描述](https://istack.dev59.com/MKYBl.webp)
我理解的问题是语法冲突和未解决的承诺导致图表 PDF 无法加载自定义字体。如果您查看默认的 amcharts vs_fonts 文件,您会看到导出默认语法可能会导致问题。其次,请检查您的字体文件是否损坏。
希望这能帮助到您。谢谢。