How to Build a Browser-Based PDF Blur Tool Using JavaScript

TL;DR · AI 摘要
本文提供基于JavaScript的PDF模糊工具开发方案,使用PDF.js和PDF-lib实现浏览器端PDF处理,无需服务器交互。
核心要点
- 使用PDF.js渲染PDF页面并转换为HTML Canvas进行模糊操作
- 通过PDF-lib库实现模糊效果的PDF文件生成
- 支持区域选择、强度调节和多页处理的完整功能链
结构提纲
按章节快速跳转。
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- 浏览器PDF模糊工具
- 技术实现
- PDF.js渲染
- Canvas交互
- PDF-lib生成
- 功能模块
- 区域选择
- 强度调节
- 多页处理
金句 / Highlights
值得收藏与分享的关键句。
PDF.js将PDF页面渲染为Canvas,实现浏览器端无插件PDF可视化
PDF-lib库支持在现有PDF基础上叠加模糊效果而不破坏原始内容
客户端完整处理流程避免敏感数据上传服务器,提升隐私安全性
如何使用 JavaScript 构建基于浏览器的 PDF 模糊工具
2026年7月24日
/
#JavaScript
Bhavin Sheth
许多 PDF 文档包含不应公开共享的信息。个人详细信息、财务数据、签名、地址、账户号码、员工信息或机密业务数据在发送文件给其他人之前通常需要隐藏。
PDF 模糊工具使这一过程变得简单。它不会永久删除内容,而是在 PDF 的选定区域上添加模糊效果,使敏感信息难以阅读,同时保持文档其余部分不变。
在本教程中,你将使用 JavaScript 构建一个基于浏览器的 PDF 模糊工具。用户将能够上传 PDF,预览每一页,在敏感内容上绘制模糊框,调整模糊强度,将模糊效果应用到选定页面,预览最终结果,并下载处理后的 PDF,整个过程无需将文件上传到服务器。
我们将使用 PDF.js 在浏览器中渲染 PDF 页面,使用 HTML Canvas 创建和管理模糊区域,并使用 PDF-lib 生成最终的模糊 PDF。
完成本教程后,你将拥有一个功能齐全的客户端 PDF 编辑工具,与我网站(AllInOneTools)上提供的工具类似。
目录
- 这个 PDF 模糊工具的功能及其工作原理
- 项目设置
- 创建 HTML 布局
- 上传和预览 PDF
- 创建模糊区域
- 将模糊效果应用到页面
- 生成最终 PDF
- 预览结果
- 重命名和下载
- 演示:PDF 模糊工具的工作原理
- 性能优化技巧
- 常见错误
- 总结
这个 PDF 模糊工具的功能及其工作原理
PDF 模糊工具在文档共享前帮助保护敏感信息。它不会编辑或删除原始内容,而是在选定区域上应用视觉模糊效果,使机密信息变得不可读,同时保持文档其余部分不变。
这种方法对于隐藏个人详细信息、财务信息、账户号码、签名、地址、人脸或任何不应在最终文档中显示的私人内容非常有用。
在这个项目中,用户可以直接从浏览器上传 PDF,预览每一页,并在需要隐藏的区域绘制一个或多个模糊区域。该工具还允许用户调整模糊强度,对选定区域或整个页面进行模糊处理,将效果应用到当前页面、所有页面或特定页面范围,预览完成的文档,重命名输出文件,并下载最终的 PDF。
由于所有操作都在浏览器中运行,因此不会将文件上传到服务器,有助于保持文档隐私。
在后台,应用程序首先使用 PDF.js 将每一页 PDF 渲染到 HTML 画布上。而不是立即修改原始 PDF,它会记录用户创建的每个模糊区域的位置、大小、页码和模糊强度。
当用户点击“应用并最终确定”时,这些存储的区域会从浏览器坐标转换为实际的 PDF 页面坐标。然后将选定的模糊效果应用到渲染后的页面,PDF-lib 会生成一个包含模糊内容的新 PDF,同时保留文档的其余部分。
这种工作流程提供了交互式编辑体验,同时在最终生成文档之前保持原始 PDF 不变。
例如,每个模糊区域可以表示为如下对象:
const blurRegion = {
page: 2,
x: 180,
y: 240,
width: 260,
height: 90,
intensity: 6
};每个对象都存储了在最终生成 PDF 过程中重现模糊效果所需的所有信息。
项目设置
在编写任何代码之前,让我们为 PDF Blur Tool 创建一个简单的项目结构。
我们将使用纯 HTML、CSS 和 JavaScript,以及两个库:
- PDF.js 用于在浏览器中渲染 PDF 页面。
- PDF-lib 用于生成最终的模糊 PDF。
我们的项目结构如下所示:
pdf-blur-tool/
│── index.html
│── style.css
│── script.js
│── pdf.worker.min.js
│── assets/保持项目简单有助于更清楚地理解每个部分的工作原理。
在加载自己的 JavaScript 之前,先添加 PDF.js 和 PDF-lib。
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.4.168/pdf.min.js"></script>
<script src="https://unpkg.com/pdf-lib/dist/pdf-lib.min.js"></script>
<script src="script.js"></script>配置 PDF 工作线程。
pdfjsLib.GlobalWorkerOptions.workerSrc =
"pdf.worker.min.js";工作线程在后台线程中处理 PDF 渲染,有助于在页面渲染时保持界面的响应性。
创建 HTML 布局
该应用由四个主要部分组成:
- 上传区域
- PDF 预览
- 模糊设置面板
- 最终下载区域
创建基本布局:
<div id="uploadSection"></div>
<div id="editorSection" hidden>
<div id="pdfPreview"></div>
<aside id="blurSettings"></aside>
</div>
<div id="resultSection" hidden></div>初始状态下,仅显示上传区域。
选择 PDF 后,编辑器将变得可见。
选择 DOM 元素
创建对应用中使用的元素的引用。
const uploadSection =
document.getElementById(
"uploadSection"
);
const editorSection =
document.getElementById(
"editorSection"
);
const resultSection =
document.getElementById(
"resultSection"
);
const fileInput =
document.getElementById(
"pdfInput"
);
const pdfCanvas =
document.getElementById(
"pdfCanvas"
);
const canvasContext =
pdfCanvas.getContext("2d");这些引用使应用能够在上传、编辑和下载阶段之间切换。
上传和预览 PDF
上传区域支持拖放和传统文件选择两种方式。
当选择 PDF 后,在继续之前验证它确实是一个 PDF 文件。
async function handlePdfUpload(
file
) {
if (
!file ||
file.type !==
"application/pdf"
) {
alert(
"Please select a PDF file."
);
return;
}
await loadPdf(file);
}如果验证成功,文档将被加载到内存中。
读取 PDF
使用 File API 将上传的文件转换为 ArrayBuffer。
async function loadPdf(
file
) {
const bytes =
await file.arrayBuffer();
pdfDocument =
await pdfjsLib
.getDocument({
data: bytes
})
.promise;
currentPage = 1;
await renderPage(
currentPage
);
}上传的字节在生成模糊 PDF 时也会被再次使用。
渲染第一页
PDF.js 将每一页渲染到 HTML 画布上。
首先获取请求的页面。
async function renderPage(
pageNumber
) {
const page =
await pdfDocument
.getPage(
pageNumber
);
const viewport =
page.getViewport({
scale: 1.5
});调整画布大小以匹配页面尺寸。
pdfCanvas.width =
viewport.width;
pdfCanvas.height =
viewport.height;渲染页面。
await page.render({
canvasContext,
viewport
}).promise;渲染完成后,PDF 页面将在编辑器中显示出来。
创建页面导航
大多数 PDF 文档包含多页内容。
允许用户通过上一页和下一页按钮在页面间切换。
let currentPage = 1;
let pdfDocument = null;切换到上一页。
previousButton
.addEventListener(
"click",
async () => {
if (
currentPage === 1
) {
return;
}
currentPage--;
await renderPage(
currentPage
);
}
);切换到下一页。
nextButton
.addEventListener(
"click",
async () => {
if (
currentPage ===
pdfDocument.numPages
) {
return;
}
currentPage++;
await renderPage(
currentPage
);
}
);每当当前页面发生变化时更新页码显示。
pageIndicator.textContent =
`Page ${currentPage} of ${pdfDocument.numPages}`;这为用户在浏览大型 PDF 文档时提供了清晰的反馈。
准备模糊编辑
当前页面渲染完成后,应用程序会在 PDF 画布上方创建一个透明图层。
该图层用于捕获鼠标交互,而不会修改原始页面预览。
创建图层。
<canvas
id="overlayCanvas">
</canvas>调整其大小以匹配 PDF 预览。
overlayCanvas.width =
pdfCanvas.width;
overlayCanvas.height =
pdfCanvas.height;在后续教程中,这个图层将允许用户在不修改底层 PDF 页面的情况下绘制模糊区域。
显示编辑器
当第一页渲染完成后,切换从上传界面到编辑器界面。
uploadSection.hidden =
true;
editorSection.hidden =
false;用户现在可以预览文档、在页面间导航,并开始选择需要模糊的区域。
创建模糊区域
现在 PDF 预览功能已就绪,我们可以构建应用程序最重要的功能:允许用户对敏感信息进行模糊处理。
用户不会立即编辑 PDF,而是先在页面预览上绘制一个或多个模糊区域。
每个区域会存储自己的位置、尺寸和模糊强度。这些区域将在最终处理时转换为实际的 PDF 坐标。
创建模糊区域对象
每个模糊区域都表示为一个 JavaScript 对象。
例如:
const blurArea = {
page: currentPage,
x: 0,
y: 0,
width: 0,
height: 0,
intensity: 6
};而不是立即修改 PDF,应用程序会简单地跟踪这些对象,直到用户点击“应用并最终处理”。
存储多个模糊区域
用户通常需要隐藏多处信息。
将所有模糊区域存储在一个数组中。
const blurAreas = [];每当创建一个新的模糊框时,将其推入数组。
blurAreas.push({
page: currentPage,
x,
y,
width,
height,
/think
intensity: blurIntensity
});
这使得后续重新绘制、编辑或删除单个模糊区域变得简单。
### 开始模糊选择
透明叠加画布捕获鼠标交互。
当用户按下鼠标按钮时,记录起始位置。
let isDrawing = false;
let startX = 0;
let startY = 0;
overlayCanvas .addEventListener( "mousedown", event => {
isDrawing = true;
startX = event.offsetX;
startY = event.offsetY;
} );
模糊矩形从此处开始。
### 绘制模糊矩形
随着鼠标移动,更新矩形尺寸。
overlayCanvas .addEventListener( "mousemove", event => {
if ( !isDrawing ) {
return;
}
drawPreviewBox(
startX,
startY,
event.offsetX,
event.offsetY
);
} );
用户拖动鼠标时,预览会持续更新。
### 完成选择
当鼠标按钮释放时,保存完成的模糊区域。
overlayCanvas .addEventListener( "mouseup", event => {
isDrawing = false;
blurAreas.push({
page: currentPage,
x: startX,
y: startY,
width: event.offsetX - startX,
height: event.offsetY - startY,
intensity: blurIntensity
});
redrawBlurAreas();
updateBlurList();
} );
每个模糊区域都成为当前编辑会话的一部分。
### 绘制现有模糊区域
每当页面切换或添加模糊区域时,重新绘制所有模糊框。
function redrawBlurAreas() {
overlayContext.clearRect(
0,
0,
overlayCanvas.width,
overlayCanvas.height
);
blurAreas
.filter(
area =>
area.page === currentPage
)
.forEach(
drawBlurArea
);
}
这确保了在编辑过程中之前创建的模糊区域保持可见。
### 显示模糊框
使用虚线轮廓渲染每个存储的区域。
function drawBlurArea( area ) {
overlayContext .setLineDash([6, 4]);
overlayContext .strokeStyle = "#4f6cff";
overlayContext .strokeRect(
area.x,
area.y,
area.width,
area.height
);
}
轮廓作为参考线,不会成为最终PDF的一部分。
### 模糊选项
用户可以选择模糊的应用方式。
该工具支持两种模式:
- 模糊所选区域
- 模糊整个页面
所选选项控制编辑行为。
const blurMode = document.querySelector(
'input[name="blurMode"]:checked'
).value;
如果选择“模糊所选区域”,用户需要手动绘制模糊矩形。
如果选择“模糊整个页面”,应用会跳过手动选择,并在最终处理时准备模糊整个页面。
### 调整模糊强度
不同文档需要不同程度的模糊效果。
滑块让用户在应用效果前控制模糊强度。
const blurSlider = document.getElementById( "blurIntensity" );
let blurIntensity = 6;
blurSlider
.addEventListener(
"input",
event => {
blurIntensity =
Number(
event.target.value
);
}
);每次创建新的模糊区域时,所选值都会被存储。
blurArea.intensity =
blurIntensity;数值越大,模糊效果越明显。
管理多个模糊区域
许多文档包含多个机密信息。
为了不限制用户仅使用一个模糊矩形,应用程序会显示所有已保存的区域。
模糊区域 #1
模糊区域 #2
模糊区域 #3每个条目都包含一个删除按钮。
function removeBlurArea(
index
) {
blurAreas.splice(
index,
1
);
redrawBlurAreas();
updateBlurList();
}这使用户能够删除不再需要的模糊区域。
要从当前页面删除所有模糊区域:
function clearCurrentPage() {
const remaining =
blurAreas.filter(
area =>
area.page !==
currentPage
);
blurAreas.length = 0;
blurAreas.push(
...remaining
);
redrawBlurAreas();
}对页面应用模糊效果
用户可能希望仅对文档中的某一页或几页应用模糊效果。
编辑器提供三种选项:
- 仅当前页面
- 所有页面
- 指定页面
const pageOption =
document.querySelector(
'input[name="pageOption"]:checked'
).value;如果用户选择"指定页面",他们可以输入类似以下的值:
1, 3-5, 8在生成最终PDF之前,这些值将被转换为页面编号数组。
应用模糊效果
到目前为止,用户已上传PDF,选择了模糊区域,调整了模糊强度,并选择了需要处理的页面。
最后一步是将这些模糊区域转换为生成PDF中的实际模糊内容。
应用程序不会直接修改原始文档,而是创建新PDF的同时保留原始文件。
加载原始PDF
首先将上传的PDF加载到PDF-lib中。
async function applyBlur() {
const pdfDoc =
await PDFLib.PDFDocument.load(
originalPdfBytes.slice()
);
const pages =
pdfDoc.getPages();
}使用原始字节的副本可以确保上传的文档保持不变。
处理选定页面
确定需要应用模糊效果的页面。
const selectedPages =
parsePageSelection(
pageSelection,
pdfDoc.getPageCount()
);当前页面
↓
[2]
所有页面
↓
[1,2,3,4]
指定页面
↓
[1,3,5]仅这些页面会在处理过程中被修改。
将每页渲染为图像
由于模糊是基于像素的效果,每个选定的PDF页面都会被渲染到离屏画布中。
const page =
await pdfDocument.getPage(
pageNumber
);
const viewport =
page.getViewport({
scale: 2
});
const canvas =
document.createElement(
"canvas"
);
canvas.width =
viewport.width;
canvas.height =
viewport.height;await page.render({
canvasContext:
canvas.getContext("2d"),
viewport
}).promise;现在画布中包含可以编辑的PDF页面位图版本。
对选定区域应用模糊
获取属于当前页面的所有模糊区域。
const pageRegions =
blurAreas.filter(
area =>
area.page === pageNumber
);遍历每个模糊区域。
pageRegions.forEach(
area => {
blurCanvasRegion(
canvas,
area
);
}
);每个区域独立进行模糊处理。
模糊画布区域
浏览器的 Canvas API 允许在绘制时应用滤镜。
根据所选强度设置模糊滤镜。
context.filter =
`blur(${area.intensity}px)`;仅重绘所选区域。
context.drawImage(
canvas,
area.x,
area.y,
area.width,
area.height,
area.x,
area.y,
area.width,
area.height
);绘制完成后重置滤镜。
context.filter = "none";仅所选矩形区域会被模糊,页面其余部分保持不变。
模糊整个页面
如果用户选择“模糊整个页面”,处理过程会简单得多。
对整个画布应用滤镜。
context.filter =
`blur(${blurIntensity}px)`;
context.drawImage(
canvas,
0,
0
);
context.filter =
"none";整个渲染页面会应用所选的模糊效果。
将画布转换回 PDF 图像
编辑完画布后,将其转换为图像。
const imageData =
canvas.toDataURL(
"image/png"
);将图像转换为字节。
const bytes =
await fetch(imageData)
.then(
response =>
response.arrayBuffer()
);将图像嵌入 PDF-lib。
const image =
await pdfDoc.embedPng(
bytes
);替换页面内容。
const pdfPage =
pages[
pageNumber - 1
];
const size =
pdfPage.getSize();
pdfPage.drawImage(
image,
{
x: 0,
y: 0,
width:
size.width,
height:
size.height
}
);对每个选中的页面重复相同操作。
显示处理状态
生成大型 PDF 文件可能需要几秒钟。
处理期间显示加载状态。
applyButton.disabled =
true;
applyButton.textContent =
"Applying...";处理完成后:
applyButton.disabled =
false;
applyButton.textContent =
"Apply & Finalize";这为用户提供了明确的反馈,表明应用正在运行。
处理期间:
生成最终 PDF
所有页面处理完成后,保存完成的文档。
const pdfBytes =
await pdfDoc.save();
const outputBlob =
new Blob(
[pdfBytes],
{
type:
"application/pdf"
}
);存储结果以便稍后预览和下载。
generatedPdfBlob =
outputBlob;至此,模糊后的 PDF 已成功生成。
预览结果
隐藏编辑界面并显示完成的文档。
editorSection.hidden =
true;
resultSection.hidden =
false;结果界面显示:
- 最终 PDF 预览
- 可编辑的文件名
- 总页数
- 文件大小
- 下载按钮
用户可以在下载前查看处理后的文档。
重命名和下载
下载前,用户可能希望重命名生成的文件。
创建文件名输入框。
<input
type="text"
id="outputFilename"
value="blurred-document.pdf">验证文件名。
function getFilename() {
let filename =
outputFilename.value.trim();
if (!filename) {
filename =
"blurred-document.pdf";
}
if (
!filename
.toLowerCase()
.endsWith(".pdf")
) {
filename += ".pdf";
}
return filename;
}显示附加文件信息。
pageCount.textContent =
`Pages:
${finalPdfDocument.numPages}`;
fileSize.textContent =
formatFileSize(
generatedPdfBlob.size
);下载处理后的文档。
downloadButton
.addEventListener(
"click",
() => {
const url =
URL.createObjectURL(
generatedPdfBlob
);
const link =
document.createElement(
"a"
);
link.href = url;
link.download =
getFilename();
link.click();
URL.revokeObjectURL(
url
);
});浏览器直接下载完成的PDF文件,而无需将任何文件发送到远程服务器。
演示:PDF模糊工具的工作原理
让我们逐步了解完整的工作流程。
步骤1:上传PDF
用户通过拖放或点击“选择PDF”按钮上传PDF文件。
浏览器验证文件并准备渲染。
步骤2:预览文档
上传的PDF显示在预览窗口中。
用户可以使用页面导航控件在文档中切换页面。
步骤3:配置模糊设置
用户选择是对选中区域还是整页应用模糊效果。
在创建任何模糊区域之前,还可以配置模糊强度。
步骤4:绘制模糊区域
用户直接在PDF预览上点击拖拽,以在敏感内容上创建模糊矩形。
同一页面上可以创建多个模糊区域。
步骤5:调整模糊强度
模糊强度滑块控制模糊效果的强度。
数值越高,模糊效果越明显。
步骤6:管理模糊区域
可以删除单个模糊区域,或清除当前页面上的所有模糊区域。
这在生成最终PDF之前使编辑更加便捷。
步骤7:选择页面
用户决定模糊效果应用的页面范围:
- 当前页面
1,3-5,8步骤8:应用模糊效果
在确认设置后,用户点击“应用并完成”。
应用程序生成包含所选模糊效果的新PDF文件。
步骤9:查看最终文档
完成的PDF显示在预览窗口中。
用户可以在下载前验证所有模糊区域。
步骤10:重命名并下载
最后,用户可以重命名输出文件(如需),然后点击“下载”。
浏览器将完成的PDF保存到本地。
性能优化建议
大型PDF文件的渲染和处理可能需要更长时间,但通过一些简单的优化可以保持编辑器的响应性。
仅渲染用户当前查看的页面,而不是加载整个文档。
await renderPage(
currentPage
);重复使用相同的画布,在修改时仅重绘模糊区域。
overlayContext.clearRect(
0,
0,
overlayCanvas.width,
overlayCanvas.height
);
redrawBlurAreas();在最终处理阶段,仅生成用户选择的页面。
for (const page of selectedPages) {
await processPage(page);
}最后,在下载完成后释放临时资源。
URL.revokeObjectURL(
downloadUrl
);这些优化减少了内存使用,使PDF模糊工具即使处理大型多页文档也能流畅运行。
常见错误
一个常见问题是,在考虑当前缩放级别之前就存储了模糊坐标。
在生成最终文档前,始终将预览坐标转换为PDF的坐标系统。
const scaleX =
pdfWidth /
canvas.width;
const scaleY =
pdfHeight /
canvas.height;另一个错误是允许模糊区域超出页面边界。
在处理之前限制这些值。
blurArea.x = Math.max(
0,
blurArea.x
);
blurArea.y = Math.max(
0,
blurArea.y
);用户在下载前还应验证最终预览效果,特别是在不同页面存在多个模糊区域时。
最后请记住,本项目仅对渲染的PDF页面应用视觉模糊效果。如果您的应用需要永久删除敏感内容而非仅视觉遮盖,则需要采用额外的文档脱敏技术。
结论
在本教程中,您使用JavaScript构建了一个基于浏览器的PDF模糊工具。
您学习了如何上传并预览PDF文档、在页面间导航、创建和管理多个模糊区域、调整模糊强度、对选定页面应用模糊效果、使用PDF-lib生成新的PDF文件、预览处理后的文档并下载最终文件——所有操作均无需将数据上传到服务器。
通过结合PDF.js、HTML Canvas API和PDF-lib,您创建了一个专注于隐私的PDF编辑工具,该工具完全在浏览器内部运行。
您可以使用PDF模糊工具探索完整的操作流程。
从这里开始,您可以为该项目添加更多功能,例如可移动和可调整大小的模糊区域、撤销/重做支持、可重复使用的模糊预设、键盘快捷键、触屏设备编辑功能,或更多高级的基于浏览器的PDF编辑注释工具。
AllInOneTools.net创始人 —— 开发简单、免费、无需登录的网络工具,解决日常问题。我专注于实用工具、SEO、提高效率,并公开发布有用的软件。在构建和扩展AllInOneTools的过程中,我根据真实经验进行写作。
如果您读到这里,请感谢作者以表达您的支持。说声谢谢
免费学习编程。freeCodeCamp的开源课程已帮助超过40,000人成为开发者。立即开始
ADVERTISEMENT