Skip to content
Apexify.jsDocs
Apexify.js version v5.4.5

Node / Gif Animation · guide

Watermark & text overlay

Current Apexify.js 6.0.0 documentation for Watermark & text overlay.

apexify.jsRuntime: nodeCURRENTSince 6.0.0

Overlays are applied after the frame raster is drawn onto the GIF output canvas and before encoder.addFrame.


Watermarks

Global and per-frame watermarks use the same GIFWatermarkSpec:

SOURCEtypescript
typescript
Studio
interface GIFWatermarkSpec {  enable?: boolean;  url: string | Buffer | Uint8Array | URL;  x?: number;  y?: number;  opacity?: number; // 0..1  width?: number;  height?: number;  scale?: number;  margin?: number;  position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'center';}

url is a GIFFrameSource, despite the historical field name. It can therefore be local bytes, a path/data image, or a permitted remote URL. Remote watermark sources use Apexify's central network policy and byte limits.

Global watermark

SOURCEtypescript
typescript
Studio
const gif = await painter.createGIF(frames, {  outputFormat: 'buffer',  width: 640,  height: 360,  watermark: {    url: './brand/logo.png',    position: 'bottom-right',    margin: 16,    opacity: 0.8,    scale: 0.6,  },});

The global image is resolved once for the operation and reused through a bounded cache rather than being decoded independently for every frame.

Per-frame watermark

A frame-level watermark replaces the global watermark specification for that frame. enable: false suppresses watermarking for the frame even when a global watermark exists.

SOURCEtypescript
typescript
Studio
const frames = [  { buffer: frameA },  {    buffer: frameB,    watermark: {      url: './brand/alternate.png',      position: 'top-left',      opacity: 0.5,    },  },  { buffer: frameC, watermark: { enable: false, url: './brand/logo.png' } },];

Sizing and placement

  • scale scales both native dimensions and cannot be combined with explicit width/height.
  • width only preserves native aspect ratio while deriving height.
  • height only preserves native aspect ratio while deriving width.
  • both width and height use the explicit dimensions.
  • position defaults to bottom-left.
  • margin defaults to 10 pixels for position-based placement.
  • explicit x / y override the derived position coordinate independently.
  • opacity defaults to 1.

textOverlay uses the main text renderer

Phase 7 no longer uses a hard-coded ${fontSize}px Arial fillText shortcut. GIFOptions.textOverlay is based on the normal TextProperties model and is rendered through EnhancedTextRenderer.

That means GIF text overlays support the same core styling model used by createText, including nested font/fill/layout/placement/effects/decorations, custom font paths, gradients, strokes, shadows/glow, wrapping, rotation, and curved text where the underlying TextProperties feature supports it.

x and y are optional only for the GIF overlay convenience API and default to 10 and 30. fontColor remains a compatibility alias for the text color.

SOURCEtypescript
typescript
Studio
await painter.createGIF(frames, {  outputFormat: 'file',  outputFile: './out/branded.gif',  width: 640,  height: 360,  textOverlay: {    text: 'Apexify.js',    x: 24,    y: 48,    font: { family: 'Arial', size: 28 },    decorations: { bold: true },    fill: { color: '#ffffff' },    effects: {      shadow: { color: '#000000', blur: 4, offsetX: 2, offsetY: 2, opacity: 0.7 },    },  },});

Text-overlay validation uses the same authoritative text-property validation path as other Apexify rendering surfaces.

Next steps