212 lines
6.9 KiB
HTML
Raw Normal View History

2025-04-14 14:43:48 +08:00
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片转PDF</title>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
margin: 0;
background-color: #f4f4f4;
}
h1 {
font-size: 2.5vw;
margin-bottom: 20px;
color: #333;
}
#image-container {
display: flex;
flex-wrap: wrap;
gap: 15px;
justify-content: center;
margin: 20px 0;
padding: 10px;
border: 2px dashed #ccc;
background-color: #fff;
min-height: 100px;
width: 100%;
max-width: 1200px;
}
.image-item {
position: relative;
border: 1px solid #ccc;
overflow: hidden;
transition: transform 0.2s;
cursor: move; /* 提示用户可以拖拽 */
}
.image-item:hover {
transform: scale(1.05);
}
.image-item img {
width: 100%;
height: 100%;
object-fit: cover;
}
.delete-btn {
position: absolute;
top: 5px;
right: 5px;
background-color: rgb(0, 0, 0);
opacity: 0.5;
color: white;
margin: 0;
border: none;
border-radius: 50%;
width: 20px;
height: 20px;
padding: 0;
font-size: 12px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
button {
padding: 10px 20px;
font-size: 16px;
background-color: #007BFF;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
margin-top: 20px;
}
button:hover {
background-color: #0056b3;
}
@media (max-width: 600px) {
h1 {
font-size: 5vw;
}
button {
font-size: 14px;
padding: 8px 16px;
}
}
</style>
</head>
<body>
<h1>图片转PDF</h1>
<input type="file" id="file-input" multiple accept="image/*">
<div id="image-container"></div>
<button id="generate-pdf">生成PDF</button>
<!-- 引入外部库 -->
<script src="../../../libs/Sortable.min.js"></script>
<script src="../../../libs/pdf-lib.min.js"></script>
<script>
const fileInput = document.getElementById('file-input');
const imageContainer = document.getElementById('image-container');
const generateButton = document.getElementById('generate-pdf');
let images = [];
// 文件选择事件
fileInput.addEventListener('change', (e) => {
handleFiles(e.target.files);
});
// 生成PDF
generateButton.addEventListener('click', async () => {
if (images.length === 0) {
alert('请先添加至少一张图片!');
return;
}
const pdfDoc = await PDFLib.PDFDocument.create();
for (const image of images) {
const imgBytes = await fetch(image.src).then(res => res.arrayBuffer());
let img = image.file.type === 'image/png' ?
await pdfDoc.embedPng(imgBytes) :
await pdfDoc.embedJpg(imgBytes);
const page = pdfDoc.addPage([img.width, img.height]);
page.drawImage(img, { x: 0, y: 0, width: img.width, height: img.height });
}
const pdfBytes = await pdfDoc.save();
const blob = new Blob([pdfBytes], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = '图片合集.pdf';
a.click();
URL.revokeObjectURL(url);
});
// 处理文件
function handleFiles(files) {
Array.from(files).forEach(file => {
if (file.type.startsWith('image/')) {
const reader = new FileReader();
reader.onload = function(e) {
const imgWrapper = document.createElement('div');
imgWrapper.classList.add('image-item');
const img = document.createElement('img');
img.src = e.target.result;
const deleteBtn = document.createElement('button');
deleteBtn.classList.add('delete-btn');
deleteBtn.innerHTML = '×';
deleteBtn.addEventListener('click', () => {
imgWrapper.remove();
images = images.filter(item => item.src !== img.src);
});
imgWrapper.appendChild(img);
imgWrapper.appendChild(deleteBtn);
imageContainer.appendChild(imgWrapper);
images.push({ src: e.target.result, file });
setImageSize();
};
reader.readAsDataURL(file);
}
});
}
// 获取视口宽度
function getViewportWidth() {
return window.innerWidth || document.documentElement.clientWidth;
}
// 设置图片尺寸
function setImageSize() {
const viewportWidth = getViewportWidth();
const imageItems = document.querySelectorAll('.image-item');
let size = viewportWidth >= 1200 ? 150 : viewportWidth >= 600 ? 100 : 80;
imageItems.forEach(item => {
item.style.width = `${size}px`;
item.style.height = `${size}px`;
});
}
// 监听窗口resize事件
window.addEventListener('resize', setImageSize);
setImageSize();
// 拖拽导入支持
imageContainer.addEventListener('dragover', (e) => {
e.preventDefault();
});
imageContainer.addEventListener('drop', (e) => {
e.preventDefault();
if (e.dataTransfer.files.length > 0) {
handleFiles(e.dataTransfer.files);
}
});
// 初始化 Sortable.js 进行拖拽排序
new Sortable(imageContainer, {
animation: 150,
onEnd: function(evt) {
// 更新 images 数组顺序
const movedItem = images.splice(evt.oldIndex, 1)[0];
images.splice(evt.newIndex, 0, movedItem);
}
});
</script>
</body>
</html>