Cómo trabajar con anotaciones en TypeScript
Esta guía muestra cómo añadir, aplanar y buscar anotaciones PDF con Aspose.PDF FOSS para TypeScript. La clase Page expone un método Add* por subtipo de anotación — marcado (resaltar, subrayar, tachar, ondulado), formas (cuadrado, círculo, línea, polígono, tinta), texto (nota adhesiva, texto libre) y enlaces — cada uno devolviendo un manejador tipado Annotation que puede leerse de nuevo o aplanarse más tarde. Requiere Node.js 22 o posterior.
Guía paso a paso
Paso 1: Instalar el paquete
git clone https://github.com/aspose-pdf-foss/Aspose.PDF-FOSS-for-TypeScript.git
cd Aspose.PDF-FOSS-for-TypeScript
npm install
npm run buildVerifique la instalación importando la clase Document en un nuevo archivo TypeScript — esta línea debería resolverse sin error una vez que el paquete esté instalado:
import { Document } from '@asposefoss/pdf';Paso 2: Importar clases requeridas
Importa Document para abrir el archivo y Page para las firmas de tipo de anotación utilizadas en los pasos siguientes:
import { Document, Page } from '@asposefoss/pdf';Paso 3: Añadir anotaciones de marcado
Page.AddHighlight(), Page.AddUnderline(), Page.AddSquiggly() y Page.AddStrikeOut() aceptan todos una matriz quads — un cuádruple de 8 números (x1,y1,x2,y2,x3,y3,x4,y4) por cada región de texto resaltado — más un color y un contents opcional. La biblioteca genera automáticamente el flujo de apariencia (/AP) para los cuatro subtipos:
import { Document } from '@asposefoss/pdf';
const doc = Document.OpenFile('input.pdf');
const page = doc.Pages[0];
page.AddHighlight({
quads: [72, 700, 300, 700, 72, 685, 300, 685],
color: [1, 1, 0],
contents: 'Yellow highlight',
});
page.AddUnderline({
quads: [72, 660, 300, 660, 72, 645, 300, 645],
color: [0, 0, 1],
});
page.AddStrikeOut({
quads: [72, 620, 300, 620, 72, 605, 300, 605],
color: [1, 0, 0],
});
doc.WriteTo('annotated.pdf');Paso 4: Añadir anotaciones de forma y tinta
Page.AddSquare() y Page.AddCircle() aceptan un rect delimitador más color (trazo) y un fill opcional. Page.AddLine() acepta un line de 4 números (x1,y1,x2,y2) y terminaciones de flecha opcionales. Page.AddInk() acepta paths — una matriz de arreglos planos de pares de puntos, uno por cada trazo de lápiz:
page.AddSquare({ rect: [100, 500, 220, 560], color: [0.8, 0, 0], fill: [1, 1, 0.5], width: 2 });
page.AddCircle({ rect: [250, 500, 370, 560], color: [0, 0.5, 0], width: 2 });
page.AddLine({
line: [100, 470, 370, 470],
color: [0, 0, 0.7],
width: 2,
startEnding: 'OpenArrow',
endEnding: 'ClosedArrow',
});
page.AddInk({
paths: [[100, 400, 130, 430, 160, 390, 190, 420]],
color: [0.6, 0, 0.6],
width: 2,
});Paso 5: Añadir una nota adhesiva y texto libre
Page.AddTextNote() coloca un ícono clicable que abre una ventana emergente de comentario. Page.AddFreeText() dibuja texto directamente en la página dentro de su rect:
page.AddTextNote({
rect: [400, 700, 420, 720],
icon: 'Note',
author: 'Reviewer',
contents: 'This is a sticky-note annotation.',
});
page.AddFreeText({
rect: [400, 600, 550, 660],
contents: 'FreeText sample',
fontSize: 10,
align: 'center',
fill: [1, 1, 0.8],
width: 1,
});Paso 6: Aplanar una anotación en contenido estático
Cada controlador de anotación devuelto por una llamada Add* tiene un método Flatten() que incorpora la apariencia de la anotación en el flujo de contenido de la página y la elimina de /Annots. Después de aplanar no queda nada para hacer clic o editar en un visor:
const note = page.AddFreeText({
rect: [210, 535, 470, 590],
contents: 'Sticky note — flattened into the page.',
fontSize: 11,
align: 'left',
});
note.Flatten(); // -> boolean; bakes the annotation, unwires itself from /Annots
Paso 7: Buscar texto de anotación
Page.SearchAnnotationText() and Page.SearchAnnotations() están disjuntos en ambas direcciones: SearchAnnotationText() coincide con los metadatos de anotación literal (/Contents, /T, /Subj), mientras que SearchAnnotations() coincide con el rendered texto de anotaciones de marcado como FreeText:
const metadataHits = page.SearchAnnotationText('confidential');
for (const hit of metadataHits) {
console.log(hit.key, hit.value); // e.g. 'Contents', 'confidential'
}
const renderedHits = page.SearchAnnotations('confidential');
console.log(renderedHits.length);Problemas comunes y soluciones
Page.AddHighlight() (o otro método de marcado) se dibuja en el lugar equivocado. quads es una matriz plana de 8 números (x1,y1,x2,y2,x3,y3,x4,y4), no es un rect — pasar un rectángulo de 4 números produce un quad degenerado o ausente. Construye un quad por cada línea de texto resaltado.
Una anotación aplanada sigue siendo clicable. Flatten() debe llamarse sobre el objeto devuelto por el Add* llamado, y el documento debe guardarse (doc.WriteTo() / doc.Save()) después de aplanar — el cambio solo existe en memoria hasta que el archivo se escribe de nuevo.
SearchAnnotationText() no devuelve resultados aunque el texto sea visible en la página. Solo busca en los campos de metadatos de la anotación (/Contents, /T, /Subj) — texto de marcado visible generado a partir de la propia apariencia de una anotación (p. ej., una FreeText cuerpo) se encuentra por SearchAnnotations() en su lugar, y tampoco busca contenido de página ordinario (usar Page.GetText() or Page.Search() para eso).
Las marcas de redacción no aparecen al buscar anotaciones. Page.AddRedact() crea un RedactAnnotation, un subtipo distinto de las anotaciones de marcado/forma/texto cubiertas aquí — vea el Redaction guía.
Preguntas frecuentes
¿Cuántos subtipos de anotación admite Page?
La biblioteca genera apariencias para markup (highlight, underline, strikeout, squiggly), shapes (square, circle, line, polygon, ink), text (sticky note, free text), links y stamps — además de anotaciones de file attachment y redaction, que se cubren en sus propias guías prácticas.
¿Puedo leer anotaciones que ya existen en una página?
Sí — Page.Annotations devuelve las anotaciones existentes como una matriz de manejadores tipados que puedes inspeccionar, editar o aplanar, y Page.RemoveAnnotation(a) elimina una.
¿Cuál es la diferencia entre aplanar una anotación y aplicar una redacción?
Flatten() incorpora una anotación appearance en la página y elimina el objeto de anotación, pero cualquier contenido de texto o imagen debajo de ella permanece intacto. ApplyRedactions() reescribe de forma destructiva el flujo de contenido de modo que el contenido cubierto desaparece — vea la guía de Redacción para más detalles.
¿Se conservan las anotaciones a través de un ciclo de guardar/abrir?
Sí — las anotaciones añadidas antes de doc.WriteTo() / doc.Save() se escriben en el PDF y se leen correctamente en el siguiente Document.Open() / Document.OpenFile().