Skip to main content Home Creators johnnuwan eva_core d3-js
d3-js D3.js (Data-Driven Documents) : bibliothèque JavaScript de visualisation de données par manipulation directe du DOM — SVG, Canvas, transitions, force layout, géo, hiérarchies, échelles, axes, brush, zoom, drag.
Jump to install Skills Marketplace Discover and explore AI skills built by the community.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Copy promptShow prompt details A direct command skips the review prompt. Inspect the source before running it.
npx skills add https://github.com/JohnNuwan/EVA_CORE --skill d3-jsThe command stays on one line. Scroll horizontally to inspect it before copying.
Prefer a local copy? Download the files currently available to SkillsMP.
Download Zip Downloading... More from this repository
Related occupations SOC
Based on SOC occupation classification
name d3-js description D3.js (Data-Driven Documents) : bibliothèque JavaScript de visualisation de données par manipulation directe du DOM — SVG, Canvas, transitions, force layout, géo, hiérarchies, échelles, axes, brush, zoom, drag. version 1.0.0 author EVA license Privée EVA platforms ["linux","macos","windows"] metadata {"EVA":{"tags":["d3","d3js","data-visualization","svg","javascript","dataviz","interactive-viz","web"],"homepage":"https://d3js.org/","related_skills":["observable","chart-js","plotly","dashboard-design"]}} prerequisites {"commands":["node","npm"],"npm_packages":["d3"]}
Compétence D3.js — Visualisation de Données par Manipulation du DOM
Vue d'ensemble
D3.js (Data-Driven Documents) est la bibliothèque de référence pour les visualisations de données sur le web. Contrairement aux librairies "boîte noire" (Chart.js, Highcharts), D3 opère directement sur le DOM : l'utilisateur manipule des éléments SVG/Canvas en liant des données, ce qui offre un contrôle total sur chaque pixel de la visualisation.
Philosophie D3 : "Penser en données, dessiner en DOM."
Points forts : flexibilité totale, SVG/Canvas/WebGL, animations fluides, écosystème riche (geo, hiérarchies, réseaux, layouts).
Points faibles : courbe d'apprentissage raide, pas de graphiques prêts à l'emploi, verbose pour des charts simples.
Quand l'utiliser
Activez cette compétence lorsque l'utilisateur :
Veut créer une visualisation de données interactive pour le web.
A besoin d'un contrôle pixel-parfait sur l'apparence d'un graphique.
Souhaite des animations de transition entre états de données.
Travaille sur des visualisations géospatiales (carte choroplèthe, projections).
Veut des graphiques en réseau, arbres, treemaps, sunbursts.
A besoin d'interactions avancées : zoom, brush, drag, tooltips personnalisés.
Prérequis
npm install d3
1. Sélections et Liaison de Données (Data Join)
1.1 Le Pattern d'Entrée-Sortie (Enter/Update/Exit)
const data = [10 , 25 , 50 , 75 , 100 ];
const circles = d3.select ("svg" )
.selectAll ("circle" )
.data (data);
circles.enter ()
.append ("circle" )
.attr ("r" , d)
. ( , i * + )
. ( , )
. ( , );
circles. ( , d);
circles. (). ();
d =>
attr
"cx"
(d, i ) =>
100
50
attr
"cy"
100
attr
"fill"
"steelblue"
attr
"r"
d =>
exit
remove
1.2 La Méthode Générale .join() (D3 v7+) svg.selectAll ("circle" )
.data (data)
.join ("circle" )
.attr ("r" , d => d)
.attr ("cx" , (d, i ) => i * 100 + 50 )
.attr ("cy" , 100 )
.attr ("fill" , "steelblue" );
2. Échelles (Scales) Les échelles transforment le domaine des données en plage visuelle.
const xScale = d3.scaleLinear ()
.domain ([0 , 100 ])
.range ([0 , 800 ]);
const timeScale = d3.scaleTime ()
.domain ([new Date ("2024-01-01" ), new Date ("2024-12-31" )])
.range ([0 , 800 ]);
const colorScale = d3.scaleOrdinal ()
.domain (["A" , "B" , "C" ])
.range (d3.schemeCategory10 );
const tempScale = d3.scaleSequential ()
.domain ([20 , 100 ])
.interpolator (d3.interpolateReds );
const logScale = d3.scaleLog ()
.domain ([1 , 1000 ])
.range ([0 , 800 ]);
const thresholdScale = d3.scaleThreshold ()
.domain ([50 , 75 , 90 ])
.range (["#e74c3c" , "#f39c12" , "#2ecc71" , "#27ae60" ]);
3. Axes (Axes) const svg = d3.select ("svg" );
const margin = { top : 20 , right : 30 , bottom : 40 , left : 50 };
const width = 800 - margin.left - margin.right ;
const height = 400 - margin.top - margin.bottom ;
const g = svg.append ("g" )
.attr ("transform" , `translate(${margin.left} ,${margin.top} )` );
const xScale = d3.scaleLinear ().domain ([0 , 100 ]).range ([0 , width]);
const yScale = d3.scaleLinear ().domain ([0 , 100 ]).range ([height, 0 ]);
g.append ("g" )
.attr ("transform" , `translate(0,${height} )` )
.call (d3.axisBottom (xScale))
.selectAll ("text" )
.attr ("transform" , "rotate(-45)" )
.style ("text-anchor" , "end" );
g.append ("g" )
.call (d3.axisLeft (yScale));
g.append ("g" )
.call (d3.axisLeft (yScale)
.ticks (10 )
.tickFormat (d => `${d} %` )
.tickSizeOuter (0 )
);
4. Graphiques Fondamentaux
4.1 Bar Chart const data = [
{ name : "A" , value : 30 },
{ name : "B" , value : 80 },
{ name : "C" , value : 45 },
{ name : "D" , value : 60 },
{ name : "E" , value : 20 },
];
const x = d3.scaleBand ()
.domain (data.map (d => d.name ))
.range ([0 , width])
.padding (0.1 );
const y = d3.scaleLinear ()
.domain ([0 , d3.max (data, d => d.value )])
.range ([height, 0 ]);
g.selectAll ("rect" )
.data (data)
.join ("rect" )
.attr ("x" , d => x (d.name ))
.attr ("y" , d => y (d.value ))
.attr ("width" , x.bandwidth ())
.attr ("height" , d => height - y (d.value ))
.attr ("fill" , "steelblue" );
4.2 Line Chart (Série Temporelle) const line = d3.line ()
.x (d => x (d.date ))
.y (d => y (d.value ))
.curve (d3.curveMonotoneX );
g.append ("path" )
.datum (data)
.attr ("fill" , "none" )
.attr ("stroke" , "steelblue" )
.attr ("stroke-width" , 2 )
.attr ("d" , line);
const area = d3.area ()
.x (d => x (d.date ))
.y0 (y (0 ))
.y1 (d => y (d.value ))
.curve (d3.curveMonotoneX );
g.append ("path" )
.datum (data)
.attr ("fill" , "steelblue" )
.attr ("fill-opacity" , 0.1 )
.attr ("d" , area);
4.3 Scatter Plot g.selectAll ("circle" )
.data (data)
.join ("circle" )
.attr ("cx" , d => x (d.x ))
.attr ("cy" , d => y (d.y ))
.attr ("r" , d => d.r || 5 )
.attr ("fill" , d => colorScale (d.category ))
.attr ("opacity" , 0.7 );
4.4 Pie / Donut Chart const pie = d3.pie ().value (d => d.value );
const arc = d3.arc ().innerRadius (0 ).outerRadius (200 );
const donutArc = d3.arc ().innerRadius (80 ).outerRadius (200 );
const arcs = g.selectAll ("path" )
.data (pie (data))
.join ("path" )
.attr ("d" , donutArc)
.attr ("fill" , d => colorScale (d.data .name ))
.attr ("stroke" , "white" )
.attr ("stroke-width" , 2 );
5. Animations et Transitions
g.selectAll ("rect" )
.data (newData)
.join ("rect" )
.transition ()
.duration (800 )
.delay ((d, i ) => i * 50 )
.ease (d3.easeElasticOut )
.attr ("height" , d => height - y (d.value ))
.attr ("y" , d => y (d.value ));
g.selectAll ("rect" )
.data (data)
.join ("rect" )
.attr ("y" , height)
.attr ("height" , 0 )
.transition ()
.duration (600 )
.delay ((d, i ) => i * 30 )
.ease (d3.easeBounceOut )
.attr ("y" , d => y (d.value ))
.attr ("height" , d => height - y (d.value ));
g.selectAll ("circle" )
.transition ()
.duration (1000 )
.attrTween ("cx" , d => {
const interpolate = d3.interpolate (0 , x (d.x ));
return t => interpolate (t);
});
6. Interactions
6.1 Tooltip const tooltip = d3.select ("body" )
.append ("div" )
.attr ("class" , "tooltip" )
.style ("position" , "absolute" )
.style ("background" , "rgba(0,0,0,0.8)" )
.style ("color" , "white" )
.style ("padding" , "8px 12px" )
.style ("border-radius" , "4px" )
.style ("font-size" , "14px" )
.style ("pointer-events" , "none" )
.style ("opacity" , 0 );
g.selectAll ("circle" )
.on ("mouseenter" , (event, d ) => {
tooltip.transition ().duration (200 ).style ("opacity" , 0.9 );
tooltip.html (`<strong>${d.name} </strong><br>Valeur : ${d.value} ` )
.style ("left" , `${event.pageX + 10 } px` )
.style ("top" , `${event.pageY - 28 } px` );
})
.on ("mouseleave" , () => {
tooltip.transition ().duration (500 ).style ("opacity" , 0 );
});
6.2 Zoom & Pan const zoom = d3.zoom ()
.scaleExtent ([0.5 , 10 ])
.translateExtent ([[0 , 0 ], [width, height]])
.on ("zoom" , (event ) => {
g.attr ("transform" , event.transform );
});
svg.call (zoom);
svg.call (zoom.transform , d3.zoomIdentity .translate (200 , 100 ).scale (2 ));
6.3 Brush (Sélection par Rectangle) const brush = d3.brush ()
.extent ([[0 , 0 ], [width, height]])
.on ("end" , (event ) => {
if (!event.selection ) return ;
const [[x0, y0], [x1, y1]] = event.selection ;
const selected = data.filter (d =>
x (d.x ) >= x0 && x (d.x ) <= x1 && y (d.y ) >= y0 && y (d.y ) <= y1
);
console .log ("Points sélectionnés :" , selected);
});
g.append ("g" ).call (brush);
6.4 Drag (Déplacement) const drag = d3.drag ()
.on ("start" , (event, d ) => {
d.fx = d.x ; d.fy = d.y ;
})
.on ("drag" , (event, d ) => {
d.fx = event.x ; d.fy = event.y ;
redraw ();
})
.on ("end" , (event, d ) => {
d.fx = null ; d.fy = null ;
});
g.selectAll ("circle" ).call (drag);
7. Layouts Avancés
7.1 Force Layout (Graphes / Réseaux) const simulation = d3.forceSimulation (nodes)
.force ("link" , d3.forceLink (links).id (d => d.id ).distance (100 ))
.force ("charge" , d3.forceManyBody ().strength (-300 ))
.force ("center" , d3.forceCenter (width / 2 , height / 2 ))
.force ("collision" , d3.forceCollide (30 ))
.on ("tick" , ticked);
function ticked ( ) {
link.attr ("x1" , d => d.source .x )
.attr ("y1" , d => d.source .y )
.attr ("x2" , d => d.target .x )
.attr ("y2" , d => d.target .y );
node.attr ("cx" , d => d.x )
.attr ("cy" , d => d.y );
}
7.2 Treemap const root = d3.hierarchy (data).sum (d => d.value );
d3.treemap ()
.size ([width, height])
.padding (2 )
.round (true )(root);
const cells = g.selectAll ("rect" )
.data (root.leaves ())
.join ("rect" )
.attr ("x" , d => d.x0 )
.attr ("y" , d => d.y0 )
.attr ("width" , d => d.x1 - d.x0 )
.attr ("height" , d => d.y1 - d.y0 )
.attr ("fill" , d => colorScale (d.parent .data .name ));
7.3 Sunburst / Partition const root = d3.hierarchy (data).sum (d => d.value );
d3.partition ()
.size ([2 * Math .PI , radius])(root);
const arcs = g.selectAll ("path" )
.data (root.descendants ())
.join ("path" )
.attr ("d" , d3.arc ()
.startAngle (d => d.x0 )
.endAngle (d => d.x1 )
.innerRadius (d => d.y0 )
.outerRadius (d => d.y1 )
)
.attr ("fill" , d => colorScale (d.depth ));
7.4 Sankey (Diagramme de Flux) const sankey = d3.sankey ()
.nodeWidth (20 )
.nodePadding (10 )
.extent ([[0 , 0 ], [width, height]]);
const { nodes, links } = sankey ({
nodes : [...],
links : [...]
});
g.selectAll ("path" )
.data (links)
.join ("path" )
.attr ("d" , d3.sankeyLinkHorizontal ())
.attr ("fill" , "none" )
.attr ("stroke" , d => d.color )
.attr ("stroke-width" , d => d.width )
.attr ("opacity" , 0.4 );
8. Cartographie (Geo)
const projection = d3.geoMercator ()
.fitSize ([width, height], geojson);
const path = d3.geoPath ().projection (projection);
g.selectAll ("path" )
.data (topojson.feature (world, world.objects .countries ).features )
.join ("path" )
.attr ("d" , path)
.attr ("fill" , "#ddd" )
.attr ("stroke" , "#fff" )
.attr ("stroke-width" , 0.5 );
g.selectAll ("path" )
.data (geoData)
.join ("path" )
.attr ("d" , path)
.attr ("fill" , d => colorScale (d.properties .value ))
.attr ("stroke" , "#fff" );
const projections = {
equirectangular : d3.geoEquirectangular (),
albers : d3.geoAlbers (),
conicConformal : d3.geoConicConformal (),
orthographic : d3.geoOrthographic (),
stereographic : d3.geoStereographic (),
naturalEarth : d3.geoNaturalEarth1 (),
};
9. Modulaires (Modules D3 Individuels) D3 est modulaire : importez uniquement ce dont vous avez besoin.
import { select, selectAll } from "d3-selection" ;
import { scaleLinear, scaleOrdinal } from "d3-scale" ;
import { line, area } from "d3-shape" ;
import { axisBottom, axisLeft } from "d3-axis" ;
import { transition } from "d3-transition" ;
import { easeElasticOut } from "d3-ease" ;
import { geoMercator, geoPath } from "d3-geo" ;
import * as d3 from "d3" ;
Module Utilité d3-selectionSélection DOM, data join d3-scaleÉchelles (lin, log, time, ordinal, band) d3-shapeLignes, aires, arcs, symboles d3-axisAxes de graphique d3-transitionAnimations, transitions d3-easeFonctions d'easing d3-arrayStatistiques, tris, groupBy d3-formatFormatage de nombres d3-time-formatFormatage de dates d3-geoProjections cartographiques d3-forceSimulation de forces (graphes) d3-hierarchyTreemap, sunburst, dendrogram d3-sankeyDiagrammes de flux Sankey (module externe) d3-brushSélection rectangulaire d3-zoomZoom/Pan d3-dragGlisser-déposer d3-colorManipulation de couleurs d3-interpolateInterpolation de valeurs d3-timerBoucle d'animation requestAnimationFrame
10. Patterns de Performance
const canvas = document .getElementById ("canvas" );
const ctx = canvas.getContext ("2d" );
const render = ( ) => {
ctx.clearRect (0 , 0 , width, height);
data.forEach (d => {
ctx.beginPath ();
ctx.arc (xScale (d.x ), yScale (d.y ), 3 , 0 , Math .PI * 2 );
ctx.fillStyle = colorScale (d.category );
ctx.fill ();
});
};
svg.selectAll ("circle" )
.data (data, d => d.id )
.join ("circle" )
.attr ("cx" , d => x (d.x ));
const xScale = d3.scaleLinear ().domain (...).range (...);
selection.raise ();
selection.lower ();
Pièges Courants (Pitfalls)
Mutation accidentelle des données dans le data join.
Erreur : D3 stocke les données en place sur l'élément DOM via __data__. Modifier d.x dans un callback modifie l'objet original.
Correction : Faites une copie des données si vous devez les transformer : data.map(d => ({...d})).
Axes tronqués ou illisibles.
Erreur : Les étiquettes d'axes débordent du groupe SVG car le margin n'est pas assez large.
Correction : Toujours définir des margin explicites et traduire le groupe conteneur.
Transitions en conflit (torn tearing).
Erreur : Plusieurs transitions sur le même élément s'interrompent mutuellement.
Correction : Utilisez selection.interrupt() avant une nouvelle transition, ou gérez avec selection.transition().on("end", ...).
Force layout infini.
Erreur : La simulation de forces ne converge pas (nœuds qui s'éloignent à l'infini).
Correction : Équilibrer les forces : forceManyBody().strength(-300) + forceCenter() + forceCollide(). Ajuster alphaDecay.
Carte géo incomplète ou déformée.
Erreur : Le fichier TopoJSON/GeoJSON n'est pas correctement lié à la projection.
Correction : Vérifiez que topojson.feature() est bien appelé, et que la projection utilise .fitSize() ou .fitExtent().
Sélecteurs réutilisés sans vidage préalable.
Erreur : Appeler svg.selectAll("circle").data(nouveauxData) sur un SVG qui contient déjà des cercles — les anciens persistent si mal gérés.
Correction : Utiliser le pattern enter/update/exit complet ou .join().
Oubli de la fonction de clé dans le data join.
Erreur : D3 lie par index (pas par identité), ce qui cause des animations incorrectes lors de réorganisations.
Correction : Toujours fournir une fonction de clé : .data(data, d => d.id).
Ressources
Checklist