效果
主程序
<el-container ref="PdfPage">
<el-button type="primary" data-html2canvas-ignore='true' @click="printPage">打印el-button>
<el-main>
<el-row ref="Content" :gutter="20">
......
el-row>
el-main>
el-container>
<script>
import html2canvas from 'html2canvas';
import JsPDF from 'jspdf';
export default {
name: "Home",
methods: {
printPage() {
const elRef = this.$refs['PdfPage'].$el;
const contentRef = this.$refs['Content'].$el;
const options = {
windowHeight: contentRef.clientHeight + 160,
}
html2canvas(elRef, options)
.then(canvas => {
const [w, h] = [595.28, 841.89];
const [cw, ch] = [canvas.width, canvas.height];
const PDF = new JsPDF('p', 'pt', 'a4');
const pageData = canvas.toDataURL('image/jpeg', 1.0);
PDF.addImage(pageData, 'JPEG', 0, (h - ch / (cw / w)) / 2, w, ch / (cw / w));
PDF.save('00.pdf');
})
},
},
}
script>
源码
<template>
<el-container class="Home">
<el-aside width="240px">
<el-menu default-active="1-4-1" background-color="transparent">
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location">i>
<span>导航一span>
template>
<el-menu-item-group>
<template slot="title">分组一template>
<el-menu-item index="1-1">选项1el-menu-item>
<el-menu-item index="1-2">选项2el-menu-item>
el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3el-menu-item>
el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4template>
<el-menu-item index="1-4-1">选项1el-menu-item>
el-submenu>
el-submenu>
<el-menu-item index="2">
<i class="el-icon-menu">i>
<span slot="title">导航二span>
el-menu-item>
<el-menu-item index="3">
<i class="el-icon-document">i>
<span slot="title">导航三span>
el-menu-item>
<el-menu-item index="4">
<i class="el-icon-setting">i>
<span slot="title">导航四span>
el-menu-item>
el-menu>
el-aside>
<el-container ref="PdfPage">
<el-header>
<el-row type="flex" align="middle">
<el-col :span="20">
<el-page-header content="详情页面" />
el-col>
<el-col :span="4" align="right">
<el-button type="primary" data-html2canvas-ignore='true' @click="printPage">打印el-button>
el-col>
el-row>
el-header>
<el-main>
<el-row ref="Content" :gutter="20">
<el-col :span="12">
<v-chart class="chart" :option="option1" autoresize />
el-col>
<el-col :span="12">
<v-chart class="chart" :option="option2" autoresize />
el-col>
<el-col :span="24">
<v-chart class="chart" :option="option3" autoresize />
el-col>
el-row>
el-main>
<el-footer>Hello Lee!!!el-footer>
el-container>
el-container>
template>
<script>
import { use } from "echarts/core";
import { CanvasRenderer } from "echarts/renderers";
import { PieChart, LineChart, BarChart } from "echarts/charts";
import {
TitleComponent,
TooltipComponent,
LegendComponent,
ToolboxComponent,
GridComponent,
} from "echarts/components";
import VChart, { THEME_KEY } from "vue-echarts";
import html2canvas from 'html2canvas';
import JsPDF from 'jspdf';
export default {
name: "Home",
components: {
VChart
},
provide: {
[THEME_KEY]: "default"
},
data() {
use([
CanvasRenderer,
LineChart,
PieChart,
BarChart,
TitleComponent,
TooltipComponent,
LegendComponent,
ToolboxComponent,
GridComponent,
]);
return {
option1: {
title: {
text: "Traffic Sources",
left: "center"
},
tooltip: {
trigger: "item",
formatter: "{a}
{b} : {c} ({d}%)"
},
legend: {
orient: "vertical",
left: "left",
data: [
"Direct",
"Email",
"Ad Networks",
"Video Ads",
"Search Engines"
]
},
series: [
{
name: "Traffic Sources",
type: "pie",
radius: "55%",
center: ["50%", "60%"],
data: [
{ value: 335, name: "Direct" },
{ value: 310, name: "Email" },
{ value: 234, name: "Ad Networks" },
{ value: 135, name: "Video Ads" },
{ value: 1548, name: "Search Engines" }
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: "rgba(0, 0, 0, 0.5)"
}
}
}
]
},
option2: {
color: ['#80FFA5', '#00DDFF', '#37A2FF', '#FF0087', '#FFBF00'],
title: {
text: 'Gradient Stacked Area Chart'
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
},
legend: {
bottom: '0',
data: ['Line 1', 'Line 2', 'Line 3', 'Line 4', 'Line 5']
},
toolbox: {
feature: {
saveAsImage: {}
}
},
grid: {
left: '3%',
right: '4%',
bottom: '5%',
containLabel: true
},
xAxis: [
{
type: 'category',
boundaryGap: false,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
}
],
yAxis: [
{
type: 'value'
}
],
series: [
{
name: 'Line 1',
type: 'line',
stack: 'Total',
smooth: true,
lineStyle: {
width: 0
},
showSymbol: false,
areaStyle: {
opacity: 0.8,
},
emphasis: {
focus: 'series'
},
data: [140, 232, 101, 264, 90, 340, 250]
},
{
name: 'Line 2',
type: 'line',
stack: 'Total',
smooth: true,
lineStyle: {
width: 0
},
showSymbol: false,
areaStyle: {
opacity: 0.8,
},
emphasis: {
focus: 'series'
},
data: [120, 282, 111, 234, 220, 340, 310]
},
{
name: 'Line 3',
type: 'line',
stack: 'Total',
smooth: true,
lineStyle: {
width: 0
},
showSymbol: false,
areaStyle: {
opacity: 0.8,
},
emphasis: {
focus: 'series'
},
data: [320, 132, 201, 334, 190, 130, 220]
},
{
name: 'Line 4',
type: 'line',
stack: 'Total',
smooth: true,
lineStyle: {
width: 0
},
showSymbol: false,
areaStyle: {
opacity: 0.8,
},
emphasis: {
focus: 'series'
},
data: [220, 402, 231, 134, 190, 230, 120]
},
{
name: 'Line 5',
type: 'line',
stack: 'Total',
smooth: true,
lineStyle: {
width: 0
},
showSymbol: false,
label: {
show: true,
position: 'top'
},
areaStyle: {
opacity: 0.8,
},
emphasis: {
focus: 'series'
},
data: [220, 302, 181, 234, 210, 290, 150]
}
]
},
option3: (function () {
const builderJson = {
all: 10887,
charts: {
map: 3237,
lines: 2164,
bar: 7561,
line: 7778,
pie: 7355,
scatter: 2405,
candlestick: 1842,
radar: 2090,
heatmap: 1762,
treemap: 1593,
graph: 2060,
boxplot: 1537,
parallel: 1908,
gauge: 2107,
funnel: 1692,
sankey: 1568
},
components: {
geo: 2788,
title: 9575,
legend: 9400,
tooltip: 9466,
grid: 9266,
markPoint: 3419,
markLine: 2984,
timeline: 2739,
dataZoom: 2744,
visualMap: 2466,
toolbox: 3034,
polar: 1945
},
ie: 9743
};
const downloadJson = {
'echarts.min.js': 17365,
'echarts.simple.min.js': 4079,
'echarts.common.min.js': 6929,
'echarts.js': 14890
};
const themeJson = {
'dark.js': 1594,
'infographic.js': 925,
'shine.js': 1608,
'roma.js': 721,
'macarons.js': 2179,
'vintage.js': 1982
};
const waterMarkText = 'ECHARTS';
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = canvas.height = 100;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.globalAlpha = 0.08;
ctx.font = '20px Microsoft Yahei';
ctx.translate(50, 50);
ctx.rotate(-Math.PI / 4);
ctx.fillText(waterMarkText, 0, 0);
let option = {
backgroundColor: {
type: 'pattern',
image: canvas,
repeat: 'repeat'
},
tooltip: {},
title: [
{
text: '在线构建',
subtext: '总计 ' + builderJson.all,
left: '25%',
textAlign: 'center'
},
{
text: '各版本下载',
subtext:
'总计 ' +
Object.keys(downloadJson).reduce(function (all, key) {
return all + downloadJson[key];
}, 0),
left: '75%',
textAlign: 'center'
},
{
text: '主题下载',
subtext:
'总计 ' +
Object.keys(themeJson).reduce(function (all, key) {
return all + themeJson[key];
}, 0),
left: '75%',
top: '50%',
textAlign: 'center'
}
],
grid: [
{
top: 50,
width: '50%',
bottom: '45%',
left: 10,
containLabel: true
},
{
top: '55%',
width: '50%',
bottom: 0,
left: 10,
containLabel: true
}
],
xAxis: [
{
type: 'value',
max: builderJson.all,
splitLine: {
show: false
}
},
{
type: 'value',
max: builderJson.all,
gridIndex: 1,
splitLine: {
show: false
}
}
],
yAxis: [
{
type: 'category',
data: Object.keys(builderJson.charts),
axisLabel: {
interval: 0,
rotate: 30
},
splitLine: {
show: false
}
},
{
gridIndex: 1,
type: 'category',
data: Object.keys(builderJson.components),
axisLabel: {
interval: 0,
rotate: 30
},
splitLine: {
show: false
}
}
],
series: [
{
type: 'bar',
stack: 'chart',
z: 3,
label: {
position: 'right',
show: true
},
data: Object.keys(builderJson.charts).map(function (key) {
return builderJson.charts[key];
})
},
{
type: 'bar',
stack: 'chart',
silent: true,
itemStyle: {
color: '#eee'
},
data: Object.keys(builderJson.charts).map(function (key) {
return builderJson.all - builderJson.charts[key];
})
},
{
type: 'bar',
stack: 'component',
xAxisIndex: 1,
yAxisIndex: 1,
z: 3,
label: {
position: 'right',
show: true
},
data: Object.keys(builderJson.components).map(function (key) {
return builderJson.components[key];
})
},
{
type: 'bar',
stack: 'component',
silent: true,
xAxisIndex: 1,
yAxisIndex: 1,
itemStyle: {
color: '#eee'
},
data: Object.keys(builderJson.components).map(function (key) {
return builderJson.all - builderJson.components[key];
})
},
{
type: 'pie',
radius: [0, '30%'],
center: ['75%', '25%'],
data: Object.keys(downloadJson).map(function (key) {
return {
name: key.replace('.js', ''),
value: downloadJson[key]
};
})
},
{
type: 'pie',
radius: [0, '30%'],
center: ['75%', '75%'],
data: Object.keys(themeJson).map(function (key) {
return {
name: key.replace('.js', ''),
value: themeJson[key]
};
})
}
]
};
return option;
})(),
}
},
methods: {
printPage() {
const elRef = this.$refs['PdfPage'].$el;
const contentRef = this.$refs['Content'].$el;
const options = {
windowHeight: contentRef.clientHeight + 160,
}
html2canvas(elRef, options)
.then(canvas => {
const [w, h] = [595.28, 841.89];
const [cw, ch] = [canvas.width, canvas.height];
const PDF = new JsPDF('p', 'pt', 'a4');
const pageData = canvas.toDataURL('image/jpeg', 1.0);
PDF.addImage(pageData, 'JPEG', 0, (h - ch / (cw / w)) / 2, w, ch / (cw / w));
PDF.save('00.pdf');
})
},
},
}
script>
<style lang="less" scoped>
.Home {
position: relative;
width: 100%;
height: 100%;
.el-header {
background-color: #B3C0D1;
.el-row {
height: 100%;
}
}
.el-footer {
background-color: #B3C0D1;
line-height: 60px;
}
.el-aside {
background-color: #D3DCE6;
}
.el-main {
background-color: #E9EEF3;
}
.chart {
height: 500px;
}
}
style>