vue使用pdf-dist实现pdf预览以及水印
一.使用pdf-dist插件将PDF文件转换为一张张canvas图片
npm install pdf-dist
二.页面引入插件
const pdfJS = require("pdfjs-dist");
pdfJS.GlobalWorkerOptions.workerSrc = require("pdfjs-dist/build/pdf.worker.entry");
三.渲染PDF
renderPage(num) {
this.renderingPage = true;
this.pdfData.promise.then((pdf) => {
this.pdfPageNumber = pdf.numPages;
pdf.getPage(num).then((page) => {
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
- 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
四.添加水印
_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;
},
五.完整代码(带翻页)
<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,
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) {
let CMAP_URL = "https://unpkg.com/pdfjs-dist@2.0.943/cmaps/";
this.pdfData = pdfJS.getDocument({
data: data,
cMapUrl: CMAP_URL,
cMapPacked: true,
});
this.renderPage(1);
},
renderPage(num) {
this.renderingPage = true;
this.pdfData.promise.then((pdf) => {
this.pdfPageNumber = pdf.numPages;
pdf.getPage(num).then((page) => {
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
- 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 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,
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) {
let CMAP_URL = "https://unpkg.com/pdfjs-dist@2.0.943/cmaps/";
this.pdfData = pdfJS.getDocument({
data: data,
cMapUrl: CMAP_URL,
cMapPacked: true,
});
this.renderPage(1);
},
renderPage(num) {
this.renderingPage = true;
this.pdfData.promise.then((pdf) => {
this.pdfPageNumber = pdf.numPages;
pdf.getPage(num).then((page) => {
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;
}
.pdf-container {
width: 100%;
height: 100%;
}
</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
七.下载源码地址
下载地址
八.效果展示
