目录
一、基于pdf.js、turnjs4封装的3d翻页效果pdf文件阅读器、pdf文件url拼接地址栏就可以展示、兼容pc端、H5端
一、基于pdf.js、turnjs4封装的3d翻页效果pdf文件阅读器、pdf文件url拼接地址栏就可以展示、兼容pc端、H5端
二、效果展示图
三、部分源码
<script>
/*定义变量参数 */
// 定义一个空字符串变量用于存储PDF文件的URL
var pdfurl = "";
// 获取flipbook元素,该元素将被用来呈现翻页效果
var flipbook = $("#flipbook");
// 初始化当前页码为1
var pageCurrent = 0;
// 设置书本ID,可以根据需要进行更改
var bid = 1;
// 初始化缩放比例和旋转角度为1(即不缩放、不旋转)
var scale = 1;
var rotate = 1;
// 初始化画布宽度和高度为空值,在后续代码中会动态设置这些值
var canvasWidth = null;
var canvasHeight = null;
const getUrlParam = (name) => {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象
var r = window.location.search.substring(1).match(reg); //匹配目标参数
if (r != null) return decodeURI(r[2]);
return null; //返回参数值
};
const isMobile = () => {
// 检查用户代理是否包含“Mobi”子字符串
return /Mobi/.test(navigator.userAgent);
};
const disableScroll = () => {
// 获取当前垂直滚动位置
let scrollTop = window.pageYOffset || document.documentElement.scrollTop;
// 禁用默认的窗口滚动行为
const preventDefault = (e) => {
e.preventDefault();
};
// 在触摸设备上,禁用touchmove事件来防止页面滑动。
document.body.addEventListener("touchmove", preventDefault, {
passive: false,
});
//在非触摸设备上,阻止窗口滚动事件并将其替换为preventDefault函数。
window.addEventListener("scroll", preventDefault);
// 将body元素的样式设置为固定,并将其上一个滚动位置应用于它。
document.body.style.position = "fixed";
document.body.style.top = -scrollTop + "px";
};
const preloadPdf = async (url) => {
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
return pdfjsLib.getDocument(arrayBuffer);
};
// 在页面加载时就开始预加载PDF文件
window.addEventListener("load", async () => {
if (getUrlParam("pdfurl") != null) {
pdfurl = getUrlParam("pdfurl");
getpdf(pdfurl);
var vConsole = new VConsole();
disableScroll();
console.log(pdfurl);
} else {
alert("文件为空");
}
});
const getpdf = async (url) => {
const loadingTask = pdfjsLib.getDocument(url);
const pdf = await loadingTask.promise;
// 获取第一页的视图,并根据其宽度设置 flipbook 的宽度
const firstPage = await pdf.getPage(1);
const viewport = firstPage.getViewport({ scale: scale });
const mobieWidth = viewport.width * 2;
const pcWidth = viewport.width * 2;
const pdfWidth = isMobile() ? mobieWidth : pcWidth;
const canvasCache = {};
// 一次性获取所有页面的canvas对象,并将其缓存起来
for (let i = 1; i <= pdf.numPages; i++) {
const id = "canvaspage" + i;
const div = document.createElement("div");
div.innerHTML = `<canvas id="${id}" class="page"></canvas>`;
flipbook.append(div);
const page = await pdf.getPage(i);
const canvas = await setcanvas(page, id);
canvasCache[id] = canvas;
}
// 加载turn.js并设置参数
await new Promise((resolve) => {
yepnope({
test: Modernizr.csstransforms,
yep: ["./JS/turnjs4/lib/turn.js"],
complete: () => {
$("#flipbook").turn({
width: pdfWidth,
height: viewport.height,
elevation: 50,
display: isMobile() ? "single" : "double",
autoCenter: true,
duration: 1000,
gradients: true,
disable: true,
// 添加turn.js的turned事件回调函数,用于预加载相邻页面
// 预加载相邻页面的数量可以根据实际情况调整
turned: async function (event, page = 1) {
console.log(event, page, "33333333333333");
const prevPage = page - 1;
const nextPage = page + 1;
// 预加载当前页面的相邻页面
if (prevPage > 0 && !canvasCache[prevPage]) {
const id = "canvaspage" + prevPage;
const div = document.createElement("div");
div.innerHTML = `<canvas id="${id}" class="page"></canvas>`;
flipbook.append(div);
const page = await pdf.getPage(prevPage);
const canvas = await setcanvas(page, id);
canvasCache[prevPage] = canvas;
}
if (nextPage <= pdf.numPages && !canvasCache[nextPage]) {
const id = "canvaspage" + nextPage;
const div = document.createElement("div");
div.innerHTML = `<canvas id="${id}" class="page"></canvas>`;
flipbook.append(div);
const page = await pdf.getPage(nextPage);
const canvas = await setcanvas(page, id);
canvasCache[nextPage] = canvas;
}
// 移除未缓存的旧页面
const unloadPage = isMobile() ? page + 2 : page + 4;
const unloadPage2 = isMobile() ? page - 2 : page - 4;
if (canvasCache[unloadPage]) {
const canvas = canvasCache[unloadPage];
delete canvasCache[unloadPage];
canvas.parentNode.remove();
}
if (canvasCache[unloadPage2]) {
const canvas = canvasCache[unloadPage2];
delete canvasCache[unloadPage2];
canvas.parentNode.remove();
}
},
});
resolve();
},
});
});
// 预加载所有canvas对象的图像数据
Object.values(canvasCache).forEach((canvas) => {
const context = canvas.getContext("2d");
const imageData = context.getImageData(
0,
0,
canvas.width,
canvas.height
);
});
// 使用pdf.js库解析PDF文档并返回Promise对象,在解析完成后隐藏遮罩层。
const response = await fetch(url);
const arrayBuffer = await response.arrayBuffer();
const pdfData = new Uint8Array(arrayBuffer);
await pdfjsLib.getDocument(pdfData).promise;
$("#overlay").hide();
};
const canvasCache = {};
const setcanvas = async (page, id) => {
const canvas = document.getElementById(id);
const canvasRect = canvas.getBoundingClientRect();
const isVisible =
canvasRect.bottom > 0 &&
canvasRect.top < window.innerHeight &&
canvasRect.right > 0 &&
canvasRect.left < window.innerWidth;
if (isVisible) {
// 如果 canvas 可见,则将其添加到缓存中
canvasCache[id] = canvas;
} else {
// 如果 canvas 不可见,则从缓存中删除它
delete canvasCache[id];
}
if (!canvas) {
console.log("Canvas element with ID " + id + " not found.");
return;
}
const context = canvas.getContext("2d");
if (!context) {
console.log("Could not get 2D context for canvas element.");
return;
}
const viewport = page.getViewport({ scale: scale });
const screenWidth = Math.min(window.innerWidth, window.innerHeight);
const newScale = screenWidth / viewport.width;
const newViewport = page.getViewport({ scale: newScale });
const outputScale = window.devicePixelRatio;
canvas.width = Math.floor(newViewport.width * outputScale);
canvas.height = Math.floor(newViewport.height * outputScale);
canvas.style.width = "100%";
canvas.style.height = "100%";
const transform =
outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null;
const renderContext = {
canvasContext: context,
transform: transform,
viewport: newViewport,
};
await page.render(renderContext).promise;
return canvas;
};
$(function () {
$(".flip_button_left").bind("click", function () {
$("#flipbook").turn("previous");
});
$(".flip_button_right").bind("click", function () {
$("#flipbook").turn("next");
});
});
</script>