banner

vue使用pdf-dist实现pdf预览以及水印

  • Home
  • vue-pdf-dist-watermark
Scroll down

vue使用pdf-dist实现pdf预览以及水印

一.使用pdf-dist插件将PDF文件转换为一张张canvas图片

1
npm install pdf-dist

二.页面引入插件

1
2
const pdfJS = require("pdfjs-dist");
pdfJS.GlobalWorkerOptions.workerSrc = require("pdfjs-dist/build/pdf.worker.entry");

三.渲染PDF

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// 根据页码渲染相应的PDF
renderPage(num) {
this.renderingPage = true;
this.pdfData.promise.then((pdf) => {

this.pdfPageNumber = pdf.numPages;

pdf.getPage(num).then((page) => {
// 获取DOM中为预览PDF准备好的canvasDOM对象
let canvas = this.$refs.myCanvas;
let ctx = canvas.getContext("2d");

// 获取页面比率
let ratio = this._getRatio(ctx);

// 根据页面宽度和视口宽度的比率就是内容区的放大比率
let dialogWidth = this.$refs["canvasCont"].offsetWidth;
let pageWidth = page.view[2] * ratio;
let scale = dialogWidth / pageWidth;
let viewport = page.getViewport({ scale });


// 记录内容区宽高,后期添加水印时需要
this.width = viewport.width * ratio;
this.height = viewport.height * ratio;

canvas.width = this.width;
canvas.height = this.height;

// 缩放比率
ctx.setTransform(ratio, 0, 0, ratio, 0, 0);

let renderContext = {
canvasContext: ctx,
viewport: viewport,
};
page.render(renderContext).promise.then(() => {
this.renderingPage = false;
this.pageNo = num;

// 添加水印
this._renderWatermark();
});
});
});
},
// 计算角度
_getRatio(ctx) {
let dpr = window.devicePixelRatio || 1;
let bsr =
ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio ||
1;
return dpr / bsr;
},

四.添加水印

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 生成水印图片
_initWatermark() {
let canvas = document.createElement("canvas");
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext("2d");
ctx.rotate((-18 * Math.PI) / 180);
ctx.font = "10px Vedana";
ctx.fillStyle = "rgba(0, 0, 0, 0.8)";
ctx.textAlign = "left";
ctx.textBaseline = "middle";
ctx.fillText(this.watermark, 10, 100);
return canvas;
},

五.完整代码(带翻页)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<template>
<div class="main-container">
<input type="file" ref="fielinput" @change="uploadFile" />
<div ref="canvasCont" class="canvas-container">
<canvas ref="myCanvas" class="pdf-container"></canvas>
</div>
<div class="pagination-wrapper">
<button @click="clickPre">上一页</button>
<span>第{{ pageNo }} / {{ pdfPageNumber }}页</span>
<button @click="clickNext">下一页</button>
</div>
</div>
</template>

<script>
const pdfJS = require("pdfjs-dist");

pdfJS.GlobalWorkerOptions.workerSrc = require("pdfjs-dist/build/pdf.worker.entry");
export default {
props: {
watermark: {
type: String,
default: "水印文字水印文字水印文字",
},
},
mounted() {},
data() {
return {
pageNo: null,
pdfPageNumber: null,
renderingPage: false,
pdfData: null, // PDF的base64
scale: 1, // 缩放值
width: "",
height: "",
};
},
methods: {
uploadFile() {
let inputDom = this.$refs.fielinput;
let file = inputDom.files[0];
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
let data = atob(
reader.result.substring(reader.result.indexOf(",") + 1)
);
this.loadPdfData(data);
};
},
loadPdfData(data) {
// 引入pdf.js的字体
let CMAP_URL = "https://unpkg.com/pdfjs-dist@2.0.943/cmaps/";
//读取base64的pdf流文件
this.pdfData = pdfJS.getDocument({
data: data, // PDF base64编码
cMapUrl: CMAP_URL,
cMapPacked: true,
});
this.renderPage(1);
},

// 根据页码渲染相应的PDF
renderPage(num) {
this.renderingPage = true;
this.pdfData.promise.then((pdf) => {

this.pdfPageNumber = pdf.numPages;

pdf.getPage(num).then((page) => {
// 获取DOM中为预览PDF准备好的canvasDOM对象
let canvas = this.$refs.myCanvas;
let ctx = canvas.getContext("2d");

// 获取页面比率
let ratio = this._getRatio(ctx);

// 根据页面宽度和视口宽度的比率就是内容区的放大比率
let dialogWidth = this.$refs["canvasCont"].offsetWidth;
let pageWidth = page.view[2] * ratio;
let scale = dialogWidth / pageWidth;
let viewport = page.getViewport({ scale });


// 记录内容区宽高,后期添加水印时需要
this.width = viewport.width * ratio;
this.height = viewport.height * ratio;

canvas.width = this.width;
canvas.height = this.height;

// 缩放比率
ctx.setTransform(ratio, 0, 0, ratio, 0, 0);

let renderContext = {
canvasContext: ctx,
viewport: viewport,
};
page.render(renderContext).promise.then(() => {
this.renderingPage = false;
this.pageNo = num;

// 添加水印
this._renderWatermark();
});
});
});
},
// 计算角度
_getRatio(ctx) {
let dpr = window.devicePixelRatio || 1;
let bsr =
ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio ||
1;
return dpr / bsr;
},

// 在画布上渲染水印
_renderWatermark() {
let canvas = this.$refs.myCanvas;
let ctx = canvas.getContext("2d");
// 平铺水印
let pattern = ctx.createPattern(this._initWatermark(), "repeat");
ctx.rect(0, 0, this.width, this.height);
ctx.fillStyle = pattern;
ctx.fill();
},

// 生成水印图片
_initWatermark() {
let canvas = document.createElement("canvas");
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext("2d");
ctx.rotate((-18 * Math.PI) / 180);
ctx.font = "10px Vedana";
ctx.fillStyle = "rgba(0, 0, 0, 0.8)";
ctx.textAlign = "left";
ctx.textBaseline = "middle";
ctx.fillText(this.watermark, 10, 100);
return canvas;
},

clickPre() {
if (!this.renderingPage && this.pageNo && this.pageNo > 1) {
this.renderPage(this.pageNo - 1);
}
},
clickNext() {
if (
!this.renderingPage &&
this.pdfPageNumber &&
this.pageNo &&
this.pageNo < this.pdfPageNumber
) {
this.renderPage(this.pageNo + 1);
}
},
},
};
</script>

<style scoped>
.main-container {
display: flex;
flex-direction: column;
align-items: center;
}
.canvas-container {
width: 100%;
height: 100%;
border: 1px dashed black;
position: relative;
display: flex;
justify-content: center;
}
.pdf-container {
width: 100%;
height: 100%;
}

.pagination-wrapper {
display: flex;
justify-content: center;
align-items: center;
}
</style>

六.完整代码(滑动)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
<template>
<div class="main-container">
<input type="file" ref="fielinput" @change="uploadFile" />
<div ref="canvasCont" class="canvas-container">
<canvas v-for="pageIndex in pdfPageNumber"
:ref="`myCanvas${pageIndex}`" :key="pageIndex" class="pdf-container"></canvas>
</div>
</div>
</template>

<script>
const pdfJS = require("pdfjs-dist");

pdfJS.GlobalWorkerOptions.workerSrc = require("pdfjs-dist/build/pdf.worker.entry");
export default {
props: {
watermark: {
type: String,
default: "水印文字水印文字水印文字",
},
},
mounted() {},
data() {
return {
pageNo: null,
pdfPageNumber: null,
renderingPage: false,
pdfData: null, // PDF的base64
scale: 1, // 缩放值
width: "",
height: "",
};
},
methods: {
uploadFile() {
let inputDom = this.$refs.fielinput;
let file = inputDom.files[0];
let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
let data = atob(
reader.result.substring(reader.result.indexOf(",") + 1)
);
this.loadPdfData(data);
};
},
loadPdfData(data) {
// 引入pdf.js的字体
let CMAP_URL = "https://unpkg.com/pdfjs-dist@2.0.943/cmaps/";
//读取base64的pdf流文件
this.pdfData = pdfJS.getDocument({
data: data, // PDF base64编码
cMapUrl: CMAP_URL,
cMapPacked: true,
});
this.renderPage(1);
},

// 根据页码渲染相应的PDF
renderPage(num) {
this.renderingPage = true;
this.pdfData.promise.then((pdf) => {

this.pdfPageNumber = pdf.numPages;

pdf.getPage(num).then((page) => {
// 获取DOM中为预览PDF准备好的canvasDOM对象
let canvas = this.$refs[`myCanvas${num}`][0];
let ctx = canvas.getContext("2d");

// 获取页面比率
let ratio = this._getRatio(ctx);

// 根据页面宽度和视口宽度的比率就是内容区的放大比率
let dialogWidth = this.$refs["canvasCont"].offsetWidth;
let pageWidth = page.view[2] * ratio;
let scale = dialogWidth / pageWidth;
let viewport = page.getViewport({ scale });


// 记录内容区宽高,后期添加水印时需要
this.width = viewport.width * ratio;
this.height = viewport.height * ratio;

canvas.width = this.width;
canvas.height = this.height;

// 缩放比率
ctx.setTransform(ratio, 0, 0, ratio, 0, 0);

let renderContext = {
canvasContext: ctx,
viewport: viewport,
};

page.render(renderContext).promise.then(() => {
this.renderingPage = false;
this.pageNo = num;
// 添加水印
this._renderWatermark(num);
if(num < this.pdfPageNumber){
this.renderPage(num+1)
}
});
});
});
},
// 计算角度
_getRatio(ctx) {
let dpr = window.devicePixelRatio || 1;
let bsr =
ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio ||
1;
return dpr / bsr;
},

// 在画布上渲染水印
_renderWatermark(num) {
let canvas = this.$refs[`myCanvas${num}`][0];
let ctx = canvas.getContext("2d");
// 平铺水印
let pattern = ctx.createPattern(this._initWatermark(), "repeat");
ctx.rect(0, 0, this.width, this.height);
ctx.fillStyle = pattern;
ctx.fill();
},

// 生成水印图片
_initWatermark() {
let canvas = document.createElement("canvas");
canvas.width = 200;
canvas.height = 200;
let ctx = canvas.getContext("2d");
ctx.rotate((-18 * Math.PI) / 180);
ctx.font = "10px Vedana";
ctx.fillStyle = "rgba(0, 0, 0, 0.8)";
ctx.textAlign = "left";
ctx.textBaseline = "middle";
ctx.fillText(this.watermark, 10, 100);
return canvas;
},
},
};
</script>

<style scoped>
.main-container {
display: flex;
flex-direction: column;
align-items: center;
}
.canvas-container {
width: 100%;
height: 100%;
border: 1px dashed black;
position: relative;
/* display: flex; */
/* justify-content: center; */
}
.pdf-container {
width: 100%;
height: 100%;
}
</style>

七.下载源码地址

下载地址

其他文章
请输入关键词进行搜索