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

效果

Vue(十七):利用 html2canvas、JsPDF 依赖实现打印功能_第1张图片

主程序


<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">选项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 = { // 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>

你可能感兴趣的:(Vue,vue.js,echarts,javascript,jspdf,html2canvas)