chartjs-plugin-annotation

Draws lines, boxes, points, labels, polygons, and ellipses on Chart.js charts, with full interactivity.

Library
npm
v3.1.0
623stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
48/100Fair
Development Activity0
Maintenance32
Community72
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
81/100Excellent
Architecture82
Code Quality88
Innovation65
Learning Curve90

chartjs-plugin-annotation is the official annotation plugin for Chart.js 4.x, letting you draw lines, boxes, points, labels, polygons, and ellipses directly on the chart area to call out thresholds, ranges, or events in your data. It works across line, bar, scatter, and bubble charts on linear, logarithmic, time, or category scales, and includes a doughnut-label annotation type for placing text, images, or custom canvas content in the center of doughnut charts.

Annotations are fully scriptable and support click, hover (enter/leave), and drag interaction hooks, plus configurable animations for position and color changes. Because it registers as a standard Chart.js plugin rather than an inline plugin, it can be explicitly registered, unregistered, and reused across multiple chart instances with predictable lifecycle behavior tied into Chart.js’s own update cycle (beforeUpdate, afterDraw, afterDestroy, etc.).

Maintained under the official chartjs GitHub organization, it ships with full TypeScript type definitions, an extensive Karma/Jasmine test suite covering every annotation type, and versioned releases that track specific Chart.js compatibility ranges (v3.x for Chart.js 4.x, v2.x for Chart.js 3.7-3.9, v1.x for Chart.js 3.0-3.6, v0.5.x for Chart.js 2.x).

What You Get

  • Six annotation types — line, box, point, label, polygon, and ellipse — plus a doughnutLabel type for center-of-doughnut content
  • Scriptable options so annotation position, color, and visibility can be computed per-render from chart context
  • Built-in interaction hooks for click, enter, and leave events on individual annotations
  • Configurable per-property animations (numbers and colors) driven by Chart.js’s own animation system
  • Full TypeScript type definitions for all annotation types and plugin options
  • Explicit register/unregister lifecycle so the plugin can be scoped to specific charts rather than applied globally

Common Use Cases

  • Marking a threshold or target value with a horizontal or vertical line annotation on a time-series chart
  • Highlighting a date range or value band with a semi-transparent box annotation
  • Adding clickable label annotations that open detail views when a user interacts with a specific data point
  • Placing summary text or an icon in the center of a doughnut chart using the doughnutLabel type
  • Drawing a polygon or ellipse to circle an outlier cluster of points on a scatter chart

Under The Hood

Architecture The plugin registers itself with Chart.js via Chart.register(Annotation) (src/index.js) and implements the full Chart.js plugin lifecycle in src/annotation.js: beforeInit seeds a per-chart state object in a Map keyed by chart instance, beforeUpdate normalizes the annotations option (accepting either an object keyed by id or a plain array) into a working list, afterDataLimits expands scale ranges to fit annotations via adjustScaleRange, and afterUpdate drives updateListeners, updateElements, and updateHooks each render. Drawing is dispatched through a shared draw() function invoked from beforeDatasetsDraw/afterDatasetsDraw/beforeDraw/afterDraw hooks based on each annotation’s configured drawTime. Per-type behavior (line, box, point, label, polygon, ellipse, doughnutLabel) lives in src/types/*.js, each implementing a shared resolveElementProperties/draw contract that elements.js and annotation.js consume generically, while events.js and interaction.js hit-test the currently visible elements against pointer events to dispatch click/enter/leave callbacks. The state-per-chart-instance design lets the plugin be registered once but safely support many independent chart instances.

Tech Stack Written in plain ES modules ("type": "module") with a chart.js >=4.0.0 peer dependency and no other runtime dependencies, relying on chart.js/helpers for shared utilities. TypeScript consumers get hand-written .d.ts declarations under types/, type-checked via a dedicated tsconfig in types/tests/. Builds run through Rollup (rollup.config.js plus @rollup/plugin-json, @rollup/plugin-node-resolve, @rollup/plugin-terser) producing CJS, ESM, and minified browser bundles. Tests run in real browsers via Karma + Jasmine (with Chrome/Firefox launchers and a Rollup preprocessor for bundling specs), supplemented by a separate Mocha-driven integration suite and pixelmatch for pixel-level comparisons. Documentation is built with VuePress plus TypeDoc-extracted API references.

Code Quality The test/ directory contains 246 files including dedicated spec files per annotation type (line, box, point, label, polygon, ellipse, doughnutLabel) plus animation, events, hooks, and helpers specs — indicating deliberate per-feature coverage rather than a handful of smoke tests. A separate test/integration/ suite runs under Mocha with full stack traces enabled. ESLint extends the shared eslint-config-chartjs style guide plus plugin:es/no-new-in-es2019 and markdown-embedded-code linting, and the TypeScript types are both lint-checked and type-checked independently. GitHub Actions CI runs the full suite on every push, with separate workflows for npm publishing, release drafting, documentation builds, and bundle-size tracking. JSDoc typedef comments annotate function signatures throughout the plain-JS source, giving IDE-level type hints even outside the .d.ts files.

API Design The public surface is entirely declarative: annotations are plain objects (or an array of them) under options.plugins.annotation.annotations, requiring only a one-time Chart.register() call with no imperative setup. Any option can be scriptable — a function resolved against chart/element context at render time — letting consumers compute annotation position, color, or visibility dynamically without touching Chart.js’s lower-level element APIs. Interaction callbacks (click, enter, leave) are defined inline on each annotation object rather than requiring manual canvas event-listener wiring. This closely mirrors Chart.js’s own configuration idioms — consistent and low-boilerplate for anyone already familiar with Chart.js options, though the per-type option surface (seven distinct annotation shapes) takes some reference-doc lookups to master, and annotation changes still require an explicit chart.update() call, matching Chart.js’s broader reactivity model rather than offering something more automatic.

Used by 7 apps in this directory

Python
90%
Apache 2.0

Apache Airflow

Data Engineering

46,755

Define, schedule, and monitor complex data workflows as Python code — with a powerful UI, 80+ provider integrations, and battle-tested scalability across thousands of production deployments.

View details
96
Repo Health
89
Technical
64
Dependency
Built with
Python90%
Updated yesterday
Go
85%
Apache 2.0

Argo Workflows

Devops · Data Engineering

16,956

The most popular Kubernetes-native workflow engine for orchestrating containerized DAGs, ML pipelines, CI/CD, and parallel batch jobs at scale.

View details
96
Repo Health
90
Technical
67
Dependency
Built with
Go85%
TypeScript11%
Updated yesterday
Go
91%
Apache 2.0

Gatus

Monitoring · Devops

12,009

Developer-oriented health dashboard with active endpoint probing, multi-protocol checks, and 40+ alerting integrations so you know about failures before your users do.

View details
78
Repo Health
84
Technical
75
Dependency
Built with
Go91%
Updated 1 weeks ago
TypeScript
76%
AGPL 3.0

Ghostfolio

Invoicing Finance

9,252

Track your stocks, ETFs, and crypto with a privacy-first, self-hostable wealth management platform built for data-driven investors.

View details
93
Repo Health
79
Technical
67
Dependency
Built with
TypeScript76%
HTML21%
Updated yesterday
Python
54%
Other

PostHog

Analytics · Monitoring · Developer Tools

39,612

The all-in-one open source product platform combining analytics, session replay, feature flags, error tracking, AI observability, and a built-in data warehouse in a single self-hostable stack.

View details
92
Repo Health
80
Technical
65
Dependency
Built with
Python54%
TypeScript36%
Updated today
TypeScript
50%
Other

SigNoz

Monitoring · Analytics

32,028

Self-host your entire observability stack — logs, metrics, traces, and LLM monitoring — in one OpenTelemetry-native platform, without the Datadog bill.

View details
92
Repo Health
83
Technical
67
Dependency
Built with
TypeScript50%
Go39%
Updated today
TypeScript
97%
Apache 2.0

Unleash

Developer Tools · Devops · Ab Testing Experimentation

13,787

The open-source feature management platform that lets you ship code to production and control who sees it — without redeploying.

View details
91
Repo Health
84
Technical
70
Dependency
Built with
TypeScript97%
Updated today

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search