Archived
1
0
This repository has been archived on 2025-04-26. You can view files and clone it, but cannot push or open issues or pull requests.
pdf2img/cssjs/js/main.js

376 lines
11 KiB
JavaScript
Raw Normal View History

// 设置PDF.js worker路径
pdfjsLib.GlobalWorkerOptions.workerSrc = 'cssjs/js/pdf.worker.js';
// 全局变量
let pdfDocument = null;
let pdfFile = null;
let renderedPages = [];
// DOM元素
const uploadArea = document.getElementById('upload-area');
const pdfFileInput = document.getElementById('pdf-file-input');
const selectFileBtn = document.getElementById('select-file-btn');
const loadingContainer = document.getElementById('loading-container');
const pdfInfoContainer = document.getElementById('pdf-info-container');
const previewContainer = document.getElementById('preview-container');
const previewItems = document.getElementById('preview-items');
const exportBtn = document.getElementById('export-btn');
const combinePagesSwitch = document.getElementById('combine-pages-switch');
const highQualitySwitch = document.getElementById('high-quality-switch');
// PDF信息显示元素
const pdfNameValue = document.getElementById('pdf-name-value');
const pdfSizeValue = document.getElementById('pdf-size-value');
const pdfPagesValue = document.getElementById('pdf-pages-value');
// 事件监听器
document.addEventListener('DOMContentLoaded', function() {
// 检查PDF.js是否正确加载
if (typeof pdfjsLib === 'undefined') {
alert('PDF.js库加载失败请确保pdf.js文件已正确放置');
return;
}
// 初始化事件监听
initEventListeners();
});
// 初始化事件监听器
function initEventListeners() {
selectFileBtn.addEventListener('click', () => pdfFileInput.click());
pdfFileInput.addEventListener('change', handleFileSelect);
exportBtn.addEventListener('click', exportImages);
// 拖放功能
uploadArea.addEventListener('dragover', (e) => {
e.preventDefault();
uploadArea.classList.add('dragover');
});
uploadArea.addEventListener('dragleave', () => {
uploadArea.classList.remove('dragover');
});
uploadArea.addEventListener('drop', (e) => {
e.preventDefault();
uploadArea.classList.remove('dragover');
if (e.dataTransfer.files.length > 0) {
const file = e.dataTransfer.files[0];
if (file.type === 'application/pdf') {
pdfFileInput.files = e.dataTransfer.files;
handleFileSelect(e);
} else {
showError('请选择PDF文件');
}
}
});
}
// 处理文件选择
function handleFileSelect(e) {
const file = pdfFileInput.files[0];
if (!file) return;
if (file.type !== 'application/pdf') {
showError('请选择PDF文件');
return;
}
if (file.size > 20 * 1024 * 1024) { // 20MB
showError('文件大小不能超过20MB');
return;
}
pdfFile = file;
// 显示加载状态
uploadArea.style.display = 'none';
loadingContainer.style.display = 'block';
previewContainer.style.display = 'none';
pdfInfoContainer.style.display = 'none';
previewItems.innerHTML = '';
renderedPages = [];
// 读取PDF文件
const reader = new FileReader();
reader.onload = function(event) {
const typedArray = new Uint8Array(event.target.result);
loadPdfFromData(typedArray);
};
reader.readAsArrayBuffer(file);
}
// 从ArrayBuffer加载PDF
function loadPdfFromData(data) {
pdfjsLib.getDocument({ data }).promise
.then(pdf => {
pdfDocument = pdf;
// 更新PDF信息
pdfNameValue.textContent = pdfFile.name;
pdfSizeValue.textContent = formatFileSize(pdfFile.size);
pdfPagesValue.textContent = pdf.numPages;
// 渲染预览
renderPdfPreview(pdf);
})
.catch(error => {
console.error('PDF加载错误:', error);
showError('无法加载PDF文件请确保文件未损坏');
resetUI();
});
}
// 渲染PDF预览
function renderPdfPreview(pdf) {
const totalPages = pdf.numPages;
let renderedCount = 0;
// 更新加载文本
document.getElementById('loading-text').textContent = `正在渲染预览 (0/${totalPages})`;
// 为每一页创建预览
for (let pageNumber = 1; pageNumber <= totalPages; pageNumber++) {
pdf.getPage(pageNumber).then(page => {
const scale = 0.5; // 预览缩放比例
const viewport = page.getViewport({ scale });
// 创建canvas元素
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
canvas.width = viewport.width;
canvas.height = viewport.height;
// 渲染PDF页面到canvas
const renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext).promise.then(() => {
renderedCount++;
document.getElementById('loading-text').textContent = `正在渲染预览 (${renderedCount}/${totalPages})`;
// 存储渲染的页面
renderedPages[pageNumber - 1] = {
pageNumber: pageNumber,
canvas: canvas,
width: viewport.width,
height: viewport.height
};
// 如果所有页面都已渲染,显示预览
if (renderedCount === totalPages) {
displayPreviews();
}
});
});
}
}
// 显示预览
function displayPreviews() {
// 按页码排序
renderedPages.sort((a, b) => a.pageNumber - b.pageNumber);
// 清空预览容器
previewItems.innerHTML = '';
// 添加每一页的预览
renderedPages.forEach(page => {
const colDiv = document.createElement('div');
colDiv.className = 'col-md-6 col-lg-4 preview-item';
const pageNumberDiv = document.createElement('div');
pageNumberDiv.className = 'page-number';
pageNumberDiv.textContent = `${page.pageNumber}`;
// 克隆canvas以避免原始canvas被修改
const displayCanvas = document.createElement('canvas');
displayCanvas.width = page.canvas.width;
displayCanvas.height = page.canvas.height;
const displayContext = displayCanvas.getContext('2d');
displayContext.drawImage(page.canvas, 0, 0);
colDiv.appendChild(displayCanvas);
colDiv.appendChild(pageNumberDiv);
previewItems.appendChild(colDiv);
});
// 显示预览和控制面板
loadingContainer.style.display = 'none';
pdfInfoContainer.style.display = 'block';
previewContainer.style.display = 'block';
}
// 导出图片
function exportImages() {
if (!pdfDocument || renderedPages.length === 0) {
showError('没有可导出的内容');
return;
}
const combinePages = combinePagesSwitch.checked;
const highQuality = highQualitySwitch.checked;
const scale = highQuality ? 2.0 : 1.0;
// 显示加载状态
loadingContainer.style.display = 'block';
document.getElementById('loading-text').textContent = '正在准备导出...';
if (combinePages) {
// 合并为单张图片
exportCombinedImage(scale);
} else {
// 导出为多张图片
exportMultipleImages(scale);
}
}
// 导出合并的单张图片
function exportCombinedImage(scale) {
// 计算合并后的图片尺寸
let totalHeight = 0;
let maxWidth = 0;
renderedPages.forEach(page => {
totalHeight += page.height * (scale / 0.5);
maxWidth = Math.max(maxWidth, page.width * (scale / 0.5));
});
// 创建合并的canvas
const combinedCanvas = document.createElement('canvas');
combinedCanvas.width = maxWidth;
combinedCanvas.height = totalHeight;
const combinedContext = combinedCanvas.getContext('2d');
// 填充白色背景
combinedContext.fillStyle = '#FFFFFF';
combinedContext.fillRect(0, 0, combinedCanvas.width, combinedCanvas.height);
// 重新渲染每一页到合并的canvas
let currentY = 0;
let renderedCount = 0;
const renderNextPage = (index) => {
if (index >= renderedPages.length) {
// 所有页面都已渲染,导出图片
combinedCanvas.toBlob(blob => {
saveAs(blob, `${pdfFile.name.replace('.pdf', '')}_combined.png`);
loadingContainer.style.display = 'none';
}, 'image/png');
return;
}
const page = renderedPages[index];
// 更新加载文本
document.getElementById('loading-text').textContent = `正在合并页面 (${index + 1}/${renderedPages.length})`;
// 获取原始页面
pdfDocument.getPage(page.pageNumber).then(pdfPage => {
const viewport = pdfPage.getViewport({ scale });
// 创建临时canvas
const tempCanvas = document.createElement('canvas');
tempCanvas.width = viewport.width;
tempCanvas.height = viewport.height;
const tempContext = tempCanvas.getContext('2d');
// 渲染到临时canvas
const renderContext = {
canvasContext: tempContext,
viewport: viewport
};
pdfPage.render(renderContext).promise.then(() => {
// 将临时canvas的内容绘制到合并的canvas
const x = (maxWidth - viewport.width) / 2; // 居中
combinedContext.drawImage(tempCanvas, x, currentY);
// 更新Y坐标
currentY += viewport.height;
// 渲染下一页
renderNextPage(index + 1);
});
});
};
// 开始渲染第一页
renderNextPage(0);
}
// 导出多张图片
function exportMultipleImages(scale) {
const zip = new JSZip();
const folder = zip.folder("images");
let processedCount = 0;
// 更新加载文本
document.getElementById('loading-text').textContent = `正在导出图片 (0/${renderedPages.length})`;
// 处理每一页
renderedPages.forEach((page, index) => {
// 获取原始页面
pdfDocument.getPage(page.pageNumber).then(pdfPage => {
const viewport = pdfPage.getViewport({ scale });
// 创建canvas
const canvas = document.createElement('canvas');
canvas.width = viewport.width;
canvas.height = viewport.height;
const context = canvas.getContext('2d');
// 填充白色背景
context.fillStyle = '#FFFFFF';
context.fillRect(0, 0, canvas.width, canvas.height);
// 渲染PDF页面到canvas
const renderContext = {
canvasContext: context,
viewport: viewport
};
pdfPage.render(renderContext).promise.then(() => {
// 将canvas转换为blob
canvas.toBlob(blob => {
// 添加到zip
folder.file(`page_${page.pageNumber}.png`, blob);
processedCount++;
document.getElementById('loading-text').textContent = `正在导出图片 (${processedCount}/${renderedPages.length})`;
// 如果所有页面都已处理生成并下载zip
if (processedCount === renderedPages.length) {
zip.generateAsync({ type: 'blob' }).then(content => {
saveAs(content, `${pdfFile.name.replace('.pdf', '')}_images.zip`);
loadingContainer.style.display = 'none';
});
}
}, 'image/png');
});
});
});
}
// 辅助函数
function formatFileSize(bytes) {
if (bytes < 1024) return bytes + ' B';
else if (bytes < 1048576) return (bytes / 1024).toFixed(2) + ' KB';
else return (bytes / 1048576).toFixed(2) + ' MB';
}
function showError(message) {
alert(message);
}
function resetUI() {
uploadArea.style.display = 'block';
loadingContainer.style.display = 'none';
pdfInfoContainer.style.display = 'none';
previewContainer.style.display = 'none';
pdfFileInput.value = '';
}