Introduction
D3.js reste en 2026 la librairie de référence pour les visualisations de données hautement personnalisées. Contrairement aux frameworks haut niveau, D3 vous donne un contrôle total sur le DOM et le SVG. Ce tutoriel expert vous guide à travers la création d'une visualisation interactive complète avec gestion des données dynamiques, animations performantes et simulations physiques.
Prérequis
- Node.js 20+ et TypeScript 5.5+
- Connaissances solides en JavaScript moderne et SVG
- D3.js v7 installé
- Un éditeur avec support TypeScript
Initialisation du projet
npm init -y
npm install d3 @types/d3
npm install -D typescript viteNous initialisons un projet Vite pour le développement moderne et installons D3.js v7 avec ses types TypeScript officiels.
Configuration TypeScript
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
}
}Configuration stricte TypeScript optimisée pour D3.js afin de bénéficier de l'inférence de types sur les sélections et les données.
Création du conteneur SVG
import * as d3 from 'd3';
const width = 800;
const height = 600;
const svg = d3.select('#app')
.append('svg')
.attr('width', width)
.attr('height', height)
.attr('viewBox', `0 0 ${width} ${height}`);Création d'un SVG responsive avec viewBox. Toujours utiliser viewBox pour garantir l'adaptabilité sur tous les écrans.
Liaison de données et échelles
interface DataPoint { x: number; y: number; value: number; }
const data: DataPoint[] = [
{ x: 10, y: 20, value: 45 },
{ x: 30, y: 50, value: 78 },
{ x: 60, y: 30, value: 92 }
];
const xScale = d3.scaleLinear()
.domain(d3.extent(data, d => d.x) as [number, number])
.range([50, width - 50]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)!])
.range([height - 50, 50]);Utilisation d'échelles linéaires avec calcul automatique du domaine via d3.extent. Toujours typer vos données pour éviter les erreurs runtime.
Ajout des cercles avec transitions
svg.selectAll('circle')
.data(data)
.join('circle')
.attr('cx', d => xScale(d.x))
.attr('cy', d => yScale(d.y))
.attr('r', 0)
.attr('fill', '#3b82f6')
.transition()
.duration(800)
.ease(d3.easeBounceOut)
.attr('r', d => Math.sqrt(d.value) * 1.5);Pattern .join() moderne et transition avec ease personnalisé. Les transitions D3 sont performantes car elles utilisent requestAnimationFrame.
Bonnes pratiques
- Toujours typer vos interfaces de données pour bénéficier de l'auto-complétion
- Utiliser .join() plutôt que .enter()/.exit() pour un code plus concis
- Préférer les transitions courtes (600-900ms) avec ease approprié
- Nettoyer les écouteurs d'événements lors du démontage du composant
- Mesurer les performances avec les DevTools avant d'ajouter trop d'éléments
Erreurs courantes à éviter
- Oublier de gérer les valeurs null dans les domaines d'échelles
- Utiliser des sélecteurs CSS trop génériques qui cassent le scoping
- Appliquer des transitions sur des milliers d'éléments sans throttling
- Négliger l'accessibilité (aria-labels sur les éléments SVG)
Pour aller plus loin
Approfondissez les simulations de force et les layouts hiérarchiques dans notre formation complète : Formations Learni.