useInkAnnotationCreate

Returns a function that creates an ink annotation (a freehand drawing made of one or more paths) on a page and resolves with its snapshot.

const createInkAnnotation = useInkAnnotationCreate()

const inkAnnotation = await createInkAnnotation({ pageId, ...inkAnnotationProps })

The input is the pageId plus every field of InkAnnotationProps:

PropTypeMeaning
x, y, width, heightnumberThe box the paths run through, in user space (origin at the bottom-left corner of the page). The stroke extends beyond it by half borderWidth.
inkListnumber[][]The paths, each a flat array [x1, y1, x2, y2, ...] of at least two points. Coordinates are fractions of the box, described below.
borderColorColorStringThe stroke color, such as 'rgba(255,0,0,1)'. The stroke opacity is carried in the alpha channel.
borderWidthnumberThe stroke width in user-space units.
lineCapLineCapStyleThe shape of the path ends: 'butt', 'round', or 'square'.
blendModeBlendModeHow the strokes composite over the page: 'Normal', or a PDF blend mode such as 'Multiply' for a highlighter.

The x, y, width, and height fields form the AnnotationGeometry type shared by annotations, and borderColor and borderWidth form AnnotationBorderStyle, shared by the annotations that paint a border or a stroke.

BlendMode is one of 'Normal', 'Compatible', 'Multiply', 'Screen', 'Overlay', 'Darken', 'Lighten', 'ColorDodge', 'ColorBurn', 'HardLight', 'SoftLight', 'Difference', 'Exclusion', 'Hue', 'Saturation', 'Color', or 'Luminosity'.

Path coordinates

Each inkList coordinate is a fraction of the box: 0 at its left or bottom edge, 1 at its right or top edge, with the y axis pointing up as in user space. The box is the bounds of the paths, so across all paths the coordinates span exactly from 0 to 1 on each axis. On an axis where the box has zero size, such as the height of a horizontal stroke, every coordinate is 0. Storing the paths relative to the box lets the annotation move and resize by changing the box alone.

Behavior

  • The resolved value is an InkAnnotation snapshot: the input fields plus id, type: 'annotation', and subtype: 'Ink'. The id is session-scoped: don't store it across page reloads.
  • The function is asynchronous because the target page may not be loaded yet.
  • An unknown pageId, an empty inkList, a path with fewer than two points or an odd number of coordinates, or paths that don't span the box throw InvalidInputError. With no document loaded, the call throws DocumentNotLoadedError.

Example

import { useInkAnnotationCreate } from '@sdk-pdf/react'

// Draws a stroke through user-space points, such as the ones captured from a pointer.
function useDrawStroke() {
  const createInkAnnotation = useInkAnnotationCreate()

  return (pageId: string, points: { x: number; y: number }[]) => {
    const xs = points.map((point) => point.x)
    const ys = points.map((point) => point.y)
    const x = Math.min(...xs)
    const y = Math.min(...ys)
    const width = Math.max(...xs) - x
    const height = Math.max(...ys) - y

    // Express each point as a fraction of the box; a zero-size axis maps to 0.
    const path = points.flatMap((point) => [
      width ? (point.x - x) / width : 0,
      height ? (point.y - y) / height : 0,
    ])

    return createInkAnnotation({
      pageId,
      x,
      y,
      width,
      height,
      inkList: [path],
      borderColor: 'rgba(0,0,255,1)',
      borderWidth: 2,
      lineCap: 'round',
      blendMode: 'Normal',
    })
  }
}

The created annotation appears in useSelectedBlocks when selected, and its border can be changed with useSelectionAnnotationProps. To delete it, see useBlockDelete.

On this page