如何在JavaScript中将PDF缩放至Canvas的宽高尺寸?
解决PDF预览无法占满Canvas的问题
问题分析
你的代码存在三个核心问题导致PDF无法占满Canvas:
useEffect依赖数组为空,容器尺寸或PDF文件变化时不会重新渲染预览- 渲染PDF时未对内容做居中对齐,留白集中在一侧,视觉上显得未占满
- Canvas的显示样式未与实际画布尺寸绑定,可能出现尺寸不匹配的情况
修复方案
1. 更新ImagePreview组件代码
以下提供两种适配模式,按需选择:
模式一:保持比例居中显示(无裁剪,完整展示PDF)
这种模式下PDF会完整显示,空白均匀分布在Canvas两侧:
function ImagePreview({ pdf, containerWidth, containerHeight }) { const canvasRef = useRef(null); useEffect(() => { async function init() { try { const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); const uid = await getUserId(); const publicUrl = await supabase.storage.from("pdf-documents").getPublicUrl(uid + "/" + pdf.name).data.publicUrl; // 重置画布内容 ctx.clearRect(0, 0, canvas.width, canvas.height); const pdfDoc = await pdfjsLib.getDocument(publicUrl).promise; const page = await pdfDoc.getPage(1); const viewport = page.getViewport({ scale: 1 }); const canvasWidth = containerWidth; const canvasHeight = containerHeight; // 计算缩放比例(保持PDF比例,适配画布最小边) const scaleX = canvasWidth / viewport.width; const scaleY = canvasHeight / viewport.height; const scale = Math.min(scaleX, scaleY); const newViewport = page.getViewport({ scale }); // 设置画布实际像素尺寸 canvas.width = canvasWidth; canvas.height = canvasHeight; // 计算居中偏移量,让PDF在画布中居中 const offsetX = (canvasWidth - newViewport.width) / 2; const offsetY = (canvasHeight - newViewport.height) / 2; // 平移画布上下文,实现居中渲染 ctx.translate(offsetX, offsetY); await page.render({ canvasContext: ctx, viewport: newViewport, }).promise; // 恢复上下文初始状态 ctx.translate(-offsetX, -offsetY); } catch (error) { console.log(error); } } init(); }, [pdf, containerWidth, containerHeight]); // 添加依赖,参数变化时自动重新渲染 return ( <div> {/* 绑定Canvas显示样式与实际尺寸,消除默认间距 */} <canvas ref={canvasRef} style={{ width: `${containerWidth}px`, height: `${containerHeight}px`, display: "block" }} /> </div> ); }
模式二:铺满Canvas显示(裁剪超出部分,完全占满画布)
这种模式下PDF会填满整个Canvas,超出画布的部分会被裁剪:
仅需修改缩放比例和偏移量计算部分,其余代码与模式一一致:
// ...其他代码不变 // 计算缩放比例(保持PDF比例,覆盖画布最大边) const scaleX = canvasWidth / viewport.width; const scaleY = canvasHeight / viewport.height; const scale = Math.max(scaleX, scaleY); const newViewport = page.getViewport({ scale }); // 计算居中裁剪的偏移量 const offsetX = (canvasWidth - newViewport.width) / 2; const offsetY = (canvasHeight - newViewport.height) / 2; // ...其他代码不变
2. 优化父容器样式
为父div添加overflow: hidden(适配模式二的裁剪需求),并确保容器尺寸与传入的参数一致:
{documents.map((doc) => { return ( <div key={doc.id} className="border-solid border-2 border-sky-500 overflow-hidden" style={{ width: `${110}px`, height: `${130}px` }} > <ImagePreview pdf={doc} containerHeight={130} containerWidth={110}/> </div> ); })}
内容的提问来源于stack exchange,提问作者neil_ruaro
相关产品推荐
相关产品推荐

