D3 SVG Annotation

raw JSON →
2.5.1 verified Thu Apr 23 auth: no javascript

d3-svg-annotation is a D3.js module designed to streamline the process of adding various types of annotations to SVG-based data visualizations. It provides a flexible API for creating notes, connectors, and subjects directly on a D3-rendered chart, offering configurable styling, text wrapping, and dynamic positioning. The current stable version is 2.5.1. The package maintains a release cadence focused on addressing bugs and implementing minor feature enhancements, with significant breaking changes typically reserved for major version bumps. Its primary differentiation lies in its tight integration with the D3 ecosystem, providing a programmatic way to add rich context and explanations to complex charts without needing separate HTML overlays or manual SVG manipulation.

error TypeError: d3.annotation is not a function
cause The D3 library was not loaded or not correctly exposed globally before `d3-svg-annotation` was initialized, or `annotation` was not imported as a named export in an ES module environment.
fix
For script tags, ensure D3 loads first. For modules, use import { annotation } from 'd3-svg-annotation'; and ensure d3 is also imported or globally available.
error Property 'notePadding' does not exist on type 'Omit<Annotation, "type">'
cause This TypeScript error indicates that you are attempting to use the `notePadding` property with a version of `d3-svg-annotation` where its type definition is missing or incorrect.
fix
Update d3-svg-annotation to version 2.3.2 or higher to resolve the missing type definition for notePadding.
error Annotation note label not visible or improperly wrapped, especially with leading whitespace.
cause Earlier versions (prior to v1.17.0) had a bug where note labels starting with whitespace would not display correctly or would be omitted during word wrapping.
fix
Upgrade d3-svg-annotation to version 1.17.0 or later to fix issues related to note label display and whitespace handling.
breaking Starting with v2.0.0, the `d3-annotation.css` stylesheet is no longer required or supported. Default styling is now built directly into the library, and custom styling can be applied programmatically using the `color` property or standard CSS overrides.
fix Remove any `<link>` tags or `@import` statements referencing `d3-annotation.css` when upgrading to v2.x. Adjust custom styling to use the library's API or direct CSS for SVG elements.
gotcha TypeScript users on versions prior to 2.3.2 may encounter missing type definitions or incorrect IntelliSense for the `notePadding` property, particularly when configuring note objects within annotations.
fix Upgrade to `d3-svg-annotation@2.3.2` or later to ensure complete and correct TypeScript type definitions for `notePadding`.
gotcha When using the minified or unminified JavaScript file directly (e.g., from CDN or local file inclusion), ensure that the D3 library is loaded *before* `d3-svg-annotation`. The library expects `d3` to be globally available.
fix Verify the script loading order in your HTML: `<script src="path/to/d3.min.js"></script><script src="path/to/d3-annotation.min.js"></script>`.
gotcha Prior to v1.14.0, the build included D3 dependency files within `d3-annotation` itself. From v1.14.0 onwards, `d3-annotation` is 'slimmed down' and expects D3 to be provided by the consumer, aligning with other D3 modules.
fix Always ensure D3 is a separate dependency and loaded correctly when using versions 1.14.0 or newer. This is typically handled automatically by bundlers like Webpack or Rollup when using NPM imports.
npm install d3-svg-annotation
yarn add d3-svg-annotation
pnpm add d3-svg-annotation

This example demonstrates how to set up a basic D3 SVG container, define annotation data points, configure the annotation generator, and render two different types of annotations on the SVG.

import * as d3 from 'd3';
import { annotation } from 'd3-svg-annotation';

const margin = { top: 20, right: 20, bottom: 30, left: 40 };
const width = 600 - margin.left - margin.right;
const height = 400 - margin.top - margin.bottom;

const svg = d3.select('body').append('svg')
  .attr('width', width + margin.left + margin.right)
  .attr('height', height + margin.top + margin.bottom)
  .append('g')
  .attr('transform', `translate(${margin.left},${margin.top})`);

const annotations = [
  {
    note: { label: "An interesting data point", title: "Point A" },
    x: 100,
    y: 150,
    dy: 30,
    dx: 30,
    subject: { radius: 10, radiusPadding: 5 },
    color: "#E8336D"
  },
  {
    note: { label: "This is another observation.", title: "Point B", align: "left" },
    x: 450,
    y: 100,
    dy: -50,
    dx: -60,
    subject: { width: 50, height: 20 },
    type: annotation.annotationCalloutRect,
    color: "#007bff"
  }
];

const makeAnnotations = annotation()
  .type(annotation.annotationLabel)
  .annotations(annotations);

svg
  .append('g')
  .attr('class', 'annotation-group')
  .call(makeAnnotations);

// Add some basic styling for visibility
d3.select('body').append('style').text(`
  .annotation-group path {
    stroke-linejoin: round;
    stroke-linecap: round;
  }
  .annotation-group text {
    font-family: sans-serif;
    font-size: 12px;
  }
  .annotation-note-label {
    fill: currentColor;
  }
`);