<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta charset="utf-8" />
<title>PDF 预览、水印、缩放、旋转</title>
<script src="https://netnr.eu.org/pdfjs-dist@3.11.174/build/pdf.min.js"></script>
</head>
<body>
<h3 style="text-align:center">可拖拽 PDF文件打开,支持 #URL 打开链接</h3>
<div class="nr-tools">
<select class="nr-size">
<option value="0.5">0.5 倍</option>
<option value="0.75">0.75 倍</option>
<option value="1.0" selected>缩放比例</option>
<option value="1.5">1.5 倍</option>
<option value="2.0">2 倍</option>
<option value="4.0">4 倍</option>
</select>
<br/>
<select class="nr-watermark">
<option value="1">开启水印</option>
<option value="0">关闭水印</option>
</select>
<br/>
<select class="nr-spin">
<option value="0">旋转角度</option>
<option value="90">旋转 90</option>
<option value="180">旋转 180</option>
<option value="270">旋转 270</option>
</select>
</div>
<div class="nr-pdf-viewer"></div>
</body>
</html>
body {
color: deeppink;
}
.nr-tools {
position: fixed;
top: 10%;
right: 1.5%;
z-index: 1;
line-height: 2em;
}
.nr-pdf-viewer {
text-align: center;
}
.nr-pdf-viewer .nr-pdf-page {
position: relative;
display: inline-block;
}
.nr-pdf-viewer .nr-pdf-page canvas {
max-width: 100%;
margin: 10px auto;
border: 1px solid #ddd;
}
.nr-newline {
clear: both;
}
.nr-spin-90 .nr-pdf-page {
transform: rotate(90deg);
}
.nr-spin-180 .nr-pdf-page {
transform: rotate(180deg);
}
.nr-spin-270 .nr-pdf-page {
transform: rotate(270deg);
}
.wm {
position: absolute;
z-index: 1;
top: 50px;
right: 50px;
overflow: hidden;
pointer-events: none;
}
.wm2 {
opacity: 0.5;
max-width: 80%;
color: #ff0000;
font-weight: 600;
font-size: 1.2rem;
font-family: "宋体";
margin: 15% 0 0 40%;
letter-spacing: -2px;
transform: rotate(-5deg);
text-shadow: #ff0000 1px 0 0, #ff0000 0 1px 0, #ff0000 -1px 0 0,
#ff0000 0 -1px 0;
}
@media screen and (max-width: 500px) {
.wm2 {
font-size: 1.1vw;
}
}
.wm2>table {
border-collapse: collapse;
}
.wm2>table tr td {
text-align: left;
position: relative;
white-space: nowrap;
padding: 3px 6px 0 3px;
border: 5px solid #ff0000;
}
.wm2 .wm-icon {
height: 25px;
}
.wm2 .wm-title {
font-size: 2rem;
text-align: center;
}
.wm2 .wm-sign {
position: absolute;
height: 150px;
top: -50px;
}
.wm2 .wm-footer {
text-align: left;
padding-top: 10px;
white-space: nowrap;
letter-spacing: -2px;
}
var pv = {
pdfViewer: document.querySelector(".nr-pdf-viewer"),
pdfDocument: null,
loadUrl: function (url) {
pdfjsLib.getDocument(url).promise.then(function (pdfDocument) {
pv.pdfDocument = pdfDocument;
pv.renderDocument(pv.pdfDocument);
}).catch(function (reason) {
console.error(reason);
})
},
renderDocument: function (pdfDocument) {
pv.pdfViewer.innerHTML = "";
//总页数
let pageCount = pdfDocument.numPages;
var nrwm = document.querySelector('.nr-watermark');
//构建空页
for (var i = 0; i < pageCount; i++) {
//页
let div = document.createElement("div");
div.className = "nr-pdf-page";
div.id = "nr-pdf-page-" + (i + 1);
div.innerHTML = '<canvas></canvas>';
//水印
if (nrwm.value == "1") {
div.appendChild(wm.two());
}
//换行
let nl = document.createElement("div");
nl.className = "nr-newline";
pv.pdfViewer.appendChild(div);
pv.pdfViewer.appendChild(nl);
}
for (let pageIndex = 1; pageIndex <= pageCount; pageIndex++) {
pdfDocument.getPage(pageIndex).then(function (pdfPage) {
let canvas = document.getElementById("nr-pdf-page-" + pageIndex).firstChild;
const viewport = pdfPage.getViewport({ scale: document.querySelector('.nr-size').value * 1 });
canvas.width = viewport.width;
canvas.height = viewport.height;
const ctx = canvas.getContext("2d");
const renderTask = pdfPage.render({
canvasContext: ctx,
viewport,
});
return renderTask.promise;
});
}
},
base64ToUint8Array: function (base64) {
var raw = atob(base64);
var uint8Array = new Uint8Array(raw.length);
for (var i = 0; i < raw.length; i++) {
uint8Array[i] = raw.charCodeAt(i);
}
return uint8Array;
},
receiveFiles: function (fn) {
//拖拽
"dragleave dragenter dragover".split(' ').forEach(en => {
document.addEventListener(en, function (e) {
e.stopPropagation();
e.preventDefault();
})
})
document.addEventListener("drop", function (e) {
e.preventDefault();
var files = (e.dataTransfer || e.originalEvent.dataTransfer).files;
if (files && files.length) {
fn(files);
}
})
}
}
pv.loadUrl("https://gs.zme.ink/2019/07/06/181724f50f.pdf");
pv.receiveFiles(function (files) {
var file = files[0];
if (file.type == "application/pdf") {
var r = new FileReader();
r.onload = function (e) {
pv.loadUrl(pv.base64ToUint8Array(e.target.result.split(',').pop()));
}
r.readAsDataURL(file);
}
});
window.onhashchange = function () {
var url = location.hash.substring(1);
if (url.includes("://")) {
pv.loadUrl(url);
}
}
document.querySelector('.nr-size').onchange = function () {
pv.renderDocument(pv.pdfDocument);
}
document.querySelector('.nr-watermark').onchange = function () {
pv.renderDocument(pv.pdfDocument);
}
document.querySelector('.nr-spin').onchange = function () {
console.log(this.value)
pv.pdfViewer.classList.remove("nr-spin-90")
pv.pdfViewer.classList.remove("nr-spin-180")
pv.pdfViewer.classList.remove("nr-spin-270")
if (this.value != "0") {
pv.pdfViewer.classList.add('nr-spin-' + this.value);
}
}
var wm = {
two: function () {
var wmbox = document.createElement('div');
wmbox.className = "wm wm2";
wmbox.innerHTML = `
<table>
<tr>
<td colspan="2"><img class="wm-icon" src="https://img11.360buyimg.com/ddimg/jfs/t1/172605/23/10640/69151/60a7aaa7Eb219c62e/73fcbb83d4a2db76.png" /><div class="wm-title">计量章CALIBRATION</div></td>
</tr>
<tr>
<td>位置 LOCATION</td>
<td></td>
</tr>
<tr>
<td>计量结果 CAL RESULT</td>
<td>合格PASS/不合格FAIL</td>
</tr>
<tr>
<td>发布标签 DECAL ISSUED</td>
<td>是YES/否NO</td>
</tr>
<tr>
<td>系统更新 SYSTEM UPDATED</td>
<td>是YES/否NO</td>
</tr>
<tr>
<td>日期 DATE</td>
<td></td>
</tr>
<tr>
<td>签字 SIGNATURE</td>
<td><div><img class="wm-sign" src="https://img10.360buyimg.com/ddimg/jfs/t1/196646/31/4138/28688/60a7aaa7E8a3d9042/c1f79bcc2afe5ebc.png" /></div></td>
</tr>
</table>
<div class="wm-footer">XFQA-D001-010(23/11/2018)</div>
`;
return wmbox;
}
}