Recortar páginas PDF: elimina márgenes y espacios en blanco con JavaScript

2026-09-28 08:34:50 Allen Yang
AI Summarize:
ChatGPT
ChatGPT ✓
Claude ✓
Grok ✓
Perplexity ✓
Quick
Quick
Concise overview
Highlights
Key takeaways
Detailed
Structured explanation
Brief
One sentence summary
Summarize |

Ambas páginas recortadas con un margen de 60 puntos, eliminando el margen blanco exterior y el marco

Los PDF suelen contener más espacio en blanco del que necesitan: documentos escaneados con bordes gruesos, planos de ingeniería con márgenes generosos o facturas en las que solo importa la tabla central. Recortar la página es la solución natural, pero hacerlo en un flujo de trabajo basado en el navegador no es sencillo. Las herramientas de escritorio rompen la experiencia web, y enviar el archivo a un servidor backend plantea problemas de privacidad y cumplimiento.

Aquí es donde entra en juego Spire.PDF for JavaScript. Se ejecuta sobre WebAssembly y opera por completo dentro del navegador, cargando y guardando archivos PDF a través de un sistema de archivos virtual (VFS) sin necesidad de idas y vueltas al servidor. Puede establecer el área visible de cada página mediante programación y permitir que el usuario descargue el resultado recortado, todo del lado del cliente. Para la instalación y la configuración del proyecto, consulte Integrar Spire.PDF for JavaScript en un proyecto de React. Los ejemplos siguientes suponen que Spire.PDF está instalado y que el módulo WebAssembly está inicializado.


CropBox y MediaBox: dos cuadros de página explicados

Cada página de PDF se define mediante dos rectángulos, y comprender la diferencia entre ellos es esencial antes de empezar a recortar.

MediaBox describe las dimensiones físicas de la página, es decir, la hoja de papel completa. Es el límite más externo y define el espacio de coordenadas en el que se coloca todo el contenido. Una página A4 estándar tiene un MediaBox de aproximadamente 595 × 842 puntos.

CropBox define lo que realmente muestra el visor. Es una subregión del MediaBox, y cualquier contenido que quede fuera del CropBox se oculta a la vista. De forma predeterminada, el CropBox coincide con el MediaBox, por lo que normalmente se ve la página completa. Cuando reduce el CropBox, en efecto le está diciendo al lector de PDF: "Muestre solo esta parte de la página."

La clave para el recorte es que el CropBox se deriva del MediaBox. Se leen las dimensiones completas de la página desde page.MediaBox.Width y page.MediaBox.Height, luego se calcula un rectángulo más pequeño, con un margen interior del valor que se desee en cada lado, y se asigna a page.CropBox. Las coordenadas x e y del CropBox se miden desde la esquina superior izquierda de la página, y width y height determinan cuánto de la página se conserva.


Recortar todas las páginas con un margen uniforme

El escenario más común es aplicar la misma reducción de margen a todas las páginas de un documento. Se itera sobre doc.Pages, se lee el MediaBox de cada página y se establece un CropBox con un margen interior de un número fijo de puntos en los cuatro lados.

El ejemplo siguiente recorta 60 puntos de cada borde de cada página, suficiente para eliminar un borde blanco ancho o un marco no deseado:

function App() {
  const cropPdfPage = async () => {
    // Get the Spire.PDF WASM module
    const pdfModule = window.wasmModule?.spirepdf;

    // Check whether the module is ready
    if (!pdfModule) {
      alert('Spire.PDF is not ready yet');
      return;
    }

    // Load the PDF file to be cropped into the VFS
    const inputFileName = 'ToCrop.pdf';
    await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);

    // Create a PdfDocument object and load the PDF document
    let doc = new pdfModule.PdfDocument();
    doc.LoadFromFile(inputFileName);

    // Trim 60 points off every side
    const margin = 60;

    for (let i = 0; i < doc.Pages.Count; i++) {
      const page = doc.Pages.get_Item(i);

      // MediaBox gives the full extent of the page, from which the crop box is derived
      // (x and y are measured from the top-left corner of the page)
      const width = page.MediaBox.Width;
      const height = page.MediaBox.Height;

      page.CropBox = new pdfModule.RectangleF({
        x: margin,
        y: margin,
        width: width - margin * 2,
        height: height - margin * 2,
      });
    }

    const outputFileName = 'CropByMargins.pdf';
    doc.SaveToFile(outputFileName);
    doc.Close();

    // Read the generated file from the VFS and trigger the download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/pdf' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = outputFileName;
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Crop PDF Pages</h1>
      <button onClick={cropPdfPage}>
        Crop PDF
      </button>
    </div>
  );
}

export default App;

Ambas páginas se recortan con un margen de 60 puntos, por lo que se eliminan el margen blanco y el marco que rodea la página:

Ambas páginas recortadas con un margen de 60 puntos, eliminando el margen blanco exterior y el marco

Ajuste el valor de margin para controlar con qué agresividad se recorta la página. Un valor mayor elimina más espacio en blanco; un valor menor realiza un recorte más sutil. Como el margen se aplica de forma uniforme a los cuatro lados, este enfoque funciona mejor cuando el borde no deseado es aproximadamente igual en todos los lados, que es lo habitual en documentos escaneados y planos exportados.


Recortar una sola página o todo el documento

El bucle de la sección anterior aplica el mismo recorte a todas las páginas. Pero CropBox es una propiedad de nivel de página: no existe una interfaz de recorte para todo el documento. El bucle simplemente garantiza que cada página reciba el mismo margen. Esta distinción es importante cuando sus páginas tienen necesidades diferentes.

Cuándo recortar todo el documento: utilice el enfoque con bucle cuando todas las páginas compartan el mismo problema, por ejemplo, un lote escaneado en el que cada página tiene el mismo borde del escáner, o un conjunto de planos de varias páginas exportado con márgenes idénticos. Un único valor de margin mantiene el código sencillo y el resultado coherente.

Cuándo recortar una sola página: elimine el bucle y asigne el CropBox directamente a la página de destino. Esto resulta útil cuando solo una página necesita recorte, por ejemplo, una portada con un logotipo de gran tamaño o una factura en la que solo debe verse la región de la tabla de la página 2. También puede aplicar valores de recorte distintos a páginas distintas combinando lógica por página dentro del bucle.

A continuación se muestra cómo recortar solo la primera página, conservando un bloque de 400 × 500 puntos que comienza en la posición (80, 80) desde la esquina superior izquierda:

// Crop page 1 only: keep a 400 x 500 point block starting at (80, 80) from the top-left corner
const page = doc.Pages.get_Item(0);
page.CropBox = new pdfModule.RectangleF({ x: 80, y: 80, width: 400, height: 500 });

Los valores x e y especifican dónde comienza la región visible, medidos desde la esquina superior izquierda de la página. Los valores width y height definen el tamaño de esa región. Todo lo que quede fuera de este rectángulo se oculta al visor.


Recorte suave: qué ocurre con el contenido

Hay un detalle importante sobre CropBox que es fácil pasar por alto: realiza un recorte suave, no uno duro.

Cuando establece el CropBox, cambia el límite visible de la página: el rectángulo que muestran los visores de PDF y que las impresoras utilizan como área de página. Pero el contenido que queda fuera de este límite no se elimina del archivo. Sigue estando ahí, solo que oculto. Esto tiene dos consecuencias prácticas:

  1. El tamaño del archivo no disminuye. El texto, las imágenes y los gráficos vectoriales recortados permanecen en el flujo de datos del PDF. Si su objetivo es reducir el tamaño del archivo recortando márgenes, establecer solo el CropBox no lo conseguirá.

  2. El contenido recortado sigue siendo buscable. El texto que está fuera del CropBox visible todavía puede encontrarse con las funciones de búsqueda y copiarse por usuarios que sepan cómo seleccionar más allá del área visible. Por lo general, esto no supone un problema al recortar márgenes, pero significa que el recorte no es una forma de censurar ni de eliminar de manera segura información confidencial.

Si necesita eliminar realmente el contenido —para censurarlo, reducir el tamaño del archivo o asegurarse de que el texto oculto no pueda recuperarse—, debe reconstruir la página. El enfoque consiste en crear un documento nuevo, extraer el contenido visible de la página recortada con page.CreateTemplate(), dibujarlo en una página nueva del nuevo documento y guardar el resultado. Esto produce un recorte duro en el que el contenido fuera de los límites ya no existe en el archivo.

No obstante, para la mayoría de los casos de uso de recorte de márgenes y eliminación de espacio en blanco, el recorte suave con CropBox es exactamente lo que se necesita: es rápido, sencillo y produce un resultado visualmente limpio sin la sobrecarga de reconstruir el documento.


Preguntas frecuentes

¿Puedo recortar una sola página en lugar de todo el documento?

Sí. Como CropBox es una propiedad por página, no hay un método integrado para "recortar todo el documento": el bucle del ejemplo principal es solo una comodidad para aplicar el mismo margen a todas las páginas. Para recortar solo una página, omita el bucle y asigne el CropBox directamente a esa página:

// Crop page 1 only: keep a 400 x 500 point block starting at (80, 80) from the top-left corner
const page = doc.Pages.get_Item(0);
page.CropBox = new pdfModule.RectangleF({ x: 80, y: 80, width: 400, height: 500 });

¿Cómo deshago un recorte?

Establecer CropBox modifica el cuadro de página en el lugar, y el documento no almacena el cuadro anterior. Podría esperar que asignar page.MediaBox de nuevo a page.CropBox restaurara la vista original, pero esto no funciona como se pretende: las coordenadas se aplican en relación con el origen del área visible actual, por lo que solo cambian las dimensiones mientras el origen permanece fijo. Después de un recorte de 60 puntos, reasignar las dimensiones del MediaBox sigue dejando el área visible comenzando en (60, 60).

La solución más sencilla es volver a cargar el archivo original si todavía lo tiene. Si solo dispone del archivo recortado, puede desplazar el origen de nuevo a la esquina superior izquierda usando desplazamientos negativos y restaurar las dimensiones completas de la página:

// Undo when the crop offset was (offsetX, offsetY)
page.CropBox = new pdfModule.RectangleF({
  x: -offsetX,
  y: -offsetY,
  width: page.MediaBox.Width,
  height: page.MediaBox.Height,
});

El archivo no se redujo y el contenido recortado sigue siendo buscable, ¿por qué?

Este es el comportamiento esperado. CropBox realiza un recorte suave: solo cambia el límite visible de la página, mientras que el contenido fuera de ese límite permanece en el archivo y todavía puede encontrarse mediante búsquedas de texto u operaciones de copia. Si necesita eliminar físicamente el contenido del PDF, establecer el CropBox no es suficiente: tendría que reconstruir la página creando un documento nuevo, extrayendo el contenido visible con page.CreateTemplate(), dibujándolo en una página nueva y guardando en un archivo nuevo.


Véase también