Vue(十七):利用 html2canvas、JsPDF 依赖实现打印功能

效果

在这里插入图片描述

主程序

<!-- 打印区域 -->
<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 = {
      
      
				// width: elRef.clientWidth,
				// height: contentRef.clientHeight + 160,
				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">选项1</el-menu-item>
						<el-menu-item index="1-2">选项2</el-menu-item>
					</el-menu-item-group>
					<el-menu-item-group title="分组2">
						<el-menu-item index="1-3">选项3</el-menu-item>
					</el-menu-item-group>
					<el-submenu index="1-4">
						<template slot="title">选项4</template>
						<el-menu-item index="1-4-1">选项1</el-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} <br/>{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 = {
      
      
				// width: elRef.clientWidth,
				// height: contentRef.clientHeight + 160,
				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>

猜你喜欢

转载自blog.csdn.net/weixin_43526371/article/details/130217094
今日推荐